Android 类Path橡皮筋的效果

 
 
              Path的橡皮筋效果其实挺好实现。这里记录下学习心得。

        橡皮筋的核心思想应该是摩擦力和弹力,下拉的时候模拟出一个摩擦力的效果,松手的时候的时候有个回弹的效果就好了。

        Path是将需要有橡皮筋效果的部分做成了ListView的head。在listview的dispatchTouchEvent里进行了处理。

        先看下head的布局文件,就是一个ImageView,

       

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/headView_Main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/path_headimage"
        android:layout_width="fill_parent"
        android:layout_height="190dp"
        android:scaleType="center"
        android:src="@drawable/bg" />

</RelativeLayout>
需要注意的就是 android:scaleType="center"这个属性。也可以是 android:scaleType="centerCrop"。具体变化可以自己动手试下。
 
 
下面看下重要的代码部分,自己重写一个ListView:
public class ListViewPro extends ListView {

	private Context mContext;
	private Scroller mScroller;
	
	int left, top;
	float startX, startY, currentX, currentY;
	int bgViewH, iv1W;
	int rootW, rootH;
	View headView;
	View bgView;
	boolean scrollerType;
	static final int len = 0xc8;

	public ListViewPro(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

	}

	public ListViewPro(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.mContext = context;
		mScroller = new Scroller(mContext);
	}

	public ListViewPro(Context context) {
		super(context);

	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		int action = event.getAction();
		if (!mScroller.isFinished()) {
			return super.onTouchEvent(event);
		}
		headView = MainActivity.itemHead1;
		bgView = headView.findViewById(R.id.path_headimage);
		currentX = event.getX();
		currentY = event.getY();
		
		headView.getTop();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			
			left = bgView.getLeft();
			top = bgView.getBottom();
			rootW = getWidth();
			rootH = getHeight();
			bgViewH = bgView.getHeight();
			startX = currentX;
			startY = currentY;

			break;
		case MotionEvent.ACTION_MOVE:
		
			if (headView.isShown() && headView.getTop() >= 0) {

				int t = getScrollY(currentY - startY);
				
				if (t >= top && t <= headView.getBottom() + len) {
					bgView.setLayoutParams(new RelativeLayout.LayoutParams(bgView.getWidth(), t));
				}
				scrollerType = false;
			}
			break;
		case MotionEvent.ACTION_UP:
			
			scrollerType = true;
			mScroller.startScroll(bgView.getLeft(), bgView.getBottom(),
					
					0 - bgView.getLeft(), bgViewH - bgView.getBottom(), 200);
			invalidate();
			break;
		}

		return super.dispatchTouchEvent(event);
	}
    private int getScrollY(float dy) {
		int yy = (int) (top + dy/2.5F);
		return yy;
	}
	public void computeScroll() {
		//super.computeScroll();
		if (mScroller.computeScrollOffset()) {
			int x = mScroller.getCurrX();
			int y = mScroller.getCurrY();
		
			bgView.layout(0, 0, x + bgView.getWidth(), y);
			invalidate();
			
			if (!mScroller.isFinished() && scrollerType && y > 200) {
				bgView.setLayoutParams(new RelativeLayout.LayoutParams(bgView.getWidth(), y));
			}
		}
	}
}

原理就是根据手势在ListView上的滑动来改变ImageView的高度。代码处理部分在dispatchTouchEvent方法的MotionEvent.ACTION_MOVE这个case下:


int t = getScrollY(currentY - startY);
				
				if (t >= top && t <= headView.getBottom() + len) {
					bgView.setLayoutParams(new RelativeLayout.LayoutParams(bgView.getWidth(), t));
				}

需要关注的是getScrollY这个方法:

 
 private int getScrollY(float dy) {
		int yy = (int) (top + dy/2.5F);
		return yy;
	}
dy/2.5就是为了实现这个橡皮筋的效果。手指在ListView的滑动的距离体现到ImageView的高度时做了个摩擦力的虚拟效果。

手势弹起的时候就会sroll到初始状态。

你可能感兴趣的:(Android 类Path橡皮筋的效果)