带指示点的无限轮播(直接可以向左滑,速度稳定,时间久了速度也不会变)

本文介绍了一种基于Android平台的无限轮播图实现方案,包括自定义View组件、页面自动轮播逻辑、触摸事件处理以及指示点和数字角标同步更新的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码稍做修改可实现的效果:

    

无限轮播的分析图  :指示点及图片显示角标的对照

   

直接 贴代码

package myapp.first.myapplication.view;

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 xi on 2016/7/9.
 */
public class RollViewPager extends ViewPager {
    public RollViewPager(Context context) {
        super(context);
    }

    public RollViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void addOnPageChangeListener(OnPageChangeListener listener) {
        MyPageChangeListener myPageChangeListener = new MyPageChangeListener(listener);
        super.addOnPageChangeListener(myPageChangeListener);
    }

    @Override
    public void setAdapter(PagerAdapter adapter) {
        //  修正  adapter 中position
        MyAdapter myAdapter = new MyAdapter(adapter);
        addOnPageChangeListener(null); //手动增加一个监听
        super.setAdapter(myAdapter);
        setCurrentItem(1);
        //开启自动轮播
        startScroll();//自动轮播
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //手指触摸  按下 停止轮播  抬起继续轮播
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                stopScroll();
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_CANCEL://取消事件
            case MotionEvent.ACTION_UP:
                startScroll();
                break;
        }

        return super.onTouchEvent(ev);
    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int currentItem = getCurrentItem();
            currentItem ++;
            setCurrentItem(currentItem);
            handler.sendEmptyMessageDelayed(1, 4000);//4s发送消息
        }
    };

    public void startScroll() {
        //开启轮播
        handler.sendEmptyMessageDelayed(1, 4000);//4s发送消息
    }

    public void stopScroll(){
        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 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);
        }
    }
}

轮播布局的xml:

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

    <myapp.first.myapplication.view.RollViewPager
        android:id="@+id/roll_viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <include layout="@layout/ll_roll_point"/>
    <!--<include layout="@layout/ll_roll_number"/>-->

</FrameLayout>

下面为指示点时  指示点的 xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_point"
    android:gravity="bottom|center_horizontal"
    android:layout_gravity="bottom"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00000000"
    android:layout_marginBottom="8dp"
    android:orientation="horizontal">

</LinearLayout>

右下角为圆圈数字的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="45dp"
    android:layout_height="45dp"
    android:gravity="center"
    android:layout_gravity="right|bottom"
    android:paddingTop="5dp"
    android:layout_marginBottom="11dp"
    android:layout_marginRight="13dp"
    android:id="@+id/ll_roll_number"
    android:background="@drawable/roll_circle_conner">
        <TextView
            android:id="@+id/tv_current_number"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:textSize="20dp"
            android:layout_marginBottom="3dp"
            android:text="1"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:textSize="18dp"
            android:text="/"/>
        <TextView
            android:id="@+id/tv_count_number"
            android:textColor="#ffffff"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="n"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/chu"
            android:layout_toEndOf="@+id/chu" />

</LinearLayout>

适配器:

package myapp.first.myapplication.adapter;

import android.content.Context;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.bumptech.glide.Glide;

import java.util.List;

import myapp.first.myapplication.R;

/**
 * @Author Xi
 * Created by zz.wbkj.xi on 2016/8/15.
 */
public class RollViewPagerAdapter extends BasePagerAdapter<Integer> {

    public RollViewPagerAdapter(Context context, List<Integer> dataList) {
        super(context, dataList);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ImageView imageView = new ImageView(mContext);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        container.addView(imageView);
        Glide.with(mContext)
                .load(dataList.get(position))
//                .load(R.mipmap.ic_launcher)
//                .placeholder(R.mipmap.not_login_bg)
//                .error(R.mipmap.not_login_bg)
                .into(imageView);
//        Glide.with(mContext).load(NetPath.BASE_IMG_PATH+dataList.get(position).getPath()).into(imageView);
//        LogUtils.e(mContext,"加载轮播图",position+"");
        return imageView;
    }
}

BasePagerAdapter:

package myapp.first.myapplication.adapter;

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

import java.util.List;

/**
 * @Author Xi
 * Created by zz.wbkj.xi on 2016/8/13.
 */
public abstract class BasePagerAdapter<T> extends PagerAdapter {

    public Context mContext;
    public List<T> dataList;

    public BasePagerAdapter(Context context , List<T> dataList) {
        this.mContext = context;
        this.dataList = dataList;
    }

    @Override
    public int getCount() {
        return dataList.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
    @Override
    public abstract Object instantiateItem(ViewGroup container, int position) ;
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }


}

工具类:

package myapp.first.myapplication.tools;

import android.content.Context;

/**
 * @Author Xi
 * Created by zz.wbkj.xi on 2016/8/15.
 */
public class DensityUtil {

        /**
         * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
         */
        public static int dip2px(Context context, float dpValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }

        /**
         * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
         */
        public static int px2dip(Context context, float pxValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (pxValue / scale + 0.5f);
        }
}

package myapp.first.myapplication.tools;

import android.content.Context;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;


import java.util.List;

import myapp.first.myapplication.R;
import myapp.first.myapplication.adapter.RollViewPagerAdapter;
import myapp.first.myapplication.listener.RollViewPagerOnPageChangeListener;
import myapp.first.myapplication.view.RollViewPager;

/**
 * @Author Xi
 * Created by zz.wbkj.xi on 2016/8/16.
 */
public class RollUtils {

    private static LinearLayout.LayoutParams layoutParams;

    /***
     *  处理轮播点
     * @param mContext
     * @param rollList
     * @param ll_point
     * @param pointSelectorResourceId
     * @param rollViewPager
     */
    public static void dealPoint(Context mContext,List rollList, LinearLayout ll_point,  int pointSelectorResourceId, RollViewPager rollViewPager){
        ll_point.removeAllViews();
        if (rollList.size()!=0) {
            for (int i = 0; i < rollList.size(); i++) {
                ImageView point = new ImageView(mContext);
//                point.setBackgroundResource(R.drawable.point_selector);
                point.setBackgroundResource(pointSelectorResourceId);
                if (i == 0)
                    point.setEnabled(true);
                else {
                    point.setEnabled(false);
                }
                if (layoutParams == null)
                    layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                layoutParams.rightMargin = DensityUtil.dip2px(mContext, Float.valueOf(mContext.getResources().getString(R.string.point_margin)));
                //            layoutParams.rightMargin = DensityUtil.px2dip(mContext,Float.valueOf(15));
                ll_point.addView(point, layoutParams);
            }
//            LogUtils.e(mContext, "添加指示点", "");
        }
        rollViewPager.addOnPageChangeListener(new RollViewPagerOnPageChangeListener(mContext,rollList,ll_point));
//        rollViewPager.setCurrentItem(0);
    }

    /***
     *  处理数字
     * @param mContext
     * @param rollList
     * @param tv_count_number
     * @param tv_current_number
     * @param rollViewPager
     */
    public static void dealNumber(Context mContext,List rollList, TextView tv_count_number,TextView tv_current_number,  RollViewPager rollViewPager){
        tv_count_number.setText(String.valueOf(rollList.size()));
        rollViewPager.addOnPageChangeListener(new RollViewPagerOnPageChangeListener(mContext,rollList,tv_current_number));
    }

}

重写的页面改变监听:

package myapp.first.myapplication.listener;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.widget.LinearLayout;
import android.widget.TextView;

//import com.basedemo.my.xi.basedemo.utils.LogUtils;

import java.util.List;

/**
 * @Author Xi
 * Created by zz.wbkj.xi on 2016/8/16.
 */
public class RollViewPagerOnPageChangeListener implements ViewPager.OnPageChangeListener {

    private Context mContext;
    private LinearLayout ll_point;
    private List rollList;
    private int lastPosition ;
    TextView tv_currentNumber;
    boolean isPoint;
    boolean isNumber;

    public RollViewPagerOnPageChangeListener(Context context , List rollList, LinearLayout ll_point) {
        this.mContext = context;
        this.rollList = rollList;
        this.ll_point = ll_point;
        isPoint = true;
        isNumber = false;
    }

    public RollViewPagerOnPageChangeListener(Context context , List rollList, TextView tv_currentNumber) {
        this.mContext = context;
        this.rollList = rollList;
        this.tv_currentNumber = tv_currentNumber;
        isNumber = true;
        isPoint = false;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        if (isPoint) {
            if (rollList.size() != 0) {
                position = position % rollList.size();
                if (position != 0){
                    position = position -1;
                }else {
                    position = rollList.size()-1;
                }
                ll_point.getChildAt(lastPosition).setEnabled(false);
                ll_point.getChildAt(position).setEnabled(true);
                lastPosition = position;
            }
        }else if (isNumber){
            if (position > rollList.size()) {
                position = 1;
            } else if (position == 0) {
                position = rollList.size();
            }
            tv_currentNumber.setText(String.valueOf(position));
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

使用:

package myapp.first.myapplication.ui;

import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import myapp.first.myapplication.R;
import myapp.first.myapplication.adapter.RollViewPagerAdapter;
import myapp.first.myapplication.base.MyBaseFragment;
import myapp.first.myapplication.tools.RollUtils;
import myapp.first.myapplication.view.RollViewPager;

/**
 * Created by Administrator on 2016/10/7 0007.
 */

public class FragmentRbtn2 extends MyBaseFragment {

    private LinearLayout ll_fragment2;

    @Override
    public void init() {

    }

    @Override
    public int getLayoutResID() {
        return R.layout.fragment_rbtn2;
    }
    List<Integer> list = new ArrayList<>();
    @Override
    public void initView(View view) {
        ll_fragment2 = (LinearLayout) view.findViewById(R.id.ll_fragment2);
        View rollView = LayoutInflater.from(mContext).inflate(R.layout.rollviewpager,null);
        RollViewPager rollViewPager = (RollViewPager) rollView.findViewById(R.id.roll_viewpager);
        LinearLayout ll_point = (LinearLayout) rollView.findViewById(R.id.ll_point);
//        TextView tv_current_number = (TextView) rollView.findViewById(R.id.tv_current_number);
//        TextView tv_count_number = (TextView) rollView.findViewById(R.id.tv_count_number);
        ll_fragment2.addView(rollView);
        list.clear();
        list.add(R.mipmap.lambo);
        list.add(R.mipmap.wheel);
        list.add(R.mipmap.zhanweitu);
        rollViewPager.setAdapter(new RollViewPagerAdapter(mContext,list));
        RollUtils.dealPoint(mContext,list,ll_point,R.drawable.point_selector,rollViewPager);
//        RollUtils.dealNumber(mContext,list,tv_count_number,tv_current_number,rollViewPager);
    }

    @Override
    public void initData() {

    }

    @Override
    public void initListener() {

    }
}


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:drawable="@mipmap/dian_off"/>
    <item android:state_enabled="true" android:drawable="@mipmap/dian_on"/>
</selector>


数字圆 的 conner

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="30dp"
        />
    <solid android:color="#c6c7cc"
        />
    <stroke android:width="0dp" android:color="#00000000"/>
</shape>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值