Android基础———ViewPager

来源:互联网 发布:人工智能会毁灭人类 编辑:程序博客网 时间:2024/05/20 13:08

ViewPager

可以用来做轮播,或者做fragment的滑动框架

一、简单的一个轮播

1.在布局文件layout里面写下viewpager控件    `<android.support.v4.view.ViewPager         android:id="@+id/viewpager"         android:layout_width="match_parent"         android:layout_height="match_parent">     </android.support.v4.view.ViewPager>`注意:viewpager是v4包里面的2.ViewPager也和listview这些控件类似,需要适配器来加载view,写一个适配器    public class MyAdapter extends PagerAdapter {        private List<ImageView> imageViewList;        public MyAdapter(List<ImageView> imageViewList) {            this.imageViewList = imageViewList;        }        /**         * 获取viewpager的数目         * @return         */        @Override        public int getCount() {            return imageViewList==null?0:imageViewList.size();        }        /**         *判断 返回的view和填充到viewpager的view是否一致 一致的才返回true         * @param view instantiateItem里面加入containerde的view         * @param object instantiateItem里面返回的值         */        @Override        public boolean isViewFromObject(View view, Object object) {            return view==object;        }        /**         * 加载item ,要显示的内容加载出来         * @param container  viewpager         * @param position   要加载的位置         * @return         */        @Override        public Object instantiateItem(ViewGroup container, int position) {            //获取当前要加载的图片            ImageView imageView=imageViewList.get(position);            container.addView(imageView);            return imageView;        }        /**         * 销毁view         * @param container  viewpager对象         * @param position  当前位置         * @param object    将要销毁的对象view         */        @Override        public void destroyItem(ViewGroup container, int position, Object object) {            //从viewpager中移除view            container.removeView((View)object);        }    }3.在activity里面加代码,和listview类似,获取数据源,传到适配器,设置适配器,下面代码,数据源为三张图片,已经加在资源文件中了,资源文件也可以是从网上获取public class MainActivity extends AppCompatActivity {    //图片id数组    private int[] ids={R.mipmap.pic1,R.mipmap.pic2,R.mipmap.pic3,R.mipmap.pic4};    private ViewPager viewPager;    private List<ImageView> imageViewList;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //获取viewpager控件        viewPager = (ViewPager)findViewById(R.id.viewpager);        //获取图片,把图片装入集合中        imageViewList = new ArrayList<>();        //给viewpager添加图片        for(int i=0;i<ids.length;i++){            //将图片加载到图片控件,然后加到图片集合中            ImageView imageView=new ImageView(this);            imageView.setImageResource(ids[i]);            imageViewList.add(imageView);        }        //加载适配器        viewPager.setAdapter(new MyAdapter(imageViewList));    }}

无限轮播

无限轮播需要注意的地方:会容易在移动view时崩溃,    崩溃的原因,是从右往左滑的时候是先移除后加载,而往回滑的时候是先加载后移除。解决崩溃主要思路:        在适配器里面设置getcount时,将返回的值设置为Integer.MAX_VALUE;             public int getCount() {                return Integer.MAX_VALUE;            }        因为这个count代表的viewpager一共有多少页view,如果填实际的数据源,在循环无限的轮播的时候容易出问题,        所以设置一个很大的数来,来充当数目。        在加载view时要注意,判断当前获取的imageview是否有父容器,如果有,则需要移除父容器,没有则添加到viewpager,        public Object instantiateItem(ViewGroup container, int position) {                int rightPosition = position % imageViewList.size();//实际应该加入viewpager里面的第几个条目                ImageView imageView = imageViewList.get(rightPosition);                if (imageView.getParent() == null) {//如果获取到的imageView没有父容器就不添加到viewPager                    container.addView(imageView);                } else {//如果有父容器,就改变标记                    isBack = true;                }                return imageView;            }        在销毁view时也要进行判断,判断是否为往左滑动,如果是,则不需要销毁view             //销毁view            @Override            public void destroyItem(ViewGroup container, int position, Object object) {                if (!isBack) {//不是往左边滑的,才移除                    container.removeView((View) object);                }                isBack=false;            }    以上操作的原因:        ViewPager在滑动时,每次加载时除了当前显示的视图,还会加载两个视图,前一个和后一个,        第一次加载时,前一个没有,只加载后一个,也只有这一次是例外。        但是每次加载前后两个图片的方式又根据滑动方式分为两种:        1、当你向右边滑动时,加载顺序是:先销毁上一个,再去加载下一个的下一个        2、当你向左边滑动时,加载顺序是:先加载上一个的上一个,在去销毁下一个        因为以上两种加载方式,就会导致在只有3张图的时候,出现程序崩溃。        比如有0 1 2 三张图,当前显示的是2,上一个是1和下一个0已经加载好了。                          此时向左滑动,显示1,先加载0,会发现0已经有父容器了,加载失败,程序崩溃....    在代码里面,当只有三张图的时候,可以再添加三张一样的图,这样就不会出现以上情况了、    代码如下:(包括了handler实现自动轮播,以及小白点)        public class Main2Activity extends AppCompatActivity {        private ViewPager viewPager2;        private List<ImageView> imageViewList;        private int[] ids = {R.mipmap.pic1, R.mipmap.pic2, R.mipmap.pic3};        private int lastPoint=0;//记录上一个小白点的位置        //实现自动轮播        private Handler handler = new Handler() {            @Override            public void handleMessage(Message msg) {                switch (msg.what) {                    case 111://定时轮播                        viewPager2.setCurrentItem(viewPager2.getCurrentItem() + 1);//设置轮播为下一页                        sendEmptyMessageDelayed(111, 2000);  //延迟两秒轮播                        break;                }            }        };        private LinearLayout pointLinearLayout;        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main2);            viewPager2 = (ViewPager) findViewById(R.id.viewpager2);            imageViewList = new ArrayList<>();            //用来放白点            pointLinearLayout=(LinearLayout)findViewById(R.id.pointLinearLayout);            //给list加imageview            createImageview(false);            //3张图以下,会因为viewpager不同方向滑动,加载方式不同而出现一些问题,所以此处可以判断一下,            // 如果只有三张或一下的图,则多加三张一样的图            if (imageViewList.size() <= 3) {                createImageview(true);            }            viewPager2.setAdapter(new MyAdapterInfinite(imageViewList));            //初始将viewpager设置在中间,这样才可以往左边滑动            //Integer.MAX_VALUE/2-Integer.MAX_VALUE/2%imageViewList.size() 这个不仅取到了中间,而且取到了第一张图            //Integer.MAX_VALUE/2%imageViewList.size() 表示 中间那个位置的图片是实际的第几张图片,然后减去数,就是第0张图片也就是第一张图片            viewPager2.setCurrentItem(Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % imageViewList.size());            handler.sendEmptyMessage(111);            //viewpager的页面监听            viewPager2.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {                /**                 * 当页面滑动的时候                 *                 * @param position             当前正在滑动的那一页下标                 * @param positionOffset       滑动的偏移量 百分比 已经滑动了多少了                 * @param positionOffsetPixels 滑动的偏移量(像素),当前总共滑动了多少像素                 */                @Override                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {                }                /**                 * 页面被选择时                 * @param position 当前页面的位置                 */                @Override                public void onPageSelected(int position) {                    //用当前位置去求模得到小白点的位置,这里取余应该用ids,不能用imageviewlist,                    //因为图片有可能会有复制的                    int pointPosition=position%ids.length;                    //获取小白点,并设置值                    pointLinearLayout.getChildAt(pointPosition).setEnabled(false);                    //改变上一个小白点的状体                    pointLinearLayout.getChildAt(lastPoint).setEnabled(true);                    //设置lastpoint的值为当前页面小白点                    lastPoint=pointPosition;                }                /**                 * 页面滑动的状态发生变化的时候                 *                 * @param state 包含拖动1 SCROLL_STATE_DRAGGING,                 *              惯性滚动2 SCROLL_STATE_SETTLING,                 *              停止0SCROLL_STATE_IDLE                 */                @Override                public void onPageScrollStateChanged(int state) {                }            });            //viewpager的触摸监听            viewPager2.setOnTouchListener(new View.OnTouchListener() {                /**                 * 当触摸的时候停止轮播                 * @param view 当前的view页面                 * @param motionEvent 事件类型,按下,松开                 * @return                 */                @Override                public boolean onTouch(View view, MotionEvent motionEvent) {                    if(motionEvent.getAction()== MotionEvent.ACTION_DOWN){//按下                        handler.removeMessages(111);//移除handler                    }else if(motionEvent.getAction()==MotionEvent.ACTION_UP){                        handler.sendEmptyMessageDelayed(111,2000);                    }                    return false;                }            });        }        //用来把图片加载到list        //使用isCopy来判断是否是复制的数据,即图片数量小于等于3的时候        private void createImageview(boolean isCopy) {            for (int i = 0; i < ids.length; i++) {                ImageView imageView = new ImageView(this);                imageView.setImageResource(ids[i]);                imageViewList.add(imageView);                if (!isCopy) {//图片资源不是复制的,就生产小白点                    View view = new View(this);                    view.setBackgroundResource(R.drawable.selector);//设置背景色                    if (i == 0) {//如果是第一个则设置为红色                        view.setEnabled(false);                    }                    //将当前位置加入到tag,下次点击事件可以使用                    view.setTag(i);                    //加入小白点到线性布局                    view.setOnClickListener(new View.OnClickListener() {                        /**                         * 小白点的点击监听                         * @param view                         */                        @Override                        public void onClick(View view) {                            //获取点击的小白点的位置                            int pointposition=(int)view.getTag();                            //获取当前点击小白点位置和上个小白点的位置差                            int sub=pointposition-lastPoint;                            //viewpager当前页面去加上差值,就是点击了小白点后要显示的页面                            viewPager2.setCurrentItem(viewPager2.getCurrentItem()+sub);                        }                    });                    LinearLayout.LayoutParams layoutParams=new LinearLayout.LayoutParams(44,44);                    layoutParams.rightMargin=10;                    pointLinearLayout.addView(view,layoutParams);                }            }        }    }    除了上面的一种方法:还可以在适配器里面,每次加载图片都new一个出来,而不是去源数据中获取已经存好了的imageview。    代码如下:         @Override        public Object instantiateItem(ViewGroup container, int position) {            ImageView imageView = new ImageView(container.getContext());            imageView.setScaleType(ImageView.ScaleType.FIT_XY);            imageView.setImageResource(ids[position%ids.length]);            container.addView(imageView);            return imageView;        }    但是这样特别浪费内存.建议用上面的一种

TabLayout

一种可以与viewpager结合使用,很暴力的控件,需要添加一个依赖,因为是另外一个包里面的1.在xml布局文件里面写    <android.support.design.widget.TabLayout        android:id="@+id/tabLayout"        android:layout_width="match_parent"        android:layout_height="wrap_content"        app:tabIndicatorHeight="10dp"        app:tabSelectedTextColor="#fff"        app:tabMode="scrollable"        android:background="@drawable/shape"        app:tabIndicatorColor="#0f0"        app:tabTextColor="#00f"        ></android.support.design.widget.TabLayout>    属性:    tabIndicatorColor 下标指示器的颜色    tabIndicatorHeight 下标指示器的高度    tabTextColor tab 上面的文件的颜色    tabSelectedTextColor 被选中的 tab的上面的字的颜色2.在代码里面,viewpager的加载如上面一致,tablayout控件的设置,需要将获取到的TabLayout控件与viewpager联动,     //将tablayout与viewpager设置联动    tabLayout.setupWithViewPager(viewPager);但是有一个问题,设置联动之后,如果给tablayout的tab设置了tag,与哪个 viewpager 保持联动, 这行代码会导致所有的 tab被删除然后重新添加,所以上面的属性都会被回收。所以想要tag生效,必须在最后再添加一次tag。3.想要tablayout的文字显示出来,需要在viewpager的adapter里面重写一个方法     @Override    public CharSequence getPageTitle(int position) {        return ss.get(position);    }    这个方法会把文字添加进去。

viewpager结合fragment

1.只是适配器不同了,viewpager里面放fragment时,适配器不是pageadapter,而是用FragmentStatePagerAdapter和FragmentPageAdapter里面重写的方法也很简单,只有两个。2.在代码里面的实现很简单,    public class MainActivity extends AppCompatActivity {    private ViewPager viewPager;    private List<Fragment> fragmentList;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //获取viewpager        viewPager = (ViewPager)findViewById(R.id.viewpager);        //创建fragment        fragmentList = new ArrayList<>();        MyFragment myFragment = new MyFragment();        MyFragment2 myFragment2 = new MyFragment2();        MyFragment3 myFragment3 = new MyFragment3();        MyFragment4 myFragment4 = new MyFragment4();        //添加数据源        fragmentList.add(myFragment);        fragmentList.add(myFragment2);        fragmentList.add(myFragment3);        fragmentList.add(myFragment4);        //给viewpager设置适配器        /*        FragmentManager fm=getSupportFragmentManager();        viewPager.setAdapter(new MyAdapter(fm,fragmentList));        */        //另外一种适配器        viewPager.setAdapter(new MyAdapterFragmentState(getSupportFragmentManager(),fragmentList));        viewPager.setOffscreenPageLimit(2);//前后各加载2个    }}3.viewpager 里面可以设置前后加载图片的数量,setOffscreenPageLimit viewPager.setOffscreenPageLimit(2);//前后各加载2个好像最多可以设置为3,即前后加载3张,每次加载7张图
0 0