Android自定义之ScrollView下拉刷新

公司项目,需要用到ScrollView的下拉刷新,一开始使用的时候PullToRefresh三方库的下拉刷新,我比较纠结第三档库,很强大,但是,公司项目的需求,PullToRefresh就不能做到了,改来改去的还是自己写一个下拉刷新比较靠谱,很多东西能够自己去控制。效果图就不上传了。直接解释关键代码。

ScrollView的下拉刷新比ListView的好做多了。

因为ScroTo的性质,ScrollView的下拉刷新,需要在外部添加一个父布局,通过父布局来控制触摸手势时候下传,什么时候下拉。

我自定义了一个PullScrollView

public class PullScrollView extends RelativeLayout

public PullScrollView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init(context);

}

public PullScrollView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context);

}

public PullScrollView(Context context) {

super(context);

init(context);

}

private Scroller mScroller ;

private int mTouchSlop ;

private void init(Context context){

ViewConfiguration configuration = ViewConfiguration.get(getContext());

mTouchSlop = configuration.getScaledTouchSlop();

mScroller = new Scroller(context, new DecelerateInterpolator());

}

首先是初始化mTouchSlop  是触摸手势滑动的最小像素值,也就是说滑动多少的距离才算是手势滑动,这样可以防止手势一点点的移动就引起的滑动事件。

mScroller  是用来处理平滑滚动的。之前的博客有介绍。

第二点:

@Override

protected void onFinishInflate() {

super.onFinishInflate();

if (getChildCount() > 2) {

throw new RuntimeException("子孩子只能有两个");

}

bottomView = (ViewGroup) getChildAt(0);

contentView = (ScrollView) getChildAt(1);

}

在布局初始化结束之后,得到布局中的两个子孩子,为啥只能有两个孩子那?? BottomView是用来下拉刷新展示的View  contentView 就是我们的ScrollView了。如果子孩子多了,怎么知道哪个VIew是需要被隐藏的?所以只处理两个View的情况,当然,如果还有上拉加载更多,就需要三个子孩子了。

第三:

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

bottomHeight = getBottomViewHeight() ;

Log.i("Test", l + "ceshi" + " t="+t + " r"+r + " b=" + b + " height= "   + bottomHeight);

bottomView.layout(l, - bottomHeight, r, t);

contentView.layout(l, 0, r, b);

}

onLayout,做过自定义的都应该很熟悉这个方法,放置子孩子位置的一个方法,因为我们需要有一个子孩子隐藏掉,当我们需要它显示的时候才去显示,所以  需要手动的去将BottomView放到布局-hight到0的位置,这样下拉的时候才能显示出来。

第四:

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

if (getScrollY() < 0 ) {

return true ;

}

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN:

startY = (int) ev.getY();

break;

case MotionEvent.ACTION_MOVE:

int moveY = (int) ev.getY();

int delayY = moveY - startY ;

Log.i("Test", delayY + " =  " + mTouchSlop) ;

if (getTopPosition() && delayY > mTouchSlop) {

ev.setAction(MotionEvent.ACTION_DOWN);

return true ;

}

break ;

case MotionEvent.ACTION_UP:

break;

}

return super.onInterceptTouchEvent(ev);

}

手势的拦截动作,通过getTopPosition()方式,来判断ScrollView时候处于下拉需要显示隐藏子View的状态,delayY > mTouchSlop 是用来判断是不是下拉的动作的。 如果符合条件  我们就需要将手势拦截掉,return true。

为什么我觉得ScrollView做下来刷新比较好做那? 就是因为ScrollView的判断比较好判断。

private boolean getTopPosition(){

if (contentView.getScrollY() <= 0 ) {

return true ;

}

return false ;

}

是不是很简单!!!!

第五:

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

startY = (int) event.getY();

break;

case MotionEvent.ACTION_MOVE:

int delayY = (int) (event.getY() - startY) ;

if (getTopPosition() && getScrollY() <= 0 ) {

pullMove((int) (-delayY * 0.8));  // 跟随手势滑动

}

startY = (int) event.getY();

return true ;

case MotionEvent.ACTION_UP:

int scrollY = getScrollY();

if (state == PullState.ON_REFRESH && scrollY < 0 && Math.abs(scrollY) > bottomHeight) {

restView(-getScrollY() - bottomHeight);  // 回弹到下拉刷新的状态

return true ;

}else if (state == PullState.ON_REFRESH && scrollY < 0 && Math.abs(scrollY) < bottomHeight) {

return true ;

}

if (scrollY < 0  &&  Math.abs(scrollY) < bottomHeight ) {

returnView(); // 回弹到原来的位置。

}else if (scrollY < 0 && Math.abs(scrollY) > bottomHeight  && state != PullState.ON_REFRESH) {

if (onreListener != null) {

state = PullState.ON_REFRESH ;

onreListener.refresh();  // 回调函数

}

restView(-getScrollY() - bottomHeight);

}

break;

}

return true ;

}

这个就是做移动的处理手势的方法了。

ScrollView的下拉刷新比起Listview ,要好做的多了。哈哈………………

下面是源码附上,用做学习之用。代码还有不完善之处,等我项目完成之后,我会把项目中的封装很完善的下拉刷新代码重新打包上传。

下载地址:  http://pan.baidu.com/s/1jG67mzc

来自为知笔记(Wiz)

时间: 2025-01-01 14:57:49

Android自定义之ScrollView下拉刷新的相关文章

Android打造通用的下拉刷新组件

还记得上一篇 blog 的内容吗?如果不记得建议先去了解一下,Android 事件处理全面剖析 ,因为下拉刷新需要用到手势的处理,而上一篇文章中,对事件处理做了很详细的说明,了解了事件的处理机制,对理解本篇文章有很大的帮助.好了,这里就当大家都已经对事件处理有了一定的了解,开始我们的下拉刷新征程. 还是老规矩,先上效果图,再根据效果图来分析实现的原理: 一 .分析原理 我们都知道,listView 控件为我们提供了 addHeaderView.和 addFootView 的方法,我们通过此方法可

探索SwipeRefreshLayout配合自定义ListView完成下拉刷新、滑到底部自动加载更多

在Android开发过程中经常需要实现上下拉刷新功能,Google推出的下拉刷新控件SwipeRefreshLayout(彩虹条),由于官方版本只有下拉刷新而没有上拉加载更多的功能,很多人也尝试在这个基础上进行改写.今天尝试一下使用SwipeRefreshLayout配合自定义ListView实现下拉刷新.滑到底部自动加载更多的功能. 效果图如下所示,在进入页面的时候加载自动刷新,滑到底部自动加载更多,当数据已经加载完成则显示已经加载完成,,否则上拉任可继续加载 先贴一下项目结构图吧,这样可能对

[Android学习系列15]下拉刷新列表实现动态加载

使用google官方的SwipeRefreshLayout 参考: http://blog.csdn.net/easyer2012/article/details/22857807 http://stormzhang.github.io/android/2014/03/29/android-swiperefreshlayout/ http://www.eoeandroid.com/thread-330439-1-1.html http://www.oschina.net/translate/sw

Android实现RecyclerView的下拉刷新和上拉加载更多

Android实现RecyclerView的下拉刷新和上拉加载更多 原文地址:https://www.cnblogs.com/zhujiabin/p/8206176.html

Android UI设计: 仿QQ好友列表分组悬停,自定义Header,下拉刷新结合Demo

之前学习了Pulltorefresh,pinnedheaderexpanablelistview 但是结合起来还是有点麻烦的.尤其是像QQ这种.他不是单纯的第一个当做分组.他是分组上面还有几个按钮,还有搜索框,同时可以滑动,而且还可以悬停.想了试了好几种方法,都有BUG.最后用的一种方法. 1. pulltorefresh用的android.v4里面自带的,好像知乎也是 2. 悬停和分组用的网上的,然后我把第一个分组的样式改成了自定义的menu菜单,并且清空了child.这样看上去就像一个自定义

android 安卓自定义listview实现下拉刷新

[1].重写listView public class MyListView extends ListView implements OnScrollListener {          private final static int RELEASE_To_REFRESH = 0;// 下拉过程的状态值       private final static int PULL_To_REFRESH = 1; // 从下拉返回到不刷新的状态值       private final static

Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件

前言: 因为公司人员变动原因,导致了博主四个月没有动安卓,一直在做IOS开发,如今接近年前,终于可以花一定的时间放在安卓上了.好了,废话不多说,今天我们要带来的效果是苹果版本的QQ下拉刷新.首先看一下目标效果以及demo效果:      因为此效果实现的步骤较多,所以今天博主要实现以上效果的第一步——打造一个通用的下拉刷新控件,具体效果如下: GIF图片比较大,还希望读者能耐心等待一下下从效果图中可以看出,我们的下拉刷新的滑动还是很流畅的,可能大多数开发者用的是XListview或者PullTo

Android—自定义控件实现ListView下拉刷新

这篇博客为大家介绍一个android常见的功能——ListView下拉刷新(参考自他人博客,网址忘记了,阅读他的代码自己理解注释的,希望能帮助到大家): 首先下拉未松手时候手机显示这样的界面: 下面的代码是自定的扎样的控件: package com.dhsr.smartID.view; import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; import andr

自定义ListView实现下拉刷新,下拉加载的功能

package com.loaderman.myrefreshlistviewdemo; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android