Android开发——利用ViewPager实现显示多个item无限轮播+点击事件监听

前言

在许多APP中,我们都会看到有广告无限轮播的UI。我们公司的项目也有这个需求,我本来是想利用GitHub上的第三方去实现的,但是我们公司有要显示多个item同时显示进行无限轮播,我只好自己写一个。

效果图

这里写图片描述
实现多个item进行无限轮播,我们要求是实现3个item进行无限轮播并且添加点击事件。我做出的效果是这样的。

源代码

布局文件XML

实现多个item,需要在布局文件XML中ViewPager的布局加入android:clipChildren="false" 这样才能让ViewPager的item显示多个。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:background="@color/colorAccent"
        android:layout_height="@dimen/dp_size_188"/>

    <LinearLayout
        android:id="@+id/ly"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_size_150"
        android:layout_marginTop="@dimen/dp_size_15"
        android:clipChildren="false"
        android:orientation="vertical">

        <android.support.v4.view.ViewPager
            android:id="@+id/main_viewpager"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_size_150"
            android:layout_marginLeft="@dimen/dp_size_25"
            android:layout_marginRight="@dimen/dp_size_25"
            android:clipChildren="false"/>
    </LinearLayout>
</LinearLayout>

item的布局文件XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_size_150" />
</LinearLayout>

加载图片的Adapter

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.util.ArrayList;

/**
 * 类说明:无限轮播图片适配器
 *
 * @author wujiahua
 * @date 2018/1/17
 */

public class ImageAdapter extends PagerAdapter {
    private Context mContext;
    private ArrayList<Integer> pagesArrayList;

    public ImageAdapter(Context mContext) {
        this.mContext = mContext;
    }

    /**
     * 设置ViewPager将要显示的数据
     * 当图片数量小于3张的时候,通过复制数组拼接数据
     */
    public void setAdapterData(ArrayList<Integer> arrayList) {
        pagesArrayList = arrayList;
        if (pagesArrayList.size() < 2) {
            pagesArrayList.add(pagesArrayList.get(0));
            pagesArrayList.add(pagesArrayList.get(0));
            pagesArrayList.add(pagesArrayList.get(0));
        } else if (pagesArrayList.size() < 3) {
            pagesArrayList.add(pagesArrayList.get(0));
            pagesArrayList.add(pagesArrayList.get(1));
        }
    }

    @Override
    public int getCount() {
        //无限轮播取一个Int类型的最大:2147483647
        return Integer.MAX_VALUE;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (pagesArrayList.size() > 0) {
            View itemView = LayoutInflater.from(mContext).inflate(R.layout.viewpager_adapter, null);
            itemView.setFocusable(true);
            ImageView imageView = itemView.findViewById(R.id.imageView);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            imageView.setBackgroundResource(pagesArrayList.get(position % pagesArrayList.size()));
            container.addView(itemView);
            return itemView;
        }
        return null;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

Activity或Fragment中的源码

我这是单独的一个Demo,所以写在MainActivity中,可以写在自己想要的界面当中。

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import java.util.ArrayList;

/**
 * 类说明:这是一个加载本地资源的无限轮播。
 *
 * @author wujiahua
 */
public class MainActivity extends AppCompatActivity {
    /**上下文*/
    private Context mContext;
    /**
     * 使用Handler通信
     */
    private Handler mHandler;
    /**
     * ViewPager组件
     */
    private ViewPager mViewPager;
    /**单个item的下标*/
    private int viewPagerItemSize = 0;
    /**
     * 滑动时间间隔设置成3s
     */
    private final int INTERVAL = 1000 * 3;
    /**
     * 图片数组
     */
    private ArrayList<Integer> mArrayList;
    /**
     * 设置常量
     */
    private final static int SET_VIEWPAGER_ITEM = 9527;
    /**
     * 适配器
     */
    private ImageAdapter mViewPagerAdapter;
    /**
     * 判断是否进行轮播
     */
    private boolean isLoop = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化
        init();
    }

    private void init() {
        //初始化数据
        initData();
        if (viewPagerItemSize > 0) {
            //初始化ViewPager视图
            initViewPager();
            //设置自动滑动
            setAutoChangeViewPager();
        }
    }

    private void initData() {
        //初始化数据
        mContext = this;
        mArrayList = new ArrayList<>();
        mArrayList.add(R.mipmap.vp_1);
        mArrayList.add(R.mipmap.vp_2);
        mArrayList.add(R.mipmap.vp_3);
        viewPagerItemSize = mArrayList.size();
    }

    private void initViewPager() {
        //初始化ViewPager
        mViewPager = findViewById(R.id.main_viewpager);
        //ViewPager的父布局
        LinearLayout linearLayout = findViewById(R.id.ly);
        mViewPagerAdapter = new ImageAdapter(mContext);
        mViewPagerAdapter.setAdapterData(mArrayList);
        mViewPager.setAdapter(mViewPagerAdapter);
        //设置图片缓存为3
        mViewPager.setOffscreenPageLimit(3);
        //设置item之间间距为15dp
        mViewPager.setPageMargin(15);
        //设置item的出现位置
        int currentItem = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % viewPagerItemSize;
        mViewPager.setCurrentItem(currentItem);
        //设置父布局的LinearLayout的事件分发,反正只有中间的item可以滑动
        linearLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                mViewPager.dispatchTouchEvent(motionEvent);
                return true;
            }
        });
        //设置ViewPager事件分发
        mViewPager.setOnTouchListener(new View.OnTouchListener() {
            long downTime;
            int downX;
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                mViewPager.requestDisallowInterceptTouchEvent(true);
                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        Log.e("TAG", "==========用户按下item");
                        isLoop = false;
                        //记录按下的坐标
                        downX = (int) motionEvent.getX();
                        //记录按下的时间
                        downTime = System.currentTimeMillis();
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.e("TAG", "==========用户抬起item");
                        if (System.currentTimeMillis() - downTime < 500
                                && Math.abs(downX - motionEvent.getX()) < 30) {
                            int item = mViewPager.getCurrentItem() % 3;
                            Log.e("TAG", "==============item=" + item);
                            Log.e("TAG", "==============item=" + mViewPager.getCurrentItem());
                            if (item == 0) {
                                Toast.makeText(MainActivity.this,
                                        "用户触发点击事件,点击第一张图片", Toast.LENGTH_SHORT).show();
                            } else if (item == 1) {
                                Toast.makeText(MainActivity.this,
                                        "用户触发点击事件,点击第二张图片", Toast.LENGTH_SHORT).show();
                            } else if (item == 2) {
                                Toast.makeText(MainActivity.this,
                                        "用户触发点击事件,点击第三张图片", Toast.LENGTH_SHORT).show();
                            }
                        }
                        isLoop = true;
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        //第二个case设置item的顶级点击事件,写这个item是为了防止item失效
                        isLoop = true;
                        break;
                    default:
                        break;
                }
                return false;
            }
        });
    }

    /**自动滑动*/
    @SuppressLint("HandlerLeak")
    public void setAutoChangeViewPager() {
        PageChangeListenerImpl mPageChangeListenerImpl = new PageChangeListenerImpl();
        mViewPager.addOnPageChangeListener(mPageChangeListenerImpl);
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case SET_VIEWPAGER_ITEM:
                        if (mViewPager != null && mViewPagerAdapter != null) {
                            int currentItemIndex = mViewPager.getCurrentItem();
                            int itemsCount = mViewPagerAdapter.getCount();
                            if ((currentItemIndex + 1) < itemsCount) {
                                mViewPager.setCurrentItem(currentItemIndex + 1, true);
                            } else {
                                mViewPager.setCurrentItem(0, false);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
        };
        new Thread(new Runnable() {

            @Override
            public void run() {
                Message message = mHandler.obtainMessage();
                message.what = SET_VIEWPAGER_ITEM;
                if (isLoop) {
                    mHandler.sendMessage(message);
                }
                mHandler.removeCallbacks(this);
                mHandler.postDelayed(this, INTERVAL);
            }
        }).start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mViewPager) {
            mViewPager.removeAllViews();
            mViewPager = null;
        }
    }

    private class PageChangeListenerImpl implements ViewPager.OnPageChangeListener {
        @Override
        public void onPageScrolled(final int position, float positionOffset, int positionOffsetPixels) {
            //在ViewPager实现无限轮播的时候,需要指示器的发生变化的时候,可以在这里进行修改
        }

        @Override
        public void onPageSelected(int position) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    }
}

总结

这个Demo是利用ViewPager实现无限轮播功能,然后添加了每一个item的点击事件。希望对看我博客的小伙伴的学习和开发有帮助。最后附上源码的下载链接,如果有需要的小伙伴可以去下载运行看一下结果或者直接复制上面的源码。http://download.csdn.net/download/chengxu_kuangrexintu/10215738

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值