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