1.首先我们需要一个相对布局装一个线性布局的容器和一个白色的小点作为选中的标识,用灰点表示未选中的情况。
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="230dp"/>
<RelativeLayout
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
<View
android:id="@+id/v_guide_white_point"
android:layout_width="8dp"
android:layout_height="8dp"
android:background="@drawable/shape_point_white"/>
</RelativeLayout>
两种颜色的小点的xml文件如下,使用自定义shape。
shape_point_gray.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/darker_gray"/>
</shape>
shape_point_white.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white"/>
</shape>
2.findViewById,其实轮播图大部分都是作为头布局的,所以我这就这样写了
View headerView = View.inflate(mActivity, R.layout.header_view_pager, null);
mViewPager = (ViewPager) headerView.findViewById(R.id.view_pager);
llContainer= (LinearLayout) headerView.findViewById(R.id.ll_container);//小点的容器
mWhiteView = headerView.findViewById(R.id.v_guide_white_point); //白点
3、根据viewpager数量动态添加小灰点
private void addPoints(int size) {
for (int i = 0; i < size; i++) {
//引导页下方的点
View point = new View(mActivity);
point.setBackgroundResource(R.drawable.shape_point_gray);
//设置圆点大小
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DensityUtil.dip2px(mActivity, 8), DensityUtil.dip2px(mActivity, 8));
if (i > 0) {
params.leftMargin = DensityUtil.dip2px(mActivity, 8);
}
point.setLayoutParams(params);
llContainer.addView(point);
}
}
4.在我们滑动的时候,需要让白点移动到另一个灰点上覆盖,需要知道这个距离,这个距离需要在我们的线性布局llContainer布局完成后才能获得。
//布局完成的监听事件
llContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mPointWidth = llContainer.getChildAt(1).getLeft() - llContainer.getChildAt(0).getLeft();
llContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
5.得到两个点之间的距离后,我们就需要在viewpager的监听事件中动态的更新白点的位置(也可以选择在onPageSelected()方法中在更新白点的位置),我们选择在onPageScrolled()方法中动态更新白点位置,这样还能看到动画的效果。
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//动态更新白点的位置
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mWhiteView.getLayoutParams();
params.leftMargin = (int) (mPointWidth * (position + positionOffset) + 0.5f);
mWhiteView.setLayoutParams(params);
}
@Override
public void onPageSelected(int position) {
mTvTitle.setText(newsBean.top_stories.get(position).title);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
其实上面一种方法比较坑,不管是实现无限轮播,还是自动轮播动态更新点的位置是一个坑。—>所以给我的感觉比较适合用在引导页中。
所以最方便方法还是使用两个小点的图片,在onPageSelected()中更换图片即可
1.也是先动态添加小点到容器中,一下方法都类似,所以简单说下
for (int i = 0; i < mData.size(); i++) {
//添加轮播图小点
View indicatorView = new View(UIUtils.getContext());
indicatorView.setBackgroundResource(R.drawable.indicator_normal);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DensityUtil.dip2px(UIUtils.getContext(), 5), DensityUtil.dip2px(UIUtils.getContext(), 5));
params.leftMargin = DensityUtil.dip2px(UIUtils.getContext(), 5);
params.bottomMargin = DensityUtil.dip2px(UIUtils.getContext(), 5);
indicatorView.setLayoutParams(params);
//默认选中第一个
if (i == 0) {
indicatorView.setBackgroundResource(R.drawable.indicator_selected);
}
mLinearLayout.addView(indicatorView);
2.监听事件
//监听滑动事件
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
for (int i = 0; i < mData.size(); i++) {
position = position % mData.size();
//还原背景
View indicatorView = mLinearLayout.getChildAt(i);
indicatorView.setBackgroundResource(R.drawable.indicator_normal);
if (i == position) {
indicatorView.setBackgroundResource(R.drawable.indicator_selected);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
3.实现无限轮播
//实现无限轮播的左边
int extra = Integer.MAX_VALUE / 2 % mData.size();
int index = Integer.MAX_VALUE / 2 - extra;
mViewPager.setCurrentItem(index);
//实现自动轮播
final AutoScrollTask autoScrollTask = new AutoScrollTask();
autoScrollTask.start();
//实现自动轮播点击不滑动,松开滑动
mViewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
autoScrollTask.stop();
break;
case MotionEvent.ACTION_UP:
autoScrollTask.start();
break;
default:
break;
}
return false;
}
});
}
class AutoScrollTask implements Runnable{
//开始轮播
private void start(){
UIUtils.postSafelyDelayed(this,2000);
}
//停止轮播
private void stop(){
UIUtils.removeTast(this);
}
@Override
public void run() {
int item = mViewPager.getCurrentItem();
++item;
mViewPager.setCurrentItem(item);
start();
}
}
4.viewpager的getCount()需要改变,以及所以涉及到position的地方需要改变
private class PictureAdapter extends PagerAdapter {
@Override
public int getCount() {
//实现无限轮播:对所有position的地方进行处理,防止越界
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
position = position % mData.size();
ImageView iv = new ImageView(UIUtils.getContext());
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setImageResource(R.drawable.ic_default);
BitmapHelper.display(iv, Constants.URLS.ICON + mData.get(position));
container.addView(iv);
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
public View getHolderView() {
return holderView;
}