所谓阻尼效果,什么是阻尼效果,好吧,我不知道怎么去描述它,看图吧,真相一看就懂(参看附件gif图)
此效果在iphone上非常常见,当列表滑动到顶部或者底部,没有内容时,列表跟随手指移动一定距离,android自身的listview是滑动到顶部或者底部时,会有一层淡淡的颜色,个人比较喜欢后者,但常常在项目中会有类似于前者的需求。仿爱疯,你懂的。
好了,这里我们在说一下可能需要主要到的地方:
1.手指滑动,listview中的item跟随手指滚动(如何做到?)
2.item移动的距离小于手指滑动的距离(这个好办)
3.手指抬起之后,listview自动滚回到顶部位置(怎么办呢?)
这里我还是在代码里面来说吧:
activity_main.xml
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:padding="@dimen/padding_medium"
android:text="listview阻尼效果"
android:id="@+id/textview"
android:textSize="18sp"
tools:context=".MainActivity"/>
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_marginTop="10dp"
android:layout_below="@+id/textview"
android:layout_height="wrap_content"/>
PullListView.java
packagecom.example.pulllistview;
importandroid.content.Context;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.widget.ListView;
/**自定义阻尼效果列表**/
publicclassPullListViewextendsListViewimplementsRunnable{
privatefloatmLastDownY=0f;
privateintmDistance=0;
privateintmStep=0;
privatebooleanmPositive=false;
privateStringTag="PullListview";
publicPullListView(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
publicPullListView(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
}
publicPullListView(Contextcontext){
super(context);
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN://手指按下时触发
Log.d(Tag,"ActionDown");
if(mLastDownY==0f&&mDistance==0){
mLastDownY=event.getY();
Log.d(Tag,"mLastDownY赋值"+mLastDownY);
returntrue;
}
break;
caseMotionEvent.ACTION_CANCEL:
break;
caseMotionEvent.ACTION_UP://手指抬起之后触发
Log.d(Tag,"ActionUP");
if(mDistance!=0){
System.out.println("---post");
mStep=1;
mPositive=(mDistance>=0);
this.post(this);
returntrue;
}
mLastDownY=0f;
mDistance=0;
break;
caseMotionEvent.ACTION_MOVE://手指按下之后滑动触发
Log.d(Tag,"ActionMove");
if(mLastDownY!=0f){
mDistance=(int)(mLastDownY-event.getY());
Log.d(Tag,"mLastDownY不为0,view跟随滑动"+"mDistance"+mDistance);
if((mDistance<0&&getFirstVisiblePosition()==0&&
getChildAt(0).getTop()==0)||(mDistance>0&&
getLastVisiblePosition()==getCount()-1)){
//第一个位置并且是想下拉,就滑动或者最后一个位置向上拉
//这个判断的作用是在非顶端的部分不会有此滚动
mDistance/=2;//这里是为了减少滚动的距离
scrollTo(0,mDistance);//滚动
returntrue;
}
}
mDistance=0;
break;
}
returnsuper.onTouchEvent(event);
}
publicvoidrun(){
Log.d(Tag,"ActionUP调用post");
mDistance+=mDistance>0?-mStep:mStep;
scrollTo(0,mDistance);
if((mPositive&&mDistance<=0)||(!mPositive&&mDistance>=0)){
scrollTo(0,0);
mDistance=0;
mLastDownY=0f;
Log.d(Tag,"post中置0");
return;
}
mStep+=1;
//this.postDelayed(this,10);
this.post(this);
}
}
MainActivtiy.java
packagecom.example.pulllistview;
importjava.util.ArrayList;
importjava.util.List;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.Menu;
importandroid.widget.ArrayAdapter;
publicclassMainActivityextendsActivity{
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PullListViewlistview=(PullListView)findViewById(R.id.list);
listview.setAdapter(newArrayAdapter(this,
android.R.layout.simple_list_item_checked,getData()));
}
privateListgetData(){
Listdata=newArrayList();
data.add("阻尼效果测试数据1");
data.add("阻尼效果测试数据2");
data.add("阻尼效果测试数据3");
data.add("阻尼效果测试数据4");
data.add("阻尼效果测试数据5");
data.add("阻尼效果测试数据6");
data.add("阻尼效果测试数据7");
data.add("阻尼效果测试数据8");
data.add("阻尼效果测试数据9");
data.add("阻尼效果测试数据10");
data.add("阻尼效果测试数据11");
data.add("阻尼效果测试数据12");
data.add("阻尼效果测试数据13");
returndata;
}
@Override
publicbooleanonCreateOptionsMenu(Menumenu){
getMenuInflater().inflate(R.menu.activity_main,menu);
returntrue;
}
}
此处再提供另一种方法,但需要leve 为2.3及之后的才能使用,原因之前的sdk尚未此方法。该方法非常简单,还是看源码先.
BounceListView.java
packagecom.example.pulllistview;
importandroid.content.Context;
importandroid.util.AttributeSet;
importandroid.util.DisplayMetrics;
importandroid.widget.ListView;
publicclassBounceListViewextendsListView{
privatestaticfinalintMAX_Y_OVERSCROLL_DISTANCE=200;
privateContextmContext;
privateintmMaxYOverscrollDistance;
publicBounceListView(Contextcontext){
super(context);
mContext=context;
initBounceListView();
}
publicBounceListView(Contextcontext,AttributeSetattrs){
super(context,attrs);
mContext=context;
initBounceListView();
}
publicBounceListView(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
mContext=context;
initBounceListView();
}
privatevoidinitBounceListView(){
//getthedensityofthescreenanddosomemathswithitonthemaxoverscroll
distancevariablesothatyougetsimilarbehaviorsnomatterwhatthescreensize
finalDisplayMetricsmetrics=mContext.getResources().getDisplayMetrics();
finalfloatdensity=metrics.density;
mMaxYOverscrollDistance=(int)(density*MAX_Y_OVERSCROLL_DISTANCE);
}
//主要就是这个方法了,直接重载复写就好
@Override
protectedbooleanoverScrollBy(intdeltaX,intdeltaY,intscrollX,intscrollY,
intscrollRangeX,intscrollRangeY,intmaxOverScrollX,intmaxOverScrollY,
booleanisTouchEvent){
//Thisiswherethemagichappens,wehavereplacedtheincoming
maxOverScrollYwithourowncustomvariablemMaxYOverscrollDistance;
returnsuper.overScrollBy(deltaX,deltaY,scrollX,scrollY,scrollRangeX,
scrollRangeY,maxOverScrollX,mMaxYOverscrollDistance,isTouchEvent);
}
}