真正的画廊,左右条目可点击居中, 左右条目可滑动

来源:互联网 发布:js uint8array 编辑:程序博客网 时间:2024/06/04 19:19

利用Viewpager实现真正的Gallery, 左右条目可点击居中, 左右条目可滑动,也就是可以获得焦点

前言: 最近公司做一个想Gallery一样的效果,于是想在网上找个现成的,但是怎么找也没找到,就是找到一个鸿洋大神的巧用ViewPager 打造不一样的广告轮播切换效果的,但是左右条目不可点击,又不可以滑动,所以就做了个这个控件,本控件也是利用ViewPgaer做出来的

首先看一下效果:

这里写图片描述
从图上可以看出, 两边的item可以被点击居中, 可以被滑动,也就是可以获得焦点

接下来讲一下原理

设置PageTransformer

PageTransformer大家估计都相当熟悉吧,下面是PageTransformer的代码

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外面展示图片

这里写图片描述

大家都知道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;public GalleryViewPager(Context context) {    super(context);}public GalleryViewPager(Context context, AttributeSet attrs) {    super(context, attrs);}@Overridepublic 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();        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);}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的变化

    findViewById(R.id.root).setOnTouchListener(new View.OnTouchListener() {        @Override        public boolean onTouch(View v, MotionEvent event) {            return mViewPager.dispatchTouchEvent(event);        }    });

控制两边图片的点击事件只响应居中图片, 不响应点击事件

在viewpageradapter中设置如下代码, 中间的图片永远是mViewPager.getCurrentItem(),只有中间的图片可以响应点击事件

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

使用方式

添加依赖

1.在根目录的build.gradle中添加

allprojects {repositories {    jcenter()    maven { url 'https://jitpack.io' }// 添加jitpack.依赖}

2.在app的build.gradle中添加

    compile 'com.github.niezhiyang:NGallery:v1.0.1'

在使用的xml中,用一个父控件包裹住GalleryViewPager,目的是为了控制父控件的滑动,和点击,来设置Viewpager的状态

<RelativeLayout    android:id="@+id/root"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:clipChildren="false"    >    <!--是否限制子View在其范围内,我们将其值设置为false后那么当子控件的高度高于父控件时也会完全显示,而不会被压缩-->    <com.nie.ngallerylibrary.GalleryViewPager        android:id="@+id/viewpager"        android:layout_width="200dp"        android:layout_height="200dp"        android:layout_centerInParent="true"        android:clipChildren="false"        android:overScrollMode="never"/></RelativeLayout>

代码中设置

    mViewPager = (GalleryViewPager) findViewById(R.id.viewpager);//找到这个控件    mViewPager.setPageTransformer(true, new ScalePageTransformer());//设置PageTransformer,本库只有一个ScalePageTransformer,如果这个ScalePageTransformer满足不了您的需求,您可以自己写一个PageTransformer    findViewById(R.id.root).setOnTouchListener(new View.OnTouchListener() {        @Override        public boolean onTouch(View v, MotionEvent event) {            return mViewPager.dispatchTouchEvent(event);        }    });//找到这个父控件设置他的listener    mPagerAdapter = new SimpleAdapter(this);//初始化adapter    mViewPager.setAdapter(mPagerAdapter);//设置adapter

adapter要继承MyPageradapter;例如

public class SimpleAdapter extends MyPageradapter {    private final List<Integer> mList;    private final Context mContext;    public SimpleAdapter(Context context) {        mList = new ArrayList<>();        mContext = context;    }    public void addAll(List<Integer> list) {        mList.addAll(list);        notifyDataSetChanged();    }    @Override    public View getView(final int position, View convertView, ViewGroup container) {        ImageView imageView = null;        if (convertView == null) {            imageView = new ImageView(mContext);        } else {            imageView = (ImageView) convertView;        }        imageView.setTag(position);        imageView.setImageResource(mList.get(position));        imageView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if ((mViewPager.getCurrentItem() ) == position) {                    Toast.makeText(mContext, "点击的位置是:::"+position, Toast.LENGTH_SHORT).show();                }            }        });        return imageView;    }    @Override    public int getCount() {        return mList.size();    }}

这只不过是简单的添加imageview,你也可以添加fragment做出绚丽的效果,还可以跟任意的viewpgaerindicator使用了,是不是想想就高兴了

具体实现请看源码:NGallery

apk位置:demo.apk

欢迎start

阅读全文
2 0