/*
* 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.LinearLayout;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.Scroller;
import com.ab.view.listener.AbOnRefreshListener;
// TODO: Auto-generated Javadoc
/**
* The Class AbPullView.
*/
public class AbPullView extends ScrollView{
/** The m last y. */
private float mLastY = -1;
/** The m scroller. */
private Scroller mScroller;
/** The m scroll layout. */
private LinearLayout mScrollLayout;
//头部刷新View
/** The m header view. */
private AbListViewHeader mHeaderView;
//头部View的高度
/** The m header view height. */
private int mHeaderViewHeight;
/** The m enable pull refresh. */
private boolean mEnablePullRefresh = true;
/** The m pull refreshing. */
private boolean mPullRefreshing = false;
/** The m ab on refresh listener. */
private AbOnRefreshListener mAbOnRefreshListener = null;
/** The m scroll back. */
private int mScrollBack;
/** The Constant SCROLLBACK_HEADER. */
private final static int SCROLLBACK_HEADER = 0;
/** The Constant SCROLL_DURATION. */
private final static int SCROLL_DURATION = 400;
/** The Constant OFFSET_RADIO. */
private final static float OFFSET_RADIO = 1.8f;
/**
* 构造.
*
* @param context the context
*/
public AbPullView(Context context) {
super(context);
initView(context);
}
/**
* 构造.
*
* @param context the context
* @param attrs the attrs
*/
public AbPullView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
/**
* 初始化View.
* @param context the context
*/
private void initView(Context context) {
mScroller = new Scroller(context, new DecelerateInterpolator());
LinearLayout.LayoutParams layoutParamsFW = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
mScrollLayout = new LinearLayout(context);
mScrollLayout.setLayoutParams(layoutParamsFW);
mScrollLayout.setOrientation(LinearLayout.VERTICAL);
// init header view
mHeaderView = new AbListViewHeader(context);
// init header height
mHeaderViewHeight = mHeaderView.getHeaderHeight();
mHeaderView.setGravity(Gravity.BOTTOM);
mScrollLayout.addView(mHeaderView,layoutParamsFW);
this.addView(mScrollLayout);
}
/**
* 打开或者关闭下拉刷新功能.
*
* @param enable 开关标记
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
if (!mEnablePullRefresh) { // disable, hide the content
mHeaderView.setVisibility(View.INVISIBLE);
} else {
mHeaderView.setVisibility(View.VISIBLE);
}
}
/**
* 停止刷新并重置header的状态.
*/
public void stopRefresh() {
if (mPullRefreshing == true) {
mPullRefreshing = false;
resetHeaderHeight();
}
}
/**
* 更新header的高度.
*
* @param 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);
}
}
}
/**
* 根据状态设置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 ( (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
updateHeaderHeight(deltaY / OFFSET_RADIO);
}
break;
case MotionEvent.ACTION_UP:
mLastY = -1;
//需要刷新的条件
if (mEnablePullRefresh && mHeaderView.getVisiableHeight() >= mHeaderViewHeight) {
mPullRefreshing = true;
mHeaderView.setState(AbListViewHeader.STATE_REFRESHING);
if (mAbOnRefreshListener != null) {
//刷新
mAbOnRefreshListener.onRefresh();
}
}
if(mEnablePullRefresh){
//弹回
resetHeaderHeight();
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 描述:TODO
*/
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
if (mScrollBack == SCROLLBACK_HEADER) {
mHeaderView.setVisiableHeight(mScroller.getCurrY());
}
postInvalidate();
}
super.computeScroll();
}
/**
* 描述:设置ListView的监听器.
*
* @param abOnRefreshListener
*/
public void setAbOnRefreshListener(AbOnRefreshListener abOnRefreshListener) {
mAbOnRefreshListener = abOnRefreshListener;
}
/**
* 描述:向滚动容器中添加View.
*
* @param child the child
* @param index the index
*/
public void addChildView(View child, int index) {
mScrollLayout.addView(child,index);
}
/**
* 描述:向滚动容器中添加View.
*
* @param child the child
*/
public void addChildView(View child) {
mScrollLayout.addView(child);
}
/**
*
* 描述:获取Header View
* @return
* @throws
*/
public AbListViewHeader getHeaderView() {
return mHeaderView;
}
/**
*
* 描述:获取Header ProgressBar,用于设置自定义样式
* @return
* @throws
*/
public ProgressBar getHeaderProgressBar() {
return mHeaderView.getHeaderProgressBar();
}
}