#利用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(); } } });