首页 > 代码库 > ListView阻尼效果

ListView阻尼效果

效果图省略。。


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 = http://www.mamicode.com/{"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);
	}
}


ListView阻尼效果