效果图省略。。
。
activity_main.xml(仅仅有一个自己定义ListView)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.dampingdemo.MainActivity" > <com.example.dampingdemo.DampingListView1 android:id="@+id/listView" android:layout_width="fill_parent" android:layout_height="fill_parent" > </com.example.dampingdemo.DampingListView1> </RelativeLayout>
MainActivity(ArrayListAdapter 为了简化代码)
package com.example.dampingdemo; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; public class MainActivity extends Activity { private DampingListView1 dampingListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dampingListView = (DampingListView1) findViewById(R.id.listView); //data String[] data = {"A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C","A","B","C"}; //获取适配器 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,data ); //设置适配器 dampingListView.setAdapter(adapter); } }DampingListView1(第一种方法)
package com.example.dampingdemo; import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.widget.ExpandableListView; import android.widget.ListView; /** * 1. 在View中添加了overSrollBy方法,用于记录x, y 轴上滚动 2. 在AbsListView的onTouchEvent中推断是否到达边界(顶部 或 底部) ,然后调用view.overScrollBy ,传入 mScrollY等參数 3. overScrollBy 终于赋值给View的mScrollX, mScrollY 两个变量 4. 在AbsListView中调用完overScrollBy之后,调用invalidate重绘 * */ public class DampingListView1 extends ListView { private static final int MAX_Y_OVERSCROLL_DISTANCE = 200; private Context mContext; private int mMaxYOverscrollDistance; public DampingListView1(Context context) { super(context); mContext = context; initBounceListView(); } public DampingListView1(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; initBounceListView(); } public DampingListView1(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; initBounceListView(); } private void initBounceListView() { final DisplayMetrics metrics = mContext.getResources() .getDisplayMetrics(); final float density = metrics.density; mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE); } @Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent); } }
+++++++++++++++++++++++++++或者另外一种方法+++++++++++++++++++++++++++++++++++++++
DampingListView
package com.example.dampingdemo; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.ExpandableListView; import android.widget.ListView; public class DampingListView extends ListView implements Runnable { // 手指点位置的Y坐标 private float mLastDownY = 0f; // 移动距离 private int mDistance = 0; private int mStep = 0; // 是否移动过 private boolean mPositive = false; /** * 构造器 */ public DampingListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public DampingListView(Context context, AttributeSet attrs) { super(context, attrs); } public DampingListView(Context context) { super(context); } /** * TouchEvent事件 */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 系列事件,手指第一次按下时触发 if (mLastDownY == 0f && mDistance == 0) { mLastDownY = event.getY(); return true; } break; case MotionEvent.ACTION_CANCEL: break; case MotionEvent.ACTION_UP: // 手指离开之后触发 if (mDistance != 0) { mStep = 1; mPositive = (mDistance >= 0); // 就可以把你的Runnable对象添加到UI线程中执行。 this.post(this); return true; } // 又一次赋值 mLastDownY = 0f; mDistance = 0; break; case MotionEvent.ACTION_MOVE: // 手指按下之后滑动触发 if (mLastDownY != 0f) { mDistance = (int) (mLastDownY - event.getY()); if ((mDistance < 0 && getFirstVisiblePosition() == 0 && getChildAt( 0).getTop() == 0) || (mDistance > 0 && getLastVisiblePosition() == getCount() - 1)) { // 第一个位置而且是想下拉,就滑动或者最后一个位置向上拉 // 这个推断的作用是在非顶端的部分不会有此滚动 mDistance /= 3; // 这里是为了降低滚动的距离 scrollTo(0, mDistance); // 滚动 return true; } } // 置为0。有自己主动滑动的效果 mDistance = 0; break; } return super.onTouchEvent(event); } public void run() { mDistance += mDistance > 0 ? -mStep : mStep; scrollTo(0, mDistance); // 下拉mPositive是false,上拉是true if ((mPositive && mDistance <= 0) || (!mPositive && mDistance >= 0)) { scrollTo(0, 0); mDistance = 0; mLastDownY = 0f; return; } mStep += 1; this.post(this); } }