仿ViewPager,MyScroller的简单实现,滑动与滚动的区别

 1.为什么高分辨率文件夹内的图片在低分辨率手机上显示模糊?
系统在加载高分辨率文件夹内的图片时对其图片进行了压缩。


 2.关于滑动的两个重要API:
(1)移动屏幕一段距离:scrollBy(disX,disy);
向左滑距离为正,向右滑距离为负。
此方法其实是对scrollTo进行了包裹,内部会调用onScrollChanged.
(2)移动基准点至指定点:scrollTo(x,y).
说明:scroll坐标系不同以往,左边为正。


3.真正让ViewGroup滑动的是scrollTo,scrollBy。computeScroll的作用是计算ViewGroup如何滑动。而computeScroll是通过draw来调用的。


4.关于onTouchEvent事件解析。
除了交给手势识别器,还可以同时自己解析。


5.关于scroller重要API
scroller.startScroll(getScrollX(),0, (int) distance,0);
scroller.computeScrollOffset();

scroller.getCurrX();

6.滑动事件onFiling.

此事件必须与up事件做区分(true时为onFiling,false为up)

   /**
             * 滑行时调用
             */
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                isFiling = true;
                if (velocityX > 0 && currentIndex > 0) {
                    tempIndex = currentIndex - 1;
                } else if (velocityX < 0 && currentIndex < getChildCount() - 1) {
                    tempIndex = currentIndex + 1;
                }
                flushView();

                return false;
            }
示例代码:

package com.imooc.like_viewpager;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * Created by Administrator on 2018/1/20.
 */
public class MyScrollView extends ViewGroup {

    private static final String TAG = "MyScrollView";
    private GestureDetector detector;
    private Scroller scroller;

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    //初始化布局
    private void initView(Context context) {
        scroller = new Scroller(context);
        detector = new GestureDetector(context, new GestureDetector.OnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {

            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }

            /**
             * 手指滑动时调用
             */
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

                /**
                 *移动VIEW一段距离
                 * 向左滑为正,向右为负
                 */
                scrollBy((int) distanceX, 0);
                /**
                 *将当前视图基准点移动到某一点
                 */
                // scrollTo(x,y);
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {

            }

            /**
             * 滑行时调用
             */
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                isFiling = true;
                if (velocityX > 0 && currentIndex > 0) {
                    tempIndex = currentIndex - 1;
                } else if (velocityX < 0 && currentIndex < getChildCount() - 1) {
                    tempIndex = currentIndex + 1;
                }
                flushView();

                return false;
            }
        });
    }

    //滑动标签
    boolean isFiling = false;

    /**
     * 确定view位置
     *
     * @param changed View发生改变
     * @param l,t,r,b 是相对父布局的位置
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0; i < getChildCount(); i++) {
            View v = getChildAt(i);
            v.layout(0 + i * getWidth(), 0, getWidth() * (i + 1), getHeight());

        }
    }

    //DOWN事件的点
    float firstX;
    //当前图片下标
    int currentIndex = 0;
    //当前图片临时下标
    int tempIndex = 0;


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //将触摸事件交给手势识别器进行解析处理
        detector.onTouchEvent(event);

        //还想添加自己的事件解析
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                firstX = event.getRawX();
                break;
            case MotionEvent.ACTION_MOVE:
                //MOVE由手势识别器帮我们解析
                break;
            case MotionEvent.ACTION_UP:
                if (!isFiling) {
                    if ((event.getRawX() - firstX) > getWidth() / 2) {
                        //向右滑
                        if (currentIndex != 0) {
                            tempIndex = currentIndex - 1;
                        }
                    } else if ((firstX - event.getRawX()) > getWidth() / 2) {
                        //向左滑
                        if (currentIndex != this.getChildCount() - 1) {
                            tempIndex = currentIndex + 1;
                        }
                    } else {
                        tempIndex = currentIndex;
                    }
                    //刷新VIEW
                    flushView();
                }
                isFiling = false;

                break;
        }

        return true;
    }

    private void flushView() {
        //当前图片下标需满足的条件:
        currentIndex = tempIndex > 0 ? tempIndex : 0;
        currentIndex = (tempIndex < (this.getChildCount() - 1)) ? tempIndex : (this.getChildCount() - 1);
        currentIndex = (tempIndex == -1) ? 0 : currentIndex;
        //若想瞬间移动,,scrollTo(currentIndex * getWidth(), 0)就搞定了;

        //最终的距离-现在的距离=移动的距离,因此向左滑为正,向右为负。
        long distance = currentIndex * getWidth() - getScrollX();
        scroller.startScroll(getScrollX(), 0, (int) distance, 0);

        invalidate();
    }

    /**
     * invalidate会导致此方法的执行
     * 此方法会根据手机性能决定运行的次数
     */
    @Override
    public void computeScroll() {
        super.computeScroll();
        if (scroller.computeScrollOffset()) {
            float newX = scroller.getCurrX();
            scrollTo((int) newX, 0);
            invalidate();
        }
    }
}




你可能感兴趣的:(itheima)