Android 类Path橡皮筋的效果

来源:互联网 发布:arp设计软件 编辑:程序博客网 时间:2024/05/18 00:01


             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);}@Overridepublic 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到初始状态。