利用VIewpager实现真正的画廊,两边item可点击居中,可滑动

#利用Viewpager实现真正的Gallery, 左右条目可点击居中, 左右条目可滑动,也就是能够得到焦点 ##前言: 最近公司作一个想Gallery同样的效果,因而想在网上找个现成的,可是怎么找也没找到,就是找到一个鸿洋大神的巧用ViewPager 打造不同的广告轮播切换效果的,可是左右条目不可点击,又不能够滑动,因此就作了个这个控件,本控件也是利用ViewPgaer作出来的 ##首先看一下效果: 这里写图片描述<br> 从图上能够看出, 两边的item能够被点击居中, 能够被滑动,也就是能够得到焦点 ##接下来说一下原理 ###设置PageTransformer PageTransformer你们估计都至关熟悉吧,下面是PageTransformer的代码git

public void transformPage(View page, float position) {

    if (position < -1) {
        position = -1;
    } else if (position > 1) {
        position = 1;
    }

    float tempScale = position < 0 ? 1 + position : 1 - position;

    float slope = (MAX_SCALE - MIN_SCALE) / 1;
    //一个公式
    float scaleValue = MIN_SCALE + tempScale * slope;
    page.setScaleX(scaleValue);
    page.setScaleY(scaleValue);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        page.getParent().requestLayout();
    }
}

这个的做用就是让Viewpager展现多个条目,看下面的图片, 红色的才是ViewPager的大小,因此此PageTransformer是为了在Viewpager外面展现图片github

这里写图片描述 ###你们都知道PageTransformer没有真正的改变viewpager的状态,可是为何本demo中两侧的图片能够点击还能够滑动呢,让我慢慢跟你道来 其实很简单,就是在viewpage的父控件中拦截dispatchTouchEvent的方法来控制ViewPgaer的滑动和相应点击事件的(不懂dispatchTouchEvent即事件分发的, 问问度娘就能够了) ####先看一下自定义ViewPager public class GalleryViewPager extends ViewPager { //默认距离 private final static float DISTANCE = 10; private float downX; private float downY;app

public GalleryViewPager(Context context) {
    super(context);
}

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

[@Override](https://my.oschina.net/u/1162528)
public boolean dispatchTouchEvent(MotionEvent ev) {
    if(ev.getAction() == MotionEvent.ACTION_DOWN){
        downX = ev.getX();
        downY = ev.getY();
    }else if (ev.getAction() == MotionEvent.ACTION_UP) {

        float upX = ev.getX();
        float upY = ev.getY();
        //若是 up的位置和down 的位置 距离 > 设置的距离,则事件继续传递,不执行下面的点击切换事件
        if(Math.abs(upX - downX) > DISTANCE || Math.abs(upY - downY) > DISTANCE){
            return super.dispatchTouchEvent(ev);
        }

        View view = viewOfClickOnScreen(ev);
        if (view != null) {
            int index = (Integer) view.getTag();
            if (getCurrentItem() != index) {
                setCurrentItem(index);
            }
        }
    }
    return super.dispatchTouchEvent(ev);
}

/**
 * [@param](https://my.oschina.net/u/2303379) ev
 * [@return](https://my.oschina.net/u/556800)
 */
private View viewOfClickOnScreen(MotionEvent ev) {
    int childCount = getChildCount();
    int currentIndex = getCurrentItem();
    int[] location = new int[2];
    for (int i = 0; i < childCount; i++) {
        View v = getChildAt(i);
        int position = (Integer) v.getTag();
        v.getLocationOnScreen(location);
        int minX = location[0];
        int minY = location[1];

        int maxX = location[0] + v.getWidth();
        int maxY = location[1] + v.getHeight();

        if(position < currentIndex){
            maxX -= v.getWidth() * (1 - ScalePageTransformer.MIN_SCALE) * 0.5 + v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;
            minX -= v.getWidth() * (1 - ScalePageTransformer.MIN_SCALE) * 0.5 + v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;
        }else if(position == currentIndex){
            minX += v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE));
        }else if(position > currentIndex){
            maxX -= v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;
            minX -= v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;
        }
        float x = ev.getRawX();
        float y = ev.getRawY();

        if ((x > minX && x < maxX) && (y > minY && y < maxY)) {
            return v;
        }
    }
    return null;
}
}

等会让VIewPgaer的父控件的dispatchTouchEvent实现此ViewPager的dispatchTouchEvent就能够了 好比在mainactivity中找到父控件, 根据父控件的dispatchTouchEvent来控制此ViewPgaer的变化ide

findViewById(R.id.root).setOnTouchListener(new View.OnTouchListener() {
        [@Override](https://my.oschina.net/u/1162528)
        public boolean onTouch(View v, MotionEvent event) {
            return mViewPager.dispatchTouchEvent(event);
        }
    });

###控制两边图片的点击事件只响应居中图片, 不响应点击事件 在viewpageradapter中设置以下代码, 中间的图片永远是mViewPager.getCurrentItem(),只有中间的图片能够响应点击事件ui

imageView.setOnClickListener(new View.OnClickListener() {
            [@Override](https://my.oschina.net/u/1162528)
            public void onClick(View v) {
                Log.i("wwwwwwwwss", mViewPager.getCurrentItem()+ "------" + position);
                if ((mViewPager.getCurrentItem() ) == position) {
                    Toast.makeText(mContext, "点击的位置是:::"+position, Toast.LENGTH_SHORT).show();
                }

            }
        });

##apk位置:demo.apk ##源码位置:NGallery 欢迎startspa

相关文章
相关标签/搜索