原帖链接
<!-- Description:上拉刷新,下拉加载更多是现在最流行的手势操作,但是对于初学者来说,在实现上是有一定难度的, 网上很多教程讲的都过于复杂,对于初学者无法起到引导作用,特此写本文,帮助安卓新手入门理解此, 还有最为重要的一点:本文只帮助你理解,并不是想你成为代码搬运工!别被那么多代码吓到了, 其中很多都是注释,仔细看注释对你理解有很大的帮助 Author:Booker L Date:2014-05-16 -->
一,事先准备: 实现该功能,最基本的需要两个东西,一个是OnTouchListener,一个是OnScrollListener,必须得理解这两个东西 1,OnTouchListener:用于监测触碰事件,当发生手指碰到屏幕时,以及滑动时,需要用到该Listener来处理相应操作 2,OnScrollListener:用于监听ListView的滚动事件(不一定是ListView,应是支持该监听的所有控件), 当滚动到第一行或最后一行时需要的判断,其中会有三个参数,后面会讲解道 二,Let's begin: 首先先自定义两个listener并实现对应的接口,并且在可访问公共变量的类中设置两个变量来判断当前滚动值和状态: 1, class TestClass extends Activity{ //在可访问公共变量的类中设置两个变量来判断当前滚动值和状态 private boolean isFirstRow;//是否滚到第一行 private boolean isLastRow;是否滚到最后一行 ..... } 其次写两个自定义类来实现相关接口: //滚动监听类 2.1, class MyScrollListener implements OnScrollListener{ /**当滚动时触发的方法 *firstVisiableItem--当前list中能见的第一个item下标,也就是当前被滚到最前面的 *visiableItemCount--当前可以看见的item的总数 *totalItemcount--总共的item数量 */ @Override public void onScroll(AbsListView arg0, int firstVisiableItem, int visiableItemCount, int totalItemcount) { //判断当前是否滚动到第一行(根据前面对参数的解释相信你能够理解) if(firstVisiableItem==0&&totalItemcount>0){ isFirstRow=true; }else{ //否者不是第一行 isFirstRow=false; } //判断是否到了滚动到了最后一行 if (firstVisiableItem + visiableItemCount == totalItemcount && totalItemcount > 0) { isLastRow = true; }else{ isLastRow=false; } } /**当滚动状态发生变化时触发的方法 *scrollState--发生的变化的状态,共有:SCROLL_STATE_IDLE(滚动,并且手指已经离开屏幕),SCROLL_STATE_FLING(手指快速滚动时),SCROLL_STATE_TOUCH_SCROLL(手指滚动,但是手指依然在屏幕上) */ @Override public void onScrollStateChanged(AbsListView arg0, int scrollState) { //这个方法的使用视情况而定,这里不需要用到 } } //触摸监听类 2.2, class MyTouchListener implements OnTouchListener{ /**其中MotionEvent为重要参数,它提供了触摸事件的所有参数和方法*/ @Override public boolean onTouch(View v, MotionEvent event) { /* 这里需要做的几件事: 1,当发生down事件时,记录发生该事件的y坐标 2,当发生move事件时,判断移动中的y坐标是否能够达成下拉或上拉事件 3,当发生up事件时,如果达成上拉或下拉事件时,触发对应事件 /* //为了能够形成视觉上的上拉下托简单效果,需要设置如下变量 //用于获取显示屏相关内容 DisplayMetrics dm =getResources().getDisplayMetrics(); //获取dpi值,以便较为精确的算出移动的像素 float density=dm.densityDpi/100; //得到布局参数,用它来实现视觉上的拖动效果 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); //设置一个变量来记录原始y坐标 private float or_y=0f; //event中调用getAction()来获取当前触发的是什么事件,这里我们要用到down,move,up这三个事件 switch(event.getAction()){ case MotionEvent.ACTION_DOWN: //发生down事件记录原始y坐标,getY()方法可重载,用于判断多点触控,这个不需要判断 or_y=event.getY(); break; case MotionEvent.ACTION_MOVE: //当手势移动时,获取当前y坐标,并与之前的坐标进行对比,来判断是往上还是往下 //设置变量获取移动值,往上托为正值,往下拉为负值 int y_dis=(int)(or_y-event.getY()); //判断是否达成拖动条件 if(isFirstRow&&y_dis<0){//处于第一行并且继续往下拉动 //得到移动距离的绝对值并且算出其移动的相对距离, float distance=Math.abs(y_dis/density/2); lp.topMargin=(int)distance; //形成往下拉的效果,其中listView为对应的控件(不一定是ListView) listView.setLayoutParams(lp); }else if(isLastRow&&y_dis>0){//处于最后一行并且继续网上拉时 //同理 float distance=Math.abs(y_dis/density/2); lp.bottomMargin=(int)distance; listView.setLayoutParams(lp); } break; case MotionEvent.ACTION_UP: //当发生up事件时,如果达成条件可触发事件,即触发对应事件 if(isFirstRow){ lp.topMargin=0; //调用获取刷新数据的接口方法getNewest(); }else if(isLastRow){ lp.bottomMargin=0; //调用获取更多数据的接口方法getMore(); } listView.setLayoutParams(lp); break; } } } 最后在listView中设置对应的监听即可: 3, onCreate(){ //得到控件 listView=(ListView)R.findViewById(R.id.XXX); //设置对应的listener即可 listView.setOnTouchListener(new MyTouchListener()); listView.setOnScrollListener(new MyScrollListener()); }