700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > android pulldown view Android控件PullRefreshViewGroup实现下拉刷新和上拉加载

android pulldown view Android控件PullRefreshViewGroup实现下拉刷新和上拉加载

时间:2022-08-09 21:44:06

相关推荐

android pulldown view Android控件PullRefreshViewGroup实现下拉刷新和上拉加载

本文实例为大家分享了Android实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下

先分享下源码:Android实现下拉刷新和上拉加载更多

实现思路:由PullRefreshViewGroup控件来接管标准控件(比如RecyclerView、ListView等)的滑动,调用标准控件的内部方法进行短距离滑动,不再由标准控件自己来处理事件,而完全由PullRefreshViewGroup控件来处理触摸事件。标准控件内部的滑动距离等属性,通过反射获得computeVerticalScrollExtent、computeVerticalScrollRange、computeVerticalScrollOffset这三个方法来获得。

PullRefreshViewGroup控件的布局如下

部分代码实现

触摸滑动事件处理

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

boolean bret = false;

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN: {

mPreY = ev.getY();

Log.d(TAG, "mPreY:" + String.valueOf(mPreY));

}

break;

case MotionEvent.ACTION_MOVE: {

float curY = ev.getY();

float distance = curY - mPreY;

if (Math.abs(distance) >= mTouchSlop) {

mSliding = bret = true;

//修正第一次滑动的卡顿

if (distance > 0) {

mPreY += mTouchSlop;

} else {

mPreY -= mTouchSlop;

}

if (!mScroller.isFinished()) {

mScroller.abortAnimation();

}

} else {

mSliding = bret = false;

}

}

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL: {

bret = mSliding;

}

break;

}

return bret ? true : super.onInterceptTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

boolean bret = false;

vTracker.addMovement(event);

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN: {

mPreY = event.getY();

bret = true;

}

break;

case MotionEvent.ACTION_MOVE: {

float curY = event.getY();

float distance = curY - mPreY;

Log.d(TAG, "mPreY:" + String.valueOf(mPreY) + " distance:" + String.valueOf(distance));

if (distance != 0) {

bret = true;

if (mSrcHeightHead == -1 && mHasPullRefresh) {

View child0View = mHeadView;

mSrcHeightHead = child0View.getHeight();

}

scrollBy(distance);

}

mPreY = curY;

}

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL: {

mPreCurY = 0;

View child0View = mHeadView;

int child0Height = null != child0View ? child0View.getHeight() : 0;

int child0Height2 = null != child0View ? child0View.getLayoutParams().height : 0; //视图的最终高度是有这个来决定的,请看onMeasure 函数的实现

// int child0Height3 = child0View.getMeasuredHeight();

if (child0Height2 != child0Height) {

child0Height = child0Height2;

}

int child0Top = null != child0View ? child0View.getTop() : 0;

int dy = child0Height - mSrcHeightHead + (mSrcHeightHead - Math.abs(child0Top));

Log.d(TAG, "onTouchEvent()ACTION_UP child0Height:" + String.valueOf(child0Height) + " mSrcHeightHead:" + String.valueOf(mSrcHeightHead) + " child0Top:" + String.valueOf(child0Top));

if (dy > 0) {//恢复拉伸视图的位置

if (!mLoadingMore && dy > mCanRefreshHeight && child0Top + child0Height2 > mCanRefreshHeight && mRefreshLoad != null) {

dy -= mCanRefreshHeight;

if (!mPullRefreshLoading) {

mPullRefreshLoading = true;

mTvRefreshInfo.setText("正在加载...");

mRefreshLoad.pullRefreshStartLoad();

}

}

mScroller.startScroll(0, 0, 0, -dy);

invalidate();

} else {

puteCurrentVelocity(1000);

float yvel = vTracker.getYVelocity();

if (yvel != 0) {//为了满足内部视图的快速滚动( 中间内容视图 )

mScroller.fling(0, 0, 0, (int) yvel, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);

invalidate();

}

}

vTracker.clear();

bret = true;

}

break;

}

return bret ? true : super.onTouchEvent(event);

}

小距离滑动代码

private void scrollBy(float distance) {

View child0View = mHeadView;

View child1View = getChildAt(null == mHeadView ? 0 : 1);

float distanceRemain = 0;

int child0Top = null != child0View ? child0View.getTop() : 0;

// int child0Height = child0View.getHeight();

if (distance < 0) {//向上

int child1Top = child1View.getTop();

// int child1Height = child1View.getHeight();

//child0View 缩小

if (-1 != mSrcHeightHead && null != child0View && child0View.getHeight() > mSrcHeightHead) {

float off = distance;

if (child0View.getHeight() + distance < mSrcHeightHead) {

off = -(child0View.getHeight() - mSrcHeightHead);

distance -= off;

} else {

distance = 0;

}

child0View.getLayoutParams().height += (int) off;

child1Top += (int) off; //child0view 缩小的同时, child1view 的高度也会随之上升 这里很重要

requestLayout();

child1View.offsetTopAndBottom((int) off);

if (null != mTailView) {

mTailView.offsetTopAndBottom((int) off);

}

}

if (distance != 0) {

if (child0Top + mSrcHeightHead + distance <= 0) {

distanceRemain = -(distance + (child0Top + mSrcHeightHead));//正数

distance = -(child0Top + mSrcHeightHead);//负数

}

//可以显示加载更多吗?

boolean bDirectDown = false;

boolean bCanScroll = child1View.canScrollVertically(1) || child1View.canScrollVertically(-1);

if (!bCanScroll) {

int child1ChildCount = 0;

if (child1View instanceof ViewGroup) {

child1ChildCount = ((ViewGroup) child1View).getChildCount();

}

if (child1ChildCount > 0) {

ViewGroup viewGroupChild1 = (ViewGroup) child1View;

View child1LastItem = viewGroupChild1.getChildAt(child1ChildCount - 1);

int child1ViewBottom = viewGroupChild1.getBottom();

int child1LastItemBottom = child1LastItem.getBottom() + child1Top; //相对于 ImageScaleViewGroup 的位置

//增加 child1ViewBottom > getHeight() 来控制 ScrollView

if (child1LastItemBottom == getHeight()) {

bDirectDown = true;

}

}

}

//正在下拉刷新的时候,不能显示加载更多

if ((bCanScroll || bDirectDown) && null != mTailView && !mPullRefreshLoading) {

int nVerticalScrollExtent = 0, nVerticalScrollRange = 0, nVerticalScrollOffset = 0;

Class c = null;

try {

c = Class.forName(child1View.getClass().getName());

} catch (Exception ex) {

}

try {

if (null == mComputeVerticalScrollExtent) {

Method computeVerticalScrollExtent = findcomputeVerticalMethod(c, "computeVerticalScrollExtent");

computeVerticalScrollExtent.setAccessible(true);

mComputeVerticalScrollExtent = computeVerticalScrollExtent;

}

nVerticalScrollExtent = (int) mComputeVerticalScrollExtent.invoke(child1View);

} catch (Exception ex) {

}

try {

if (null == mComputeVerticalScrollRange) {

Method computeVerticalScrollRange = findcomputeVerticalMethod(c, "computeVerticalScrollRange");

computeVerticalScrollRange.setAccessible(true);

mComputeVerticalScrollRange = computeVerticalScrollRange;

}

nVerticalScrollRange = (int) mComputeVerticalScrollRange.invoke(child1View);

} catch (Exception ex) {

}

try {

if (null == mComputeVerticalScrollOffset) {

Method computeVerticalScrollOffset = findcomputeVerticalMethod(c, "computeVerticalScrollOffset");

computeVerticalScrollOffset.setAccessible(true);

mComputeVerticalScrollOffset = computeVerticalScrollOffset;

}

nVerticalScrollOffset = (int) mComputeVerticalScrollOffset.invoke(child1View);

} catch (Exception ex) {

}

int range = nVerticalScrollRange - nVerticalScrollExtent;

if (nVerticalScrollOffset + distanceRemain > range) {

float nOff = distanceRemain - (range - nVerticalScrollOffset);

distanceRemain = range - nVerticalScrollOffset;

distance -= nOff;

}

int child3Bottom = mTailView.getBottom();

if (child3Bottom + distance < getHeight()) {

distance = getHeight() - child3Bottom;

}

}

if (!bCanScroll) {

distanceRemain = 0;

}

}

} else {//向下

int nScrollOffset = 0;

try {

Class c = Class.forName(child1View.getClass().getName());

Method computeVerticalScrollOffset = findcomputeVerticalMethod(c, "computeVerticalScrollOffset");//c.getDeclaredMethod("computeVerticalScrollOffset");

computeVerticalScrollOffset.setAccessible(true);

nScrollOffset = (int) computeVerticalScrollOffset.invoke(child1View);

} catch (Exception ex) {

}

int child2Top = null != mTailView ? mTailView.getTop() : getHeight();//注意默认值

if (child2Top < getHeight()) {

if (child2Top + distance > getHeight()) {

distanceRemain = distance - (getHeight() - child2Top);

distance = getHeight() - child2Top;

}

} else if (nScrollOffset > 0) {//内部有滚动,那么就要计算内部滚动距离,其他分配给整体滚动

if (nScrollOffset - distance <= 0) {

distanceRemain = -nScrollOffset;

// distance = distance - nScrollOffset;

distance = 0; //内部能滚动,不让外部去滚动

if (!mScroller.isFinished()) {

mScroller.abortAnimation(); //内部滚动完后,立即停止

}

} else {

distanceRemain = -distance;//负数

distance = 0;

}

} else {

if (child0Top + distance > 0) {//child0放大,child1移动

int off = (int) (child0Top + distance);

distance = -child0Top;

if (null != child0View) {

child0View.getLayoutParams().height += off;

requestLayout();

} else {

off = 0;

}

child1View.offsetTopAndBottom(off);

if (null != mTailView) {

mTailView.offsetTopAndBottom(off);

}

}

}

}

if (0 != (int) distance) {

if (null != child0View) {

child0View.offsetTopAndBottom((int) distance);

}

child1View.offsetTopAndBottom((int) distance);

if (null != mTailView) {

mTailView.offsetTopAndBottom((int) distance);

}

requestLayout();//奇酷360这里必须调用, 否则显示有点问题

}

scrollByForMidView(distanceRemain);//外部无法滚动的时候,内部滚动

if (!mPullRefreshLoading && !mLoadingMore) {

int tailviewTop = null != mTailView ? mTailView.getTop() : getHeight();//注意默认值

if (tailviewTop < getHeight() && mHasLoadMore) {//加载更多

mLoadingMore = true;

if (mRefreshLoad != null) {

mRefreshLoad.pullUpStartLoadMore();

}

} else {

if (mHasPullRefresh) {

if (distance < 0) {

int child0Bottom = child0View.getBottom();

if (child0Bottom < mCanRefreshHeight) {

mTvRefreshInfo.setText("下拉刷新");

}

} else {

int child0Bottom = child0View.getBottom();

if (child0Bottom > mCanRefreshHeight) {

mTvRefreshInfo.setText("松开刷新");

}

}

}

}

}

}

处理标准控件小距离滚动代码,这里ListView有点特殊。

private void scrollByForMidView(float distanceRemain) {

if (0 != (int) distanceRemain) {

View child1View = getChildAt(null == mHeadView ? 0 : 1);

if (child1View instanceof ListView) {

((ListView) child1View).smoothScrollBy((int) distanceRemain, 0);

} /*else if (child1View instanceof ScrollView){

((ScrollView) child1View).smoothScrollBy(0,(int) distanceRemain);

}*/ else {

child1View.scrollBy(0, (int) distanceRemain);

}

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。