安卓基础--自定义无限轮播的轮播图,可动态添加指示点,可点击跳转页面

ViewPager是android中的常见控件,今天就写一个ViewPager的常见用法,自定义轮播图,可无限轮播,可点击跳转可以动态添加指示点,且指示点不会乱跳。

下面是效果图


首先写一个java类,继承ViewPager:

package com.example.administrator.mybanner;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;/**
 * Created by bean on 2016/12/9.
 */
public class CycleViewPager extends ViewPager {
    private OnItemClickListener mOnItemClickListener;
    private int mDownX;
    private int mDownY;
    private int mDownTime;
    public CycleViewPager(Context context) {
        super(context);
    }
    public CycleViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public void setOnPageChangeListener(OnPageChangeListener listener) {
        MyPageChangeListener myPageChangeListener = new MyPageChangeListener(listener);
        super.setOnPageChangeListener(myPageChangeListener);
    }
    @Override
    public void setAdapter(PagerAdapter adapter) {
        //  修正  adapter 中position
        MyAdapter myAdapter = new MyAdapter(adapter);
        setOnPageChangeListener(null); //手动增加一个监听
        super.setAdapter(myAdapter);
        setCurrentItem(1);
        //开启自动轮播
        startScroll();//自动轮播
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //手指触摸  按下 停止轮播  抬起继续轮播
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录按下时候手指的坐标
                mDownX = (int) ev.getX();
                mDownY = (int) ev.getY();
                mDownTime = (int) System.currentTimeMillis();
                stopScroll();
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                startScroll();//当手指抬起的时候开启自动轮播
                int upX = (int) ev.getX();
                int upY = (int) ev.getY();
                int upTime = (int) System.currentTimeMillis();
                int disX = Math.abs(upX- mDownX);
                int disY = Math.abs(upY - mDownY);
                //判断手指在屏幕上移动的距离和时间,如果时间在500毫秒之内,且移动的距离小于5就说明是单击事件
                if (disX<=5&&disY<=5&&upTime - mDownTime<=500){
                    //如果传进来的条目点击事件不为空,就执行条目点击事件
                    if (mOnItemClickListener !=null){
                        mOnItemClickListener.onItemClick(getCurrentItem());
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                //取消事件,当手指移出轮播图的区域后,开启轮播
                startScroll();
                break;
        }
        return super.onTouchEvent(ev);
    }
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    int currentItem = getCurrentItem();
                    currentItem++;
                    setCurrentItem(currentItem);
                    handler.sendEmptyMessageDelayed(1, 2000);//4s发送消息
                    break;
                default:
                    break;
            }
        }
    };
    public void startScroll() {
        //开启轮播之前先关闭轮播,以免混乱
        stopScroll();
        //开启轮播
        handler.sendEmptyMessageDelayed(1, 2000);//2s发送消息
    }
    public void stopScroll()
    {
        //关闭轮播,删除所有的handler消息
        handler.removeMessages(1);
    }
    public class MyPageChangeListener implements OnPageChangeListener {
        private OnPageChangeListener listener;
        private int position;
        public MyPageChangeListener(OnPageChangeListener listener) {
            this.listener = listener;
        }
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (listener != null)
                listener.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }
        @Override
        public void onPageSelected(int position) {
            this.position = position;
            if (listener != null)
                listener.onPageSelected(position);
        }
        @Override
        public void onPageScrollStateChanged(int state) {
            //状态改变的时候 调用    手指抬起的时候切换
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                //空闲切换
                // 页面切换   自动的切换到对应的界面    最后一个A----->第一个A
                if (position == getAdapter().getCount() - 1) {
                    //最后一个元素  是否平滑切换
                    setCurrentItem(1, false);
                } else if (position == 0) {
                    //是第一个元素{D] ----> 倒数第二个元素[D]
                    setCurrentItem(getAdapter().getCount() - 2, false);
                }
            }
            if (listener != null)
                listener.onPageScrollStateChanged(state);
        }
    }
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }
    /**
     * 轮播图页面的点击事件
     */
    public interface OnItemClickListener {
        void onItemClick(int position);
    }
    public class MyAdapter extends PagerAdapter {
        private PagerAdapter adapter;
        public MyAdapter(PagerAdapter adapter) {
            this.adapter = adapter;  //[ABCD]
        }
        @Override
        public Object instantiateItem(ViewGroup Container, int position) {
            //  position 已经是 [DABCDA] 的索引了
            // 修正后的索引 应该是 [ABCD]的索引
            //修正position
            if (position == 0) { //新增的D
                position = adapter.getCount() - 1;// 最后一个元素
            } else if (position == getCount() - 1) {  //最后一个元素 A
                position = 0;
            } else {
                position -= 1; //计算新的索引
            }
            return adapter.instantiateItem(Container, position);
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            adapter.destroyItem(container, position, object);
        }
        @Override
        public int getCount() {
            return adapter.getCount() + 2;
        }
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return adapter.isViewFromObject(view, object);
        }
    }
}

接着就是用法了,我们可以在布局中加入我们的轮播图布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    tools:context=".MainActivity">
    <com.example.administrator.mybanner.CycleViewPager
        android:id="@+id/banner"
        android:layout_width="match_parent"
        android:layout_height="200dp" />
    <LinearLayout
        android:id="@+id/ll_points"
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"></LinearLayout>

</RelativeLayout>

在activity中设置开启关闭轮播图,添加指示点:

package com.example.administrator.mybanner;

import android.app.Activity;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
    private CycleViewPager pager;
    private List<Integer> list = new ArrayList<>();
    private LinearLayout ll_point;
    private List<ImageView> list1;
    private Context _context;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this._context = this;
        initView();
        initData();
        initListener();
    }
    protected void initView() {
//找到我们的ViewPager和指示点的容器
        pager = (CycleViewPager) findViewById(R.id.banner);
        ll_point = (LinearLayout) findViewById(R.id.ll_points);
    }
    @Override
    public void onStart() {
        super.onStart();
//当activity可见的时候开启轮播图
        addPoint();
        pager.startScroll();
    }
    @Override
    public void onStop() {
        super.onStop();
//不可见的时候关闭轮播图
        pager.stopScroll();
    }
    protected void initData() {
//初始化轮播图数据
        if (list.size() == 0) {
            list.add(R.drawable.picture1);
            list.add(R.drawable.picture2);
            list.add(R.drawable.picture3);
            list.add(R.drawable.picture4);
        }
        addPoint();
        pager.setAdapter(new MyItemPagerAdapter(_context, list));
        pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }
            @Override
            public void onPageSelected(int position) {
                Log.i("页面改变了", position + "");
                //当页面改变的时候,改变圆点的样式
                for (int i = 0; i < list1.size(); i++) {
                    if (i == position - 1) {
                        list1.get(i).setImageResource(R.drawable.selected_point);
                    } else {
                        list1.get(i).setImageResource(R.drawable.default_point);
                    }
                }
            }
            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }
    private void addPoint() {
        //存放imageView
        list1 = new ArrayList();
        list1.clear();
        ll_point.removeAllViews();
        for (int i = 0; i < list.size(); i++) {
//遍历所有的指示点,设置当前被选中的页面的指示点为黑色,其他的为白色
            ImageView imageView = new ImageView(_context);
            if (i == 0) {
                imageView.setImageResource(R.drawable.selected_point);
            } else {
                imageView.setImageResource(R.drawable.default_point);
            }
            //给指示点添加一个间隔
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            params.leftMargin = 10;
            list1.add(imageView);
            ll_point.addView(imageView, params);
        }

    }

  protected void initListener() {

        pager.setOnItemClickListener(new CycleViewPager.OnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                //可以在这里做跳转的操作,当轮播图页面被点击的时候,就会响应
                Toast.makeText(_context, "跳转到详情界面", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

ViewPager的适配器类:

package com.example.administrator.mybanner;


import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by Administrator on 2016/11/3.
 */
public class MyItemPagerAdapter extends PagerAdapter {
    private List<Integer> list = new ArrayList<>();
    private Context _context;
    public MyItemPagerAdapter(Context context ,List<Integer> list) {
        this.list = list;
        this._context = context;
    }
    @Override
    public int getCount() {
        return list.size();
    }
    @Override
    public boolean isViewFromObject(View view, Object o) {
        return view == o;
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ImageView view =new ImageView(_context);
        view.setScaleType(ImageView.ScaleType.FIT_XY);


        Glide.with(_context).load(list.get(position)).into(view);
        container.addView(view);
        return view;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

//指示点的两种状态,这里是用shape画出来的:下面是默认状态

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<corners android:radius="@dimen/app_margin_0" />
    <gradient android:startColor="@color/white" android:endColor="@color/white"/>
    <size android:height="@dimen/point_size" android:width="@dimen/point_size"/>
</shape>

下面是页面被选中的时候的状态:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<corners android:radius="@dimen/app_margin_0" />
    <gradient android:startColor="@color/black" android:endColor="@color/black"/>
    <size android:height="@dimen/point_size" android:width="@dimen/point_size"/>
</shape>

下面的四张图是代码中的示例图片:


好了,轮播图这就完成了。代码下载地址:https://github.com/doudouyu/MyBanner

猜你喜欢

转载自blog.csdn.net/fishandbean/article/details/53006340