/*
* Copyright (C) 2013 www.418log.org
*
* 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.ab.view.pullview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.ListAdapter;
import android.widget.ProgressBar;
import android.widget.Scroller;
import com.ab.view.listener.AbOnListViewListener;
import com.ab.view.pullview.AbMultiColumnBaseAbsListView.OnScrollListener;
// TODO: Auto-generated Javadoc
/**
* The Class AbMultiColumnListView.
*/
public class AbMultiColumnListView extends AbMultiColumnBaseListView implements OnScrollListener {
/** The m last y. */
private float mLastY = -1;
/** The m scroller. */
private Scroller mScroller;
/** The m scroll listener. */
private OnScrollListener mScrollListener;
/** The m list view listener. */
private AbOnListViewListener mListViewListener;
/** The m header view. */
private AbListViewHeader mHeaderView;
/** The m header view height. */
private int mHeaderViewHeight;
/** The m footer view height. */
private int mFooterViewHeight;
/** The m enable pull refresh. */
private boolean mEnablePullRefresh = true;
/** The m pull refreshing. */
private boolean mPullRefreshing = false;
// -- footer view
/** The m footer view. */
private AbListViewFooter mFooterView;
/** The m enable pull load. */
private boolean mEnablePullLoad;
/** The m pull loading. */
private boolean mPullLoading;
/** The m is footer ready. */
private boolean mIsFooterReady = false;
/** The m total item count. */
private int mTotalItemCount;
/** The m scroll back. */
private int mScrollBack;
/** The Constant SCROLLBACK_HEADER. */
private final static int SCROLLBACK_HEADER = 0;
/** The Constant SCROLLBACK_FOOTER. */
private final static int SCROLLBACK_FOOTER = 1;
/** The Constant SCROLL_DURATION. */
private final static int SCROLL_DURATION = 200;
/** The Constant OFFSET_RADIO. */
private final static float OFFSET_RADIO = 1.8f;
/**上一次的数量*/
private int count = 0;
/**
* Instantiates a new ab multi column list view.
*
* @param context the context
*/
public AbMultiColumnListView(Context context) {
super(context);
initView(context);
}
/**
* Instantiates a new ab multi column list view.
*
* @param context the context
* @param attrs the attrs
*/
public AbMultiColumnListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
/**
* Inits the with context.
*
* @param context the context
*/
private void initView(Context context) {
mScroller = new Scroller(context, new DecelerateInterpolator());
super.setOnScrollListener(this);
// init header view
mHeaderView = new AbListViewHeader(context);
// init header height
mHeaderViewHeight = mHeaderView.getHeaderHeight();
mHeaderView.setGravity(Gravity.BOTTOM);
addHeaderView(mHeaderView);
// init footer view
mFooterView = new AbListViewFooter(context);
mFooterViewHeight= mFooterView.getFooterHeight();
//先隐藏
mFooterView.hide();
}
/**
* 描述:TODO
* @see com.ab.view.pullview.AbMultiColumnAbsListView#setAdapter(android.widget.ListAdapter)
* @author: zhaoqp
* @date:2013-9-4 下午4:06:32
* @version v1.0
*/
@Override
public void setAdapter(ListAdapter adapter) {
// make sure XListViewFooter is the last footer view, and only add once.
if (mIsFooterReady == false) {
mIsFooterReady = true;
mFooterView.setGravity(Gravity.TOP);
addFooterView(mFooterView);
}
super.setAdapter(adapter);
}
/**
* enable or disable pull down refresh feature.
*
* @param enable the new pull refresh enable
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
if (!mEnablePullRefresh) {
mHeaderView.setVisibility(View.INVISIBLE);
} else {
mHeaderView.setVisibility(View.VISIBLE);
}
}
/**
* enable or disable pull up load more feature.
*
* @param enable the new pull load enable
*/
public void setPullLoadEnable(boolean enable) {
mEnablePullLoad = enable;
if (!mEnablePullLoad) {
mFooterView.hide();
mFooterView.setOnClickListener(null);
} else {
mPullLoading = false;
mFooterView.show();
mFooterView.setState(AbListViewFooter.STATE_READY);
mFooterView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startLoadMore();
}
});
}
}
/**
* stop refresh, reset header view.
*/
public void stopRefresh() {
if (mPullRefreshing == true) {
mPullRefreshing = false;
resetHeaderHeight();
}
//判断有没有数据
if(mAdapter.getCount()>0){
mFooterView.setState(AbListViewFooter.STATE_READY);
}else{
mFooterView.setState(AbListViewFooter.STATE_EMPTY);
}
}
/**
* 开始加载更多.
*/
private void startLoadMore() {
mFooterView.show();
mPullLoading = true;
mFooterView.setState(AbListViewFooter.STATE_LOADING);
if (mListViewListener != null) {
//开始下载数据
mListViewListener.onLoadMore();
}
}
/**
* 停止加载更多并重置footer的状态.
*/
public void stopLoadMore() {
mFooterView.hide();
mPullLoading = false;
int countNew = mAdapter.getCount();
//判断有没有更多数据了
if(countNew > count){
mFooterView.setState(AbListViewFooter.STATE_READY);
}else{
mFooterView.setState(AbListViewFooter.STATE_NO);
}
}
/**
* Update header height.
*
* @param delta the delta
*/
private void updateHeaderHeight(float delta) {
int newHeight = (int) delta + mHeaderView.getVisiableHeight();
mHeaderView.setVisiableHeight(newHeight);
if (mEnablePullRefresh && !mPullRefreshing) {
if (mHeaderView.getVisiableHeight() >= mHeaderViewHeight) {
mHeaderView.setState(AbListViewHeader.STATE_READY);
} else {
mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
}
}
setSelection(0);
}
/**
* 根据状态设置Header的位置.
*/
private void resetHeaderHeight() {
//当前下拉到的高度
int height = mHeaderView.getVisiableHeight();
if (height < mHeaderViewHeight || !mPullRefreshing) {
//距离短 隐藏
mScrollBack = SCROLLBACK_HEADER;
mScroller.startScroll(0, height, 0, -1*height, SCROLL_DURATION);
}else if(height > mHeaderViewHeight || !mPullRefreshing){
//距离多的 弹回到mHeaderViewHeight
mScrollBack = SCROLLBACK_HEADER;
mScroller.startScroll(0, height, 0, -(height-mHeaderViewHeight), SCROLL_DURATION);
}
invalidate();
}
/**
* 描述:TODO
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mLastY == -1) {
mLastY = ev.getRawY();
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
final float deltaY = ev.getRawY() - mLastY;
mLastY = ev.getRawY();
if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
updateHeaderHeight(deltaY / OFFSET_RADIO);
} else if (mEnablePullLoad && !mPullLoading && getLastVisiblePosition() == mTotalItemCount - 1 && deltaY < 0) {
startLoadMore();
}
break;
case MotionEvent.ACTION_UP:
mLastY = -1;
if (getFirstVisiblePosition() == 0) {
//需要刷新的条件
if (mEnablePullRefresh && mHeaderView.getVisiableHeight() >= mHeaderViewHeight) {
mPullRefreshing = true;
mHeaderView.setState(AbListViewHeader.STATE_REFRESHING);
if (mListViewListener != null) {
//刷新
mListViewListener.onRefresh();
}
}
//根据mPullRefreshing判断显示的header
resetHeaderHeight();
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 描述:TODO
* @see android.view.View#computeScroll()
*/
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
if (mScrollBack == SCROLLBACK_HEADER) {
mHeaderView.setVisiableHeight(mScroller.getCurrY());
}
postInvalidate();
}
super.computeScroll();
}
/**
* 描述:设置ListView的监听器.
*
* @param abOnListViewListener the new ab on list view listener
*/
public void setAbOnListViewListener(AbOnListViewListener abOnListViewListener) {
mListViewListener = abOnListViewListener;
}
/**
* 描述:TODO
* @see com.ab.view.pullview.AbMultiColumnBaseAbsListView.OnScrollListener#onScrollStateChanged(com.ab.view.pullview.AbMultiColumnBaseAbsListView, int)
* @author: zhaoqp
* @date:2013-9-4 下午4:06:32
* @version v1.0
*/
@Override
public void onScrollStateChanged(AbMultiColumnBaseAbsListView view, int scrollState) {
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(view, scrollState);
}
}
/**
* 描述:TODO
* @see com.ab.view.pullview.AbMultiColumnBaseAbsListView.OnScrollListener#onScroll(com.ab.view.pullview.AbMultiColumnBaseAbsListView, int, int, int)
* @author: zhaoqp
* @date:2013-9-4 下午4:06:32
* @version v1.0
*/
@Override
public void onScroll(AbMultiColumnBaseAbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// send to user's listener
mTotalItemCount = totalItemCount;
if (mScrollListener != null) {
mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
/**
*
* 描述:获取Header View
* @return
* @throws
*/
public AbListViewHeader getHeaderView() {
return mHeaderView;
}
/**
*
* 描述:获取Footer View
* @return
* @throws
*/
public AbListViewFooter getFooterView() {
return mFooterView;
}
/**
*
* 描述:获取Header ProgressBar,用于设置自定义样式
* @return
* @throws
*/
public ProgressBar getHeaderProgressBar() {
return mHeaderView.getHeaderProgressBar();
}
/**
*
* 描述:获取Footer ProgressBar,用于设置自定义样式
* @return
* @throws
*/
public ProgressBar getFooterProgressBar() {
return mFooterView.getFooterProgressBar();
}
}