Android开发-自定义View-AndroidStudio(十二)仿ViewPager(2)

时间:2022-02-09 15:53:46
转载请注明出处: http://blog.csdn.net/iwanghang/
觉得博文有用,请点赞,请评论,请关注,谢谢!~


老规矩,先上GIF动态图,看个效果,如果符合你的项目或者确定你要了解的内容,再往下看吧:
Android开发-自定义View-AndroidStudio(十二)仿ViewPager(2)
MainActivity.java:
package com.iwanghang.mygesturedetector;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private MyViewPager myViewPager;
    private int[] ids = {R.drawable.a,R.drawable.b,R.drawable.c,
            R.drawable.d,R.drawable.e,R.drawable.f};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getSupportActionBar().hide();

        myViewPager = (MyViewPager) findViewById(R.id.myViewPager);

        // 添加页面
        for (int i = 0; i <ids.length ; i++) {
            ImageView iv = new ImageView(this);
            iv.setBackgroundResource(ids[i]);
            //iv.setImageResource(ids[i]);
            myViewPager.addView(iv);
        }
    }

}
MyViewPager.java:
package com.iwanghang.mygesturedetector;

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

/**
 * 仿ViewPager
 */
public class MyViewPager extends ViewGroup{

    /**
     * 手势识别
     * 1、定义出来
     * 2、实例化 -> 把想要的方法给重写
     * 3、在OnTouchEvent()把时间传递给手势识别器
     */

    private GestureDetector detector; // 1、定义出来
    /**
     * 当前页面的下标位置
     */
    private int currentIndex;

    //private MyScroller myScroller; // 自己写的回弹效果
    private Scroller myScroller; // 原生的回弹效果

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context); // 2、实例化
    }

    private void initView(final Context context) {
        //myScroller = new MyScroller(); // 自己写的回弹效果
        myScroller = new Scroller(context); // 原生的回弹效果
        // 2、实例化
        detector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                //scrollBy((int)distanceX, (int)distanceY); // 这里为了演示,可以上下左右滑动
                scrollBy((int)distanceX, getScrollY()); // Y轴保持在创建时的起始值,我们一般这么用
                //Toast.makeText(context, ""+e1+"|"+e2+"|"+distanceX+"|"+distanceY, Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }

    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        // 遍历孩子,给每个孩子指定在屏幕的坐标位置
        for (int n = 0; n <getChildCount() ; n++) {
            View childView = getChildAt(n);

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

    private float startX;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        // 把时间传递给手势识别器
        detector.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                // 记录坐标
                startX = event.getX();
                break;
            case MotionEvent.ACTION_MOVE:

                break;
            case MotionEvent.ACTION_UP:
                // 新的坐标
                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;
    }

    /**
     * pager计算
     */
    private void  scrollToPager(int tempIndex){
        if (tempIndex < 0){
            tempIndex = 0;
        }
        if (tempIndex > getChildCount()-1){
            tempIndex = getChildCount()-1;
        }
        //当前页面的下标位置
        currentIndex = tempIndex;
        int distanceX = currentIndex*getWidth() - getScrollX();
        //scrollTo(currentIndex*getWidth(), getScrollY());
        myScroller.startScroll(getScrollX(),getScrollY(),distanceX,0);
        //myScroller.startScroll(getScrollX(),getScrollY(),distanceX,0,Math.abs(distanceX));
        invalidate();// 强制绘制,导致下面computeScroll执行
    }

    @Override
    public void computeScroll() {
        //super.computeScroll();
        if(myScroller.computeScrollOffset()){
            //得到移动这个一小段对应的坐标
            float currX = myScroller.getCurrX();
            scrollTo((int) currX,0);
            invalidate();
        }
    }
}
MyScroller.java:
package com.iwanghang.mygesturedetector;

import android.os.SystemClock;

/**
 * 自己写的回弹效果
 */
public class MyScroller {

    /**
     * X轴的起始坐标
     */
    private float startY;

    /**
     * Y轴的起始坐标
     */
    private float startX;

    /**
     * 在X轴要移动的距离
     */
    private int distanceX;

    /**
     * 在Y轴要移动的距离
     */
    private int distanceY;

    /**
     开始的时间
     */
    private long startTime;

    /**
     * 总时间
     */
    private long totalTime = 500;

    /**
     * 是否移动完成
     * false没有移动完成
     * true:移动结束
     */
    private boolean isFinish;
    private float currX;

    /**
     * 得到坐标
     */
    public float getCurrX() {
        return currX;
    }

    public void startScroll(float startX, float startY, int distanceX, int distanceY) {
        this.startY = startY;
        this.startX = startX;
        this.distanceX = distanceX;
        this.distanceY = distanceY;
        this.startTime = SystemClock.uptimeMillis();//系统开机时间
        this.isFinish = false;
    }

    /**
     * 速度
     求移动一小段的距离
     求移动一小段对应的坐标
     求移动一小段对应的时间
     true:正在移动
     false:移动结束

     * @return
     */
    public boolean computeScrollOffset(){
        if(isFinish){
            return  false;
        }

        //这一小段的结束时间
        long endTime = SystemClock.uptimeMillis();

        //这一小段所花的时间
        long passTime = endTime - startTime;
        if(passTime < totalTime){
            // 还没有移动结束
            // 计算平均速度
            //float voleCity = distanceX/totalTime;
            // 移动这个一小段对应的距离
            float distanceSamllX = passTime* distanceX/totalTime;

            // 移动这一小段后对应x轴上的坐标
            currX = startX + distanceSamllX;

        }else{
            // 移动结束
            isFinish = true;
            currX = startX + distanceX;
        }

        return true;
    }
}
activity_main.xml:
<?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"
    tools:context="com.iwanghang.mygesturedetector.MainActivity">

    <com.iwanghang.mygesturedetector.MyViewPager
        android:id="@+id/myViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </com.iwanghang.mygesturedetector.MyViewPager>

</RelativeLayout>


转载请注明出处: http://blog.csdn.net/iwanghang/



欢迎移动开发爱好者交流
沈阳或周边城市公司有意开发Android,请与我联系
联系方式
Android开发-自定义View-AndroidStudio(十二)仿ViewPager(2)
微信:iwanghang
QQ:413711276
邮箱:iwanghang@qq.com



觉得博文有用,请点赞,请评论,请关注,谢谢!~