ViewPager实现一个无限轮播的轮播图,对现有代码结构进行优化

代码写到这里我们发现代码结构看起来非常混乱,需要在主页面操作的地方很多,如果要改一项数据的话需要主页面和自定义类改好几个地方,我们的思路是尽可能的减少需要在主页面的操作,我们把能封装进自定义类的操作全都封装进自定义类。

因为我们在主页面操作自定义类的方法是setData

我们首先在自定义类创建一个继承pageradapter的静态抽象类适配器来代替setData方法内的适配器,然后把setData里面的自定义适配器的代码挪到这个类中,然后我们需要在主类中得到什么数据就用抽象方来强制获得,然后再在自定义类中操作。

首先是自定义类

    package com.example.viewpager.views;


    import android.content.Context;
    import android.graphics.Color;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Adapter;
    import android.widget.LinearLayout;
    import android.widget.TextView;

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.viewpager.widget.PagerAdapter;
    import androidx.viewpager.widget.ViewPager;

    import com.example.viewpager.R;


    public class LooperPager extends LinearLayout {


        private ViewPager viewPager;
        private TextView textView;
        private LinearLayout linearLayout;
        private BindTitleLisener bindTitleLisener = null;//标题,先设为空
        private nInnerAdapter Adapter = null;//适配器类型的变量

        public LooperPager(Context context) {
            this(context,null);
        }

        public LooperPager(Context context, @Nullable AttributeSet attrs) {
            this(context,attrs,0);
        }

        /**
         * java必须有一个声明super的构造器,而且必须在开头,所以其他构造器声明的this,、
         * 所以无论使用其他哪个构造器都必须要调用该构造器
         * @param context
         * @param attrs
         * @param defStyleAttr
         */
        public LooperPager(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //自定义布局绑定当前类,this:当前类,ture:确定绑定
            LayoutInflater.from(context).inflate(R.layout.looper_pager,this,true);
            inti();
        }

        /**
         *
         */

        private void inti() {
        intiView();
        initEven();
        }

        /**
         * 对页面进行滑动监听的方法
         */
        private void initEven() {
            viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                //切换的回调方法
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

                }

                @Override
                //切换停止的回调方法
                public void onPageSelected(int position) {

                    //当页面切换停止后获得标题
                    //如果标题不是空的,就设定标题为当前停止的页面标题里的数据
                    if (bindTitleLisener != null){

                        textView.setText(bindTitleLisener.getTitle(position));
                    }
                    //每次页面切换给指示器动态的添加焦点
                    setIndicaterPoint();
                }

                @Override
                //状态改变的回调方法
                public void onPageScrollStateChanged(int state) {

                }
            });
        }


        /**
         * 获得标题的接口,
         * 里面有一个获得标题的抽象方法
         * 一个获取集合长度的抽象方法
         */
        public interface BindTitleLisener{
            String getTitle(int position);

        }
        /**
         * 设置数据的方法
         */
        public void setData(nInnerAdapter adapter,BindTitleLisener lisener){
            bindTitleLisener = lisener;
            viewPager.setAdapter(adapter);
            //设定一个适配器类型的变量给下面的方法使用
            viewPager.setCurrentItem(Integer.MAX_VALUE/2 +1);
            this.Adapter = adapter;
            //可以得到数据的个数,然后根据数据的个数动态的创建圆点,indicater(指示器)
            setIndicaterPoint();

        }

        public abstract static class nInnerAdapter extends PagerAdapter{

            @Override
            public int getCount() {
                return Integer.MAX_VALUE;
            }

            @Override
            public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
                return view == object;
            }
            /**
             * 销毁
             * 作用是达到循环使用,不会导致溢出
             * @param container
             * @param position
             * @param object
             */
            @Override
            public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
                //删除数据
                container.removeView((View) object);

            }
            /**
             * 初始化
             * @param container
             * @param position
             * @return
             */
            @NonNull
            @Override
            public Object instantiateItem(@NonNull ViewGroup container, int position) {
              int  realPosition = position % getDataSize();
              //绑定抽象方法得到的布局
              View itemView = getSubView(container, realPosition);
              //把绑定的布局添加到适配器
              container.addView(itemView);
                return itemView;
            }

            /**
             * 抽象方法用来强制获得一个int类型的数据,
             * 也就是需要填入集合的长度
             * @return
             */
            protected abstract int getDataSize();

            /**
             * 抽象方法用来强制获得一个view数据
             * 抽象类调用时必须全部实现内部的抽象方法
             * @param container
             * @param position
             * @return
             */
            public abstract View getSubView(ViewGroup container, int position);
        }

        /**
         * 根据适配器的getCount方法的长度来动态的创建指示器
         * 同时每次页面切换的时候给当前页面的指示器换色
         */
        private void setIndicaterPoint() {
            if (Adapter != null&&bindTitleLisener!=null){
                int count = Adapter.getDataSize();
                linearLayout.removeAllViews();
                for (int i = 0; i < count ; i++) {
                    View view = new View(getContext());
                    //每次循环添加的时候判断下当前的圆点是否是代表当前页面,如果是就变成红色
                    if (viewPager.getCurrentItem()%Adapter.getDataSize() == i){
                        //设置颜色(Color.parseColor("#ff0000")设置颜色字符串为红色)
                        view.setBackgroundColor(Color.parseColor("#ff0000"));
                    }else{
                    //设置颜色(Color.parseColor("#ffffff")设置颜色字符串为白色)
                    view.setBackgroundColor(Color.parseColor("#ffffff"));
                    }
                    //设置指示器大小
                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
                            (SizeUtil.dip2px(getContext(),5),SizeUtil.dip2px(getContext(),5));
                    view.setLayoutParams(layoutParams);
                    //设置指示器之间的间距
                    layoutParams.setMargins(SizeUtil.dip2px(getContext(),10),0,SizeUtil.dip2px(getContext(),10),0);
                    //添加到容器里
                    linearLayout.addView(view);
                }
            }
        }

        /**
         * 加载view的方法
         */
        private void intiView() {
            viewPager = findViewById(R.id.viewPager);
            textView = findViewById(R.id.looper_title_tv);
            linearLayout = findViewById(R.id.looper_point_container_lv);
        }

    }

然后是主类

package com.example.viewpager;

import android.os.Bundle;
import android.os.PersistableBundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;

import com.example.viewpager.views.LooperPager;
import com.example.viewpager.views.PagerItem;

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

public class supper_MainActivity extends AppCompatActivity {

    private LooperPager looperPager;
    private List<PagerItem> list = new ArrayList<>();


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.supper_activity_main);
        intiData();//这里数据填充要写在加载组件上面,如果写在下面,需要在方法内部写上刷新数据的方法
        intiView();//加载组件的方法
    }

    /**
     * 填充数据
     */
    private void intiData(){
        list.add(new PagerItem("第一张图片",R.mipmap.img1));
        list.add(new PagerItem("第二张图片",R.mipmap.mig2));
        list.add(new PagerItem("第三张图片",R.mipmap.mig3));
        list.add(new PagerItem("第四张图片",R.mipmap.mig4));
    }
    private void intiView() {
        //绑定布局
        looperPager = findViewById(R.id.Looperpager);
        //设置数据
        looperPager.setData(new LooperPager.nInnerAdapter() {
            @Override
            protected int getDataSize() {
                return list.size();
            }

            @Override
            public View getSubView(ViewGroup container, int position) {
                ImageView imageView =  new ImageView(container.getContext());
                imageView.setImageResource(list.get(position).getPicResId());
                return imageView;

            }
        } , new LooperPager.BindTitleLisener() {
            @Override
            //获得当前位置图片的标题
            public String getTitle(int position) {
                return list.get(position % list.size()).getTitle();
            }


        });
    }
}

改完之后就发现我们的主页面简洁了很多,只需要操作时填入一个view数据一个集合长度就能得到一个可用的适配器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值