网络上有很多无线循环的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也是重复使用的,因为这个数非常大,
所以你不会那么无聊,一直挂机,挂到他到底吧,所以就能模拟成无线循环,
而且界面的切换也是如丝般顺滑,我比较倾斜这个算法。
废话不说,直接代码上
小圆圈样式,少用图片吧,自己写个圆,很简单的。
<?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>
这是一个圈
<?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>
自定义一个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