ViewPager简单实现

来源:互联网 发布:大数据4v特征包括 编辑:程序博客网 时间:2024/06/16 05:10
package com.edu.fzu.news.view;import android.content.Context;import android.graphics.PointF;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.Scroller;/** * 使用: *       MyScrollView myScrollView = (MyScrollView) findViewById(R.id.myscrollview); *       // 添加子View到MyScrollView中         for (int i = 0; i < ids.length; i++) {            ImageView image = new ImageView(this);            image.setBackgroundResource(ids[i]);            myScrollView.addView(image);         } *  *  *//** * 仿ViewPager:实现ViewPager随着手指的滑动而滑动 * 实现: * 1.界面:测量,布局(充血onMeasure和onLayout) * 2.事件:滑动跟随运动(onTouch事件),松手缓慢滑动到指定位置(Scroller类+computeScroll回调) * 补充: *  1.控件滑动有三种方式:Scroller,动画,Layoutparams *  2.如果要实现类似ViewPager的回调,可采用设计回调接口,然后对外暴露 */public class MyScrollView extends ViewGroup {    private Scroller mScroller;    public MyScrollView(Context context) {        this(context, null);    }    public MyScrollView(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    private void initView() {        mScroller = new Scroller(getContext());    }    /*        display:        1.measure        2.layout        3.draw--this is view, so don't draw     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // measure self        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        // measure child        for (int i=0; i<getChildCount(); i++) {            measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);        }     }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        // layout child        for (int i=0; i<getChildCount(); i++) {            View view = getChildAt(i);            view.layout(i*getWidth(), 0, (i+1)*getWidth(), getHeight());        }    }    /*    刷新思路:        1.监听滑动松开(ACTION_UP),调用启动缓慢滑动事件myScroller.startScroll           并刷新当前view,invalidate();        2.调用invalidate();导致computeScroll被回调        3.计算滑动是否完成myScroller.computeScrollOffset,并获取中间位置           myScroller.getCurrX(),跳转到中间位置        4.重新刷新界面(递归上面2-4步骤)    */    /*        event:        deal the scroll event        scroll distance     */    private PointF downPoint = new PointF();    @Override    public boolean onTouchEvent(MotionEvent event) {        // mGestureDetector.onTouchEvent(event);        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downPoint.set(event.getX(), event.getY());                break;            case MotionEvent.ACTION_MOVE:                float curX = event.getX();                float disX = -(curX - downPoint.x);                scrollBy((int) disX, 0);                downPoint.x = curX;                break;            case MotionEvent.ACTION_UP:                int nextId = (getScrollX()+getWidth()/2) / getWidth();                moveToDest(nextId);                break;        }        return true;    }    /**     * 移动到指定的屏幕上     * @param nextId   屏幕 的下标     */    private void moveToDest(int nextId) {        // check nextId between[0, getChildCount())        if (nextId < 0) {            nextId = 0;        }        if (nextId > getChildCount()-1) {            nextId = getChildCount() - 1;        }        //瞬间移动        // scroll direct to distination        // scrollTo(nextId*getWidth(), 0);        //缓慢移动到指定最终位置        int dx = nextId*getWidth() - getScrollX();        mScroller.startScroll(getScrollX(), 0, dx, 0);        /*       * 刷新当前view   onDraw()方法 的执行       */        invalidate();    }    @Override    /**     * invalidate();  会导致  computeScroll()这个方法的执行     */    public void computeScroll() {        if(mScroller.computeScrollOffset()){   // 有点类似回调:两个函数循环互相调用            int newX = (int) mScroller.getCurrX();            scrollTo(newX, 0);            invalidate();        };    }}
0 0
原创粉丝点击