/*******************************************************************************
* Copyright 2011, 2012, 2013 fanfou.com, Xiaoke, Zhang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.fanfou.app.opensource.ui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.fanfou.app.opensource.AppContext;
import com.fanfou.app.opensource.R;
/**
* @author mcxiaoke
*
*/
public class EndlessListView extends ListView implements OnItemClickListener {
public interface OnRefreshListener {
public void onItemClick(ListView view, View row, int position);
public void onLoadMore(ListView view);
public void onRefresh(ListView view);
}
private static final String TAG = EndlessListView.class.getSimpleName();
protected static final int FOOTER_NONE = 0;
protected static final int FOOTER_HIDE = 1;
protected static final int FOOTER_NORMAL = 2;
protected static final int FOOTER_LOADING = 3;
protected static final int HEADER_NONE = 10;
protected static final int HEADER_HIDE = 11;
protected static final int HEADER_NORMAL = 12;
protected static final int HEADER_LOADING = 13;
protected static final int MAX_OVERSCROLL_Y = 240;
Context mContext;
LayoutInflater mInflater;
ViewGroup mRefershView;
ProgressBar mRefreshProgressView;
TextView mRefreshTextView;
ViewGroup mLoadMoreView;
ProgressBar mLoadMoreProgressView;
// protected int mScrollState;
// protected int mFirstVisible;
// protected int mLastFirstVisible;
// protected int mVisibleItemCount;
// protected int mTotalItemCount;
// protected int mMaxOverScrollY;
TextView mLoadMoreTextView;
OnRefreshListener mOnRefreshListener;
protected boolean isLoading;
protected boolean isRefresh;
public EndlessListView(final Context context) {
super(context);
init(context);
}
public EndlessListView(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void addFooter() {
if (noFooter()) {
addFooterView(this.mLoadMoreView);
}
}
public void addHeader() {
if (noHeader()) {
addHeaderView(this.mRefershView);
}
}
private void init(final Context context) {
this.mContext = context;
setHorizontalScrollBarEnabled(false);
setVerticalScrollBarEnabled(false);
setOnItemClickListener(this);
setCacheColorHint(0);
setSelector(getResources().getDrawable(R.drawable.list_selector));
setDivider(getResources().getDrawable(R.drawable.separator));
initHeaderAndFooter();
}
private void initHeaderAndFooter() {
this.mInflater = LayoutInflater.from(this.mContext);
this.mRefershView = (ViewGroup) this.mInflater.inflate(
R.layout.list_header, null);
this.mRefreshProgressView = (ProgressBar) this.mRefershView
.findViewById(R.id.list_header_progress);
this.mRefreshTextView = (TextView) this.mRefershView
.findViewById(R.id.list_header_text);
addHeaderView(this.mRefershView);
this.mLoadMoreView = (ViewGroup) this.mInflater.inflate(
R.layout.list_footer, null);
this.mLoadMoreProgressView = (ProgressBar) this.mLoadMoreView
.findViewById(R.id.list_footer_progress);
this.mLoadMoreTextView = (TextView) this.mLoadMoreView
.findViewById(R.id.list_footer_text);
addFooterView(this.mLoadMoreView);
}
public boolean isLoading() {
return this.isLoading;
}
public boolean isRefreshing() {
return this.isRefresh;
}
void log(final String message) {
Log.d(EndlessListView.TAG, message);
}
public boolean noFooter() {
return getFooterViewsCount() == 0;
}
public boolean noHeader() {
return getHeaderViewsCount() == 0;
}
@Override
public void onItemClick(final AdapterView<?> parent, final View view,
final int position, final long id) {
if (AppContext.DEBUG) {
log("onItemClick() list.size=" + parent.getCount()
+ " adapter.size=" + parent.getAdapter().getCount()
+ " position=" + position + " id=" + id);
}
final Object o = parent.getItemAtPosition(position);
if (o == null) {
if (position == 0) {
setRefreshing();
} else if (position == (parent.getCount() - 1)) {
setLoading();
}
} else {
if (this.mOnRefreshListener != null) {
this.mOnRefreshListener.onItemClick(this, view, position);
}
}
}
public void onLoadMoreComplete() {
if (AppContext.DEBUG) {
log("onLoadMoreComplete()");
}
setFooterStatus(EndlessListView.FOOTER_NORMAL);
}
public void onNoLoadMore() {
setFooterStatus(EndlessListView.FOOTER_NONE);
}
public void onNoRefresh() {
setHeaderStatus(EndlessListView.HEADER_NONE);
}
public void onRefreshComplete() {
if (this.isRefresh) {
if (AppContext.DEBUG) {
log("onRefreshComplete()");
}
setListSelection(1);
setHeaderStatus(EndlessListView.HEADER_NORMAL);
}
}
protected void reachBottom() {
if (AppContext.DEBUG) {
Log.d(EndlessListView.TAG, "readBottom()");
}
if (!noFooter()) {
setLoading();
}
}
protected void reachTop() {
if (AppContext.DEBUG) {
Log.d(EndlessListView.TAG, "reachTop()");
}
setRefreshing();
}
public void removeFooter() {
if (getFooterViewsCount() == 1) {
removeFooterView(this.mLoadMoreView);
}
}
public void removeHeader() {
if (getHeaderViewsCount() == 1) {
removeHeaderView(this.mRefershView);
}
}
protected void setFooterStatus(final int status) {
if (status == EndlessListView.FOOTER_NONE) {
this.isLoading = false;
removeFooterView(this.mLoadMoreView);
return;
}
if (noFooter()) {
addFooterView(this.mLoadMoreView);
}
if (status == EndlessListView.FOOTER_HIDE) {
this.isLoading = false;
this.mLoadMoreView.setVisibility(View.GONE);
} else if (status == EndlessListView.FOOTER_NORMAL) {
this.isLoading = false;
this.mLoadMoreView.setVisibility(View.VISIBLE);
this.mLoadMoreProgressView.setVisibility(View.GONE);
this.mLoadMoreTextView.setVisibility(View.VISIBLE);
} else if (status == EndlessListView.FOOTER_LOADING) {
// isLoading = true;
this.mLoadMoreView.setVisibility(View.VISIBLE);
this.mLoadMoreProgressView.setVisibility(View.VISIBLE);
this.mLoadMoreTextView.setVisibility(View.GONE);
}
}
protected void setHeaderStatus(final int status) {
if (status == EndlessListView.HEADER_NONE) {
this.isRefresh = false;
removeHeaderView(this.mRefershView);
return;
}
if (status == EndlessListView.HEADER_HIDE) {
this.isRefresh = false;
this.mRefershView.setVisibility(View.GONE);
} else if (status == EndlessListView.HEADER_NORMAL) {
this.isRefresh = false;
this.mRefershView.setVisibility(View.VISIBLE);
this.mRefreshProgressView.setVisibility(View.GONE);
this.mRefreshTextView.setVisibility(View.VISIBLE);
} else if (status == EndlessListView.HEADER_LOADING) {
// isRefresh = true;
this.mRefershView.setVisibility(View.VISIBLE);
this.mRefreshProgressView.setVisibility(View.VISIBLE);
this.mRefreshTextView.setVisibility(View.GONE);
}
}
public void setListSelection(final int pos) {
post(new Runnable() {
@Override
public void run() {
setSelection(pos);
// View v = getChildAt(pos);
// if (v != null) {
// v.requestFocus();
// }
}
});
}
public void setLoading() {
if (this.isLoading) {
return;
}
if (AppContext.DEBUG) {
log("setFooterStatus(FOOTER_LOADING);");
}
this.isLoading = true;
setFooterStatus(EndlessListView.FOOTER_LOADING);
if (this.mOnRefreshListener != null) {
if (AppContext.DEBUG) {
log("onLoadMore()");
}
this.mOnRefreshListener.onLoadMore(this);
}
}
// @Override
// public void onScrollStateChanged(AbsListView view, int scrollState) {
// if(Build.VERSION.SDK_INT<9){
// return;
// }
// mScrollState = scrollState;
// switch (scrollState) {
// case SCROLL_STATE_FLING:
// if(App.DEBUG){
// Log.d(TAG, "FLING mFirstVisible=" + mFirstVisible);
// }
// break;
// case SCROLL_STATE_IDLE:
// if(App.DEBUG){
// Log.d(TAG, "IDLE mFirstVisible=" + mFirstVisible
// + " mLastFirstVisible=" + mLastFirstVisible);
// }
// if ( mLastFirstVisible + mVisibleItemCount>= mTotalItemCount
// && mFirstVisible + mVisibleItemCount>= mTotalItemCount) {
// reachBottom();
// } else if (mLastFirstVisible <3 && mFirstVisible == 0) {
// reachTop();
// }
// break;
// case SCROLL_STATE_TOUCH_SCROLL:
// mLastFirstVisible = mFirstVisible;
// if(App.DEBUG){
// Log.i(TAG, "TOUCH_SCROLL mFirstVisible=" + mFirstVisible);
// }
// break;
// default:
// break;
// }
// }
// @Override
// public void onScroll(AbsListView view, int firstVisibleItem,
// int visibleItemCount, int totalItemCount) {
// mFirstVisible = firstVisibleItem;
// mVisibleItemCount = visibleItemCount;
// mTotalItemCount = totalItemCount;
// }
// @Override
// protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
// int scrollY, int scrollRangeX, int scrollRangeY,
// int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
// return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
// scrollRangeX, scrollRangeY, maxOverScrollX, mMaxOverScrollY,
// isTouchEvent);
// }
public void setOnRefreshListener(final OnRefreshListener li) {
this.mOnRefreshListener = li;
}
public void setRefreshing() {
if (this.isRefresh) {
return;
}
if (AppContext.DEBUG) {
log("setHeaderStatus(HEADER_LOADING);");
}
this.isRefresh = true;
setHeaderStatus(EndlessListView.HEADER_LOADING);
if (this.mOnRefreshListener != null) {
if (AppContext.DEBUG) {
log("onRefresh()");
}
this.mOnRefreshListener.onRefresh(this);
}
}
}