android 滑动效果学习

前言

我们在list view或者recycle view当中的某个item向左滑动时,可以显示出删除的按钮,这种交互方式使用的非常多,今天就来学习一下它的实现原理。

Scroller的使用

首先我们需要知道view 当中的2个与scroll相关的方法:scrollTo(x,y),scrollBy(x,y),
这个两个方法的区别就是,to是相对的是view的原始坐标,而by是相对view的当前坐标。

  • scrollBy是基于view内容当前位置进行增量式的相对滑动
  • 而scrollTo则是相对于view的绝对坐标进行滑动。
    下面是2种实现的区别效果:


    android 滑动效果学习_第1张图片
    效果图

    scrollTo()方法是让View相对于初始的位置滚动某段距离,由于View的初始位置是不变的,因此不管我们点击多少次scrollTo按钮滚动到的都将是同一个位置。而scrollBy()方法则是让View相对于当前的位置滚动某段距离,那每当我们点击一次scrollBy按钮,View的当前位置都进行了变动,因此不停点击会一直向右下方移动。
    下面是一个自定义的viewgrop的示例,通过运用scrollTo和scrollBy,类似于viewpage效果。

package com.example.daixin.a3dtest;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewConfigurationCompat;
import android.text.SpanWatcher;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * TODO: document your custom view class.
 */
public class ScrollerLayout extends ViewGroup{
    private Scroller scroller;
    private int touchSlop;
    private float xDown;
    private float xMove;
    private float xLastMove;
    private int leftBorder;
    private int rightBorder;
    String TAG = "ScrollerLayout";


    public ScrollerLayout(Context context) {
        super(context);
        init(context);
    }

    public ScrollerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ScrollerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private void init(Context context){
        scroller  = new Scroller(context);
        ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
        touchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(viewConfiguration);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            // 为ScrollerLayout中的每一个子控件测量大小
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
        }

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                xDown = ev.getRawX();
                xLastMove = ev.getRawX();
                //Log.e(TAG,"onInterceptTouchEvent ACTION_DOWN xLastMove:"+xLastMove);
                break;
            case MotionEvent.ACTION_MOVE:
                xLastMove = ev.getRawX();
                //Log.e(TAG,"onInterceptTouchEvent ACTION_MOVE xLastMove:"+xLastMove);
                float diff = Math.abs(xMove - xDown);
                if (diff > touchSlop) {
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:

                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:

                break;
            case MotionEvent.ACTION_MOVE:
                Log.e(TAG,"ACTION_MOVE getScrollX:"+getScrollX());
                xMove = event.getRawX();
                //Log.e(TAG,"xMove:"+xMove);
                //Log.e(TAG,"xLastMove:"+xLastMove);
                int scrolledX = (int) (xLastMove - xMove);
                Log.e(TAG,"scrolledX:"+scrolledX);
                if (getScrollX() + scrolledX < leftBorder) {
                    scrollTo(leftBorder, 0);
                    return true;
                } else if (getScrollX() + getWidth() + scrolledX > rightBorder) {
                    scrollTo(rightBorder - getWidth(), 0);
                    return true;
                }
                scrollBy(scrolledX, 0);
                xLastMove = xMove;
                break;
            case MotionEvent.ACTION_UP:
                //Log.e(TAG,"getScrollX:"+getScrollX());
                //Log.e(TAG,"getWidth:"+getWidth());
              //判断当前处于哪个view的界面,得到targetIndex的值
                int targetIndex = (getScrollX() + getWidth() / 2) / getWidth();
                Log.e(TAG,"targetIndex:"+targetIndex);
                int dx = targetIndex * getWidth() - getScrollX();
                //Log.e(TAG,"dx:"+dx);
                // 第二步,调用startScroll()方法来初始化滚动数据并刷新界面,会不断调用computeScroll来更新。
                scroller.startScroll(getScrollX(), 0, dx, 0);
                invalidate();
                break;

        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed) {
            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                View childView = getChildAt(i);
                // 为ScrollerLayout中的每一个子控件在水平方向上进行布局
                childView.layout(i * childView.getMeasuredWidth(), 0, (i + 1) * childView.getMeasuredWidth(), childView.getMeasuredHeight());
            }
            // 初始化左右边界值
            leftBorder = getChildAt(0).getLeft();
            rightBorder = getChildAt(getChildCount() - 1).getRight();
        }
        Log.e(TAG,"leftBorder:"+leftBorder);
        Log.e(TAG,"rightBorder:"+rightBorder);
    }

    @Override
    public void computeScroll() {
        //super.computeScroll();
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            invalidate();
        }
    }
}
android 滑动效果学习_第2张图片
效果图

你可能感兴趣的:(android 滑动效果学习)