UI 效果Android开发Android知识

无限循环的ViewPager

2016-08-19  本文已影响681人  进击的包籽

网络上有很多无线循环的Viewpager,但是学习嘛,就自己写了一个无线循环的ViewPager。

思路一
网上有一种是真正意义的无限循环,比如View0,View1,View2,View3, 4个View,
在View0左侧加一个View3,View3右侧加一个View0,
就成了View3-2, View0,View1,View2,View3, View0-2,
View3向右滑动,显示的是View0-2,viewPager.setCurrentItem(position,fasle)这个方法跳到View0,
同理View0左滑,显示的是View3-2,同样跳到View3,
这个方法的缺点就是,View0到View3滑动时流畅的,但是View3到View0,是瞬间变化的,不好看。

思路二
Adapter,getCount()设置为 Integer.MAX_VALUE ,这是一个非常非常大的数,
然后我们一进去就取中间值,无论左滑还是右滑,都能不停的循环加载View,
这些view也是重复使用的,因为这个数非常大,
所以你不会那么无聊,一直挂机,挂到他到底吧,所以就能模拟成无线循环,
而且界面的切换也是如丝般顺滑,我比较倾斜这个算法。


LoopView.gif

废话不说,直接代码上
小圆圈样式,少用图片吧,自己写个圆,很简单的。

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

这是一个圆

<?xml version="1.0" encoding="utf-8"?>
<shape   
     android:shape="oval"    
     xmlns:android="http://schemas.android.com/apk/res/android">  
  <solid        
    android:color="#FFFFFF"/>  
  <size        
    android:width="15dp"        
    android:height="15dp"/>
</shape>
圆.jpg

这是一个圈

<?xml version="1.0" encoding="utf-8"?>
<shape    
    android:shape="oval"    
    xmlns:android="http://schemas.android.com/apk/res/android">    
<solid        
    android:color="#22FFFFFF"/>    
<stroke       
     android:width="1dp"        
    android:color="#FFFFFF"/>    
<size        
    android:width="15dp"        
    android:height="15dp"/>
</shape>
圈.jpg

自定义一个Adapter,要想使用LoopView。一定要使用该Adapter

import android.support.v4.view.PagerAdapter;
 
/**
 * 要用LoopView一定要使用这个Adapter
 */
public abstract class MyLoopViewAdapter extends PagerAdapter
{
    /**
     * 返回真实的view数
     */
    public abstract int getRealCount();
}
public class LoopViewAdapter extends MyLoopViewAdapter
{
    private ArrayList<View> views = new ArrayList<>();
 
    public LoopViewAdapter()
    {
    }
 
    public LoopViewAdapter(ArrayList<View> views)
    {
        this.views = views;
    }
 
    /**
     * 在下标position处添加View
     */
    public void insertView(View view, int position)
    {
        if (view != null)
        {
            this.views.add(position, view);
            notifyDataSetChanged();
        }
    }
 
    /**
     * 在尾部添加view
     */
    public void insertView(View view)
    {
        if (view != null)
        {
            this.views.add(view);
            notifyDataSetChanged();
        }
    }
 
    /**
     * 获取view
     */
    public View getView(int position)
    {
        return this.views.get(position);
    }
 
    @Override
    public int getCount()
    {
        //设置为一个很大很大的数
        return Integer.MAX_VALUE;
    }
 
    @Override
    public int getRealCount()
    {
        return views.size();
    }
 
    @Override
    public Object instantiateItem(final ViewGroup container, int position)
    {
        final View view = views.get(position % (views.size()));
 
        //在主线程添加
        container.post(new Runnable()
        {
            @Override
            public void run()
            {
                container.removeView(view);
                container.addView(view);
            }
        });
 
        return view;
    }
 
    @Override
    public void destroyItem(ViewGroup container, int position, Object object)
    {
    }
 
    @Override
    public boolean isViewFromObject(View view, Object object)
    {
        return view == object;
    }
}

自动轮播的Viewpager,默认情况下自动循环,时间间隔为2000毫秒


/**
 * 自动轮播Viewpager
 */
public class LoopViewPager extends RelativeLayout implements ViewPager.OnPageChangeListener
{
    //底部小圆圈的样式
    private int dotRes = -1;
    //图片轮转周期
    private int period = 2000;
    private static final int ADVERTISEMENT = 1;
    private NoScrollViewPager noScrollViewpager;
    private RadioGroup radioGroup;
    private LoopViewAdapter loopViewAdapter;
 
    public LoopViewPager(Context context)
    {
        this(context, null);
    }
 
    public LoopViewPager(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }
 
    public LoopViewPager(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        init();
    }
 
    private Handler handler = new Handler(new Handler.Callback()
    {
        @Override
        public boolean handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case ADVERTISEMENT:
                    viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
                    handler.sendEmptyMessageDelayed(ADVERTISEMENT, period);
                    break;
                default:
                    break;
            }
            return false;
        }
    });
 
    /**
     * 初始化控件
     */
    private void init()
    {
        noScrollViewpager = new NoScrollViewPager(getContext());
        noScrollViewpager.addOnPageChangeListener(this);
       //允许滑动
       noScrollViewpager.setScrollable(true);
 
        radioGroup = new RadioGroup(getContext());
        //设置RadioGroup为水平排列
        radioGroup.setOrientation(RadioGroup.HORIZONTAL);
 
        //让viewpager填充满怎个布局
        RelativeLayout.LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT
                , LayoutParams.MATCH_PARENT);
        viewPager.setLayoutParams(params);
        addView(viewPager);
 
        //设置radioGroup包裹内容
        params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        //设置为水平居中
        params.addRule(CENTER_HORIZONTAL);
        //设置为父布局的底部
        params.addRule(ALIGN_PARENT_BOTTOM);
        radioGroup.setLayoutParams(params);
        addView(radioGroup);
    }
 
    /**
     * 设置小圆点的样式
     */
    public void setDotRes(int dotRes)
    {
        this.dotRes = dotRes;
        if (dotRes == 0)
        {
            return;
        }
        for (int i = 0; i < radioGroup.getChildCount(); i++)
        {
            radioGroup.getChildAt(i).setBackgroundResource(dotRes);
        }
    }
 
    /**
     * 设置底部小圆点RadioGroup是否可见
     */
    public void setDotVisible(boolean visible)
    {
        if (visible)
        {
            radioGroup.setVisibility(VISIBLE);
        } else
        {
            radioGroup.setVisibility(GONE);
        }
    }
 
    /**
     * 设置轮播间隔
     */
    public void setPeriod(int period)
    {
        this.period = period;
    }
 
    /**
     * 设置是否开始滚动
     */
    public void startLoop()
    {
        //先移除,防止重复加载
        stopLoop();
        //发送延时消息
        handler.sendEmptyMessageDelayed(ADVERTISEMENT, period);
    }
 
    /**
     * 停止滚动
     */
    public void stopLoop()
    {
        handler.removeMessages(ADVERTISEMENT);
    }

   /**
      * 设置ViewPager是否允许手动滑动
      */
    public void setViewPagerScrollable(boolean scroll)
    {    
        noScrollViewpager.setScrollable(scroll);
    }
 
    /**
     * 返回当前页码
     */
    public int getCurrentItem()
    {
        return viewPager.getCurrentItem() % loopViewAdapter.getRealCount();
    }
 
    /**
     * 设置适配器
     */
    public void setAdapter(LoopViewAdapter adapter)
    {
        if (adapter == null)
        {
            return;
        }
        this.loopViewAdapter = adapter;
        int count = adapter.getRealCount();
 
        //根据适配器的图片数量,设置小圆点的数量
        for (int i = 0; i < count; i++)
        {
            RadioButton radioButton = new RadioButton(getContext());
            //给RadioButton一个空的BitmapDrawable对象,骗过setButtonDrawable的过滤,实际上绘制的时候是没有图片资源
            //将RadioButton的小圆点去掉
            radioButton.setButtonDrawable(new ColorDrawable());
            //设置不能点击
            radioButton.setEnabled(false);
            //设置小圆点的尺寸
            RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(15, 15);
            //设置小圆点的间距
            params.setMargins(0, 0, 10, 20);
            radioButton.setLayoutParams(params);
 
            //设置背景样式
            if (dotRes != -1)
            {
                radioButton.setBackgroundResource(dotRes);
            } else
            {
                radioButton.setBackgroundResource(R.drawable.advertisement_circle);
            }
            radioGroup.addView(radioButton);
        }
 
        //第一个显示为已选定
        RadioButton radioButton = (RadioButton) radioGroup.getChildAt(0);
        radioButton.setChecked(true);
 
        viewPager.setAdapter(loopViewAdapter);
        //设置viewPager切换动画
        viewPager.setPageTransformer(true, new DepthPageTransformer());
        //每次打开都会显示Viewpager第一页
        viewPager.setCurrentItem((loopViewAdapter.getCount() / 2) -
                (loopViewAdapter.getCount() / 2) % loopViewAdapter.getRealCount());
        //开始循环
        startLoop();

       //不显示小圆点,不能滑动,不循环
       if (count == 1)
       {    
           setDotVisible(false);    
           stopLoop();    
           noScrollViewpager.setScrollable(false);     
           noScrollViewpager.setCurrentItem(0);
       }
    }
 
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
    {
    }
 
    @Override
    public void onPageSelected(int position)
    {
        RadioButton radioButton = (RadioButton) radioGroup
                .getChildAt(position % loopViewAdapter.getRealCount());
        radioButton.setChecked(true);
    }
 
    @Override
    public void onPageScrollStateChanged(int state)
    {
        switch (state)
        {
            //手拖住就停止计时
            case ViewPager.SCROLL_STATE_DRAGGING:
                stopLoop();
                break;
            //松开继续继续计时
            case ViewPager.SCROLL_STATE_IDLE:
                startLoop();
                break;
            default:
                break;
        }
    }
}

使用,里面的view都是自定义的

public class LoopViewPagerActivity extends AppCompatActivity
{
    private LoopViewPager loopViewPager;
    private LoopViewAdapter loopViewAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view);
        initView();
    }
    private void initView()
    {
        loopViewPager = (LoopViewPager) findViewById(R.id.advertisementViewPager);
        //设置间隔
        loopViewPager.setPeriod(3000);
        initAdapter(getImages());
        loopViewPager.setAdapter(loopViewAdapter);
    }
    private void initAdapter(ArrayList<String> images)
    {
        final ArrayList<View> views = new ArrayList<>();
        for (int i = 0; i < 5; i++)
        {
            View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
            final TextView textView = (TextView) view.findViewById(R.id.item_tv);
            textView.setText("Mo.nica " + i);
            ImageView imageView = (ImageView) view.findViewById(R.id.item_image);
            //Glide加载图片
            Glide.with(getApplicationContext())
                    .load(images.get(i))
                    .into(imageView);
            textView.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    Toast.makeText(LoopViewPagerActivity.this, textView.getText().toString(), Toast.LENGTH_SHORT).show();
                }
            });
            view.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    Toast.makeText(LoopViewPagerActivity.this, "" + loopViewPager.getCurrentItem(), Toast.LENGTH_SHORT).show();
                    if (loopViewPager.getCurrentItem() == views.size() - 1)
                    {
                        finish();
                    }
                }
            });
            views.add(view);
        }
        loopViewAdapter = new LoopViewAdapter(views);
    }
    private ArrayList<String> getImages()
    {
        ArrayList<String> images = new ArrayList<>();
        images.add("http://download.pchome.net/wallpaper/pic-9468-1.jpg");
        images.add("http://img5.duitang.com/uploads/item/201506/14/20150614215810_ckiPE.jpeg");
        images.add("http://bizhi.cnanzhi.com/upload/bizhi/2014/1202/1417503024216.png");
        images.add("http://img4.duitang.com/uploads/item/201511/09/20151109150254_EFTmw.jpeg");
        images.add("http://img1.3lian.com/2015/w22/99/d/86.jpg");
        images.add("http://cdn.duitang.com/uploads/item/201504/09/20150409H0455_dSNH4.jpeg");
        return images;
    }}


ViewPager切换也是有动画的,这个是看鸿洋大神的
http://blog.csdn.net/lmj623565791/article/details/40411921

public class DepthPageTransformer implements ViewPager.PageTransformer
{
    private static final float MIN_SCALE = 0.75f;
 
    public void transformPage(View view, float position)
    {
        int pageWidth = view.getWidth();
 
        if (position < -1)
        { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);
 
        } else if (position <= 0)
        { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);
 
        } else if (position <= 1)
        { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);
 
            // Counteract the default slide transition
            view.setTranslationX(pageWidth * -position);
 
            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
 
        } else
        { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

最后附件,上传不了啊,算了,全部代码都在,没有大牛写的厉害,但是一起学习吧
源码下载地址:http://download.csdn.net/detail/u013365445/9608109

Github:https://github.com/Goodbao/LoopViewPager

上一篇下一篇

猜你喜欢

热点阅读