轮播图功能的全实现(自动播放、小点点、按住停止播放、放手后开始播放...)

MainActivity

/**
 * 1.实现了轮播图自动滚动效果<br>
 * 2.设置了跟随页面变化的小点点<br>
 * 3.解决了轮播图手指滑动后,显示页面错位的问题<br>
 * 4.实现了手指按住轮播图时,停止自动滚动的效果<br>
 * 5.实现了点击轮播图,跳转到相关页面的操作<br>
 */
public class MainActivity extends Activity {
    private ViewPager viewpager;
    private Context context = MainActivity.this;
    private MyAdapter myAdapter;
    private RunnableTask runnableTask = new RunnableTask();
    // 准备要显示的图片资源
    private int[] imageIdArray = { R.drawable.iv1, R.drawable.iv2,
            R.drawable.iv3, R.drawable.iv4 };
    // 准备title
    private String[] titleArray = { "中秋赏月", "倔强萝卜", "白色音符", "农夫果园" };
    // 轮播图显示的当前页
    private int currentPosition = 0;
    /**
     * 放置点的集合
     */
    private List<View> viewList = new ArrayList<View>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 找到ViewPager控件
        viewpager = (ViewPager) findViewById(R.id.viewpager);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // ★图片滚动的入口,为什么写在onResume方法里呢?
        // ★因为当view失去焦点时,停止滚动,在重新获取焦点时要继续滚动起来
        // ★如果写在onCreate方法里,只是activity第一次创建时才会滚动,一但停止滚动,再次获取焦点也不会滚动了
        startRoll();
        viewpager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int arg0) {
                //★★★★★ 当轮播图显示当前页时,一定要把currentPosition设为arg0,
                //★★★★★ 否则,当你用手指滑动轮播图时,放手后,轮播图显示的下一张页面是并不是当前显示页面的下一页
                // ★★★★★而是,他自己根据3秒钟计算得到的下一页
                currentPosition = arg0;
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
                // TODO Auto-generated method stub

            }
        });
    }

    /**
     * 让轮播图viewpager滚动起来
     */
    public void startRoll() {
        // 滚动viewpager
        if (myAdapter == null) {
            // 1.第一次初始化适配器
            myAdapter = new MyAdapter();
            viewpager.setAdapter(myAdapter);
        } else {// 8.第二次,只需要通知适配器数据发生了变化,要刷新Ui
            myAdapter.notifyDataSetChanged();
        }
        // 2.发送一个延时的消息,3秒后执行runnableTask类里run方法里的操作
        // ★(为什么执行的是runnableTask,而不是handleMessage呢?这里涉及到handler消息机制源码解析)
        handler.postDelayed(runnableTask, 3000);
    }

    class RunnableTask implements Runnable {
        @Override
        public void run() {
            // 3.变化轮播图当前要显示的页面位置,递增1,为了不使这个数字递增超过轮播图 图片的个数,取余数
            currentPosition = (currentPosition + 1) % titleArray.length;
            // 4.发送消息给主线程的handler
            handler.obtainMessage().sendToTarget();
        }
    }

    private Handler handler = new Handler() {
        // 5.接收并处理run方法发来的消息
        public void handleMessage(android.os.Message msg) {
            // 6.viewpager设置新的当前页
            viewpager.setCurrentItem(currentPosition);
            // 7.继续执行startRoll方法,成为一个循环
            startRoll();
        }
    };

    /**
     * ★当手指按住轮播图不动时,轮播图停止滚动;当点击轮播图时,跳转到相关界面
     */
    public void onTouchViewPager(View view, final int position) {
        // 给图片注册触摸事件监听器
        view.setOnTouchListener(new OnTouchListener() {

            private long downTime;
            private int downX;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:// 按下去时,记录按下的坐标和时间,用于判断是否是点击事件
                    handler.removeCallbacksAndMessages(null);// 手指按下时,取消所有事件,即轮播图不在滚动了
                    downX = (int) event.getX();
                    downTime = System.currentTimeMillis();
                    break;
                case MotionEvent.ACTION_UP:// 抬起手指时,判断落下抬起的时间差和坐标,符合以下条件为点击
                    // Toast.makeText(context, "手指抬起了", 0).show();
                    if (System.currentTimeMillis() - downTime < 500
                            && Math.abs(downX - event.getX()) < 30) {// ★考虑到手按下和抬起时的坐标不可能完全重合,这里给出30的坐标偏差
                        // 点击事件被触发
                        Toast.makeText(context,
                                "这里就不弹出对应页面了,您打开的是第" + position + "张图片", 0)
                                .show();
                    }
                    startRoll();
                    break;
                case MotionEvent.ACTION_CANCEL:
                    Toast.makeText(context, "滑动事件触发了", 0).show();
                    // ★写这个的目的为了让用户在手指滑动完图片后,能够让轮播图继续自动滚动
                    startRoll();
                    break;
                }
                return true;
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 移除所有的任务,即:view失去焦点时,停止轮播图的滚动
        handler.removeCallbacksAndMessages(null);
    }

    /**
     * 处理小点点,使得小点点随着轮播图的位置而改变颜色
     */
    private void initDot(LinearLayout dots_ll, int position) {
        // 必须每次进来清除线性布局里的所有小点点,不然,每次切换回页面,都运行initDot方法,会一直累加小点点,每次增加8个点
        dots_ll.removeAllViews();
        viewList.clear();
        // 遍历轮播图片的集合,每遍历一个,new一个view,给这个view设置背景图片,
        // 给包含小点点的父亲现形布局设置参数,设置间距,线性布局添加这些点,viewList也添加小点点
        for (int i = 0; i < imageIdArray.length; i++) {
            View view = new View(context);
            if (i == position) {
                view.setBackgroundResource(R.drawable.dot_focus);
            } else {
                view.setBackgroundResource(R.drawable.dot_normal);
            }

            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    CommonUtil.dip2px(context, 6),
                    CommonUtil.dip2px(context, 6));
            view.setLayoutParams(layoutParams);
            layoutParams.setMargins(5, 0, 5, 0);
            dots_ll.addView(view);
            viewList.add(view);
        }
    }

    /**
     * 适配器,要重写下面四个方法
     */
    class MyAdapter extends PagerAdapter {

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public int getCount() {
            return imageIdArray.length;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = View.inflate(context, R.layout.layout_roll_view, null);
            ImageView imageView = (ImageView) view.findViewById(R.id.image);
            imageView.setImageResource(imageIdArray[position]);
            TextView title = (TextView) view.findViewById(R.id.top_news_title);
            title.setText(titleArray[position]);
            LinearLayout dots_ll = (LinearLayout) view
                    .findViewById(R.id.dots_ll);
            // 处理小点点的操作
            initDot(dots_ll, position);
            // onTouchViewPager方法一定要写在instantiateItem内部,表示触摸的是当前位置的页面
            onTouchViewPager(view, position);
            // ★★★这句话很重要!!!别忘了写!!!
            ((ViewPager) container).addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            // ★★★这句话很重要!!!别忘了写!!!
            ((ViewPager) container).removeView((View) object);
        }
    }
}

----------

布局文件

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

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
    </android.support.v4.view.ViewPager>

</RelativeLayout>

item

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

    <!-- 放置轮播图片位置 -->

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY" >
    </ImageView>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="30dp"
        android:layout_alignParentBottom="true"
        android:background="#88000000"
        android:gravity="center_vertical"
        android:orientation="horizontal" >

        <!-- 放置图片标题的位置 -->

        <TextView
            android:id="@+id/top_news_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="8dp"
            android:layout_weight="1"
            android:singleLine="true"
            android:text="图片标题"
            android:textColor="#F6F6F6" />
        <!-- 放置图片中选中点的位置 -->

        <LinearLayout
            android:id="@+id/dots_ll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:gravity="center"
            android:orientation="horizontal" />
    </LinearLayout>

</RelativeLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值