利用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

相關文章
相關標籤/搜索