1. 程式人生 > >自定義View——仿ViewPager

自定義View——仿ViewPager

效果圖

1.主佈局

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

    <RadioGroup
        android:id
="@+id/rg_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal" />
<com.hbwj.a06viewpager.MyViewPager android:id="@+id/myviewpager" android:layout_width
="match_parent" android:layout_height="match_parent" android:layout_below="@+id/rg_main" />
</RelativeLayout>

2.程式碼中例項化MyScrollerView,並且新增頁面

 private MyViewPager myviewpager;
    private int[] ids = {R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a
5, R.drawable.a6}; private RadioGroup rg_main; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); myviewpager = (MyViewPager) findViewById(R.id.myviewpager); rg_main = (RadioGroup) findViewById(R.id.rg_main); //新增6頁面 for (int i = 0; i < ids.length; i++) { ImageView imageView = new ImageView(this); imageView.setBackgroundResource(ids[i]); //新增到MyViewPager這個View中 myviewpager.addView(imageView); } } }

3.onLayout方法實現:指定6個圖片的位置

  @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //遍歷孩子,給每個孩子指定在螢幕的座標位置
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);

            childView.layout(i * getWidth(), 0, (i + 1) * getWidth(), getHeight());
        }

    }

畫圖分析
這裡寫圖片描述

4.對自定義的viewpager進行滑動,此時想到的便是手勢識別器,手勢識別器分為3步走:

  • 1.定義出來
  • 2.例項化-把想要的方法給重新
  • 3.在onTouchEvent()把事件傳遞給手勢識別器
 private GestureDetector detector;
 private void initView(final Context context) {

        //2.例項化手勢識別器
        detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                Toast.makeText(context, "長按", Toast.LENGTH_SHORT).show();
            }

            /**
             *
             * @param e1
             * @param e2
             * @param distanceX 在X軸滑動了的距離
             * @param distanceY 在Y軸滑動了的距離
             * @return
             */
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {


                /**
                 *x:要在X軸移動的距離
                 *y:要在Y軸移動的距離
                 */
                scrollBy((int) distanceX, 0);

                return true;
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                Toast.makeText(context, "雙擊", Toast.LENGTH_SHORT).show();
                return super.onDoubleTap(e);
            }
        });
    }
     //3.把事件傳遞給手勢識別器:onTouchEvent方法中
        detector.onTouchEvent(event);

5.滑動到某個位置後自動到合適的位置下標停留

這裡寫圖片描述

 private float startX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        //3.把事件傳遞給手勢識別器
        detector.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //1.記錄座標
                startX = event.getX();
                System.out.println("onTouchEvent==ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("onTouchEvent==ACTION_MOVE");

                break;
            case MotionEvent.ACTION_UP:
                System.out.println("onTouchEvent==ACTION_UP");

                //2.來到新的座標
                float endX = event.getX();

                //下標位置
                int tempIndex = currentIndex;

                if ((startX - endX) > getWidth() / 2) {

                    //顯示下一個頁面
                    tempIndex++;

                } else if ((endX - startX) > getWidth() / 2) {

                    //顯示上一個頁面
                    tempIndex--;
                }

                //根據下標位置移動到指定的頁面
                scrollToPager(tempIndex);

                break;
        }
        return true;
    }
       /**
     * 遮蔽非法值,根據位置移動到指定頁面
     *
     * @param tempIndex
     */
    public void scrollToPager(int tempIndex) {

        if (tempIndex < 0) {
            tempIndex = 0;
        }

        if (tempIndex > getChildCount() - 1) {
            tempIndex = getChildCount() - 1;
        }
        //當前頁面的下標位置
        currentIndex = tempIndex;

        //總距離計算出來
        int distanceX = currentIndex * getWidth() - getScrollX();
        // int distanceX = 目標 - getScrollX();
        //移動到指定的位置
        scrollTo(currentIndex*getWidth(),getScrollY());

    }

滑動到某一個頁面的演算法
這裡寫圖片描述

6.解決仿viewpager回彈時的生硬問題:使用系統自帶的Scroller

 private Scroller scroller;
 //初始化
  scroller = new Scroller(context);
    /**
     * 遮蔽非法值,根據位置移動到指定頁面
     *
     * @param tempIndex
     */
    public void scrollToPager(int tempIndex) {

        if (tempIndex < 0) {
            tempIndex = 0;
        }

        if (tempIndex > getChildCount() - 1) {
            tempIndex = getChildCount() - 1;
        }
        //當前頁面的下標位置
        currentIndex = tempIndex;
        if (onPagerChangeListener != null) {
            onPagerChangeListener.onScrollToPager(tempIndex);
        }
        //總距離計算出來
        int distanceX = currentIndex * getWidth() - getScrollX();
        // int distanceX = 目標 - getScrollX();
        //移動到指定的位置
        //scrollTo(currentIndex*getWidth(),getScrollY());
        //scroller.startScroll(getScrollX(),getScrollY(),distanceX,0);

        scroller.startScroll(getScrollX(), getScrollY(), distanceX, 0, Math.abs(distanceX));
        invalidate();//強制繪製;//onDraw();computeScroll();
    }

    @Override
    public void computeScroll() {
//        super.computeScroll();
        if (scroller.computeScrollOffset()) {
            //得到移動這個一小段對應的座標
            float currX = scroller.getCurrX();
            scrollTo((int) currX, 0);
            invalidate();
        }

    }

新增RadioGroup點選並實現雙向跳轉

  for (int i = 0; i < myviewpager.getChildCount(); i++) {
            RadioButton button = new RadioButton(getApplicationContext());
            button.setId(i);
            if (i == 0) {
                button.setChecked(true);
            }
            rg_main.addView(button);
        }
        rg_main.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
                myviewpager.scrollToPager(checkedId);
            }
        });

定義介面PagerChangeListener監聽頁面變化

     /**
     * 監聽頁面變化
     */
    interface OnPagerChangeListener {
        void onScrollToPager(int position);
    }

    OnPagerChangeListener onPagerChangeListener;

    public void setOnPagerChangeListener(OnPagerChangeListener onPagerChangeListener) {
        this.onPagerChangeListener = onPagerChangeListener;
    }
    //scrollToPager中新增程式碼
     if (onPagerChangeListener != null) {
            onPagerChangeListener.onScrollToPager(tempIndex);
        }

使用介面

 myviewpager.setOnPagerChangeListener(new MyViewPager.OnPagerChangeListener() {
            @Override
            public void onScrollToPager(int position) {
                rg_main.check(position);
            }
        });

7.新增測試頁面

佈局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#55ff0000"
    android:weightSum="1">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="136dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <ProgressBar
        android:id="@+id/progressBar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="372dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <ProgressBar
        android:id="@+id/progressBar3"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />


    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge" />


        </LinearLayout>


    </ScrollView>
</LinearLayout>

MainActivity中添加布局

  //指定頁面添加布局
        View view=View.inflate(getApplicationContext(),R.layout.test,null);
        myviewpager.addView(view,2);

8.解決無法看到效果,在MyScrollView中重寫OnMeasure

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            childView.measure(widthMeasureSpec, heightMeasureSpec);
        }
    }

9.解決事件攔截問題

這裡寫圖片描述

MyViewPager中新增攔截事件

 /**
     * 攔截事件
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean result = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                detector.onTouchEvent(ev);
                //第一次按下的座標
                downX = ev.getX();
                downY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float newdownX = ev.getX();
                float newdownY = ev.getY();
                int distanceX = (int) Math.abs(newdownX - downX);
                int distanceY = (int) Math.abs(newdownY - downY);
                //防止抖動為1的情況
                if(distanceX>distanceY&&distanceX>10){
                   result=true;
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return result;
    }