最近一个项目中有这样一个需求,就是一个ViewPager,下面带有几个指示器的小圆点,这样的需求很容易实现,网上也有很多的开源框架都可以满足这个需求,但是最近已经不太想用开源框架了,比较简单的功能都自己写代码实现。今天就来记录一下ViewPager指示器的实现。
效果图:
就是这样一个需求,布局分析如下:
三个小圆点是根据填充ViewPager集合的size动态添加到线性布局中的。
小圆点使用ImageView画出来,背景使用shape文件来定义
未选中时的白色:
选中时的黄色:
定义好了小圆点,需要给小圆点设置宽高,Margin等参数,此时就需要设置小圆点的布局参数。从第二个小圆点开始设置左侧Margin值
for(int i =0;i<data.size();i++){
ImageView imageView = new ImageView(mActivity);
imageView.setBackgroundResource(R.drawable.home_point_white);
//布局参数,父控件是什么布局就创建什么布局的布局参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
if(i>0){
params.leftMargin = 20;//从第二个小圆点开始设置左侧边距
}
imageView.setLayoutParams(params);
ll_home_point.addView(imageView);}
小黄点是跟着ViewPager走的,给ViewPager添加一个页面切换的监听setOnPageChangeListener,其中方法onPageScrolled是在ViewPager滑动过程中调用的,其中的参数positionOffset是指滑动的百分比。
那么我们计算滑动距离是,用两个圆点之间的间距*滑动百分比,就可以时时得到滑动的距离。那么两个圆点之间的间距怎么求呢
如上图所示,两个圆点之间的距离就是两个圆点左侧的距离,用第二个圆点getLeft - 第一个圆点getLeft就可以得到。
但这样写是无法获取到两者间距的,如果在Activity中,控件的绘制是在onCreate()方法之后,那么此时控件还未绘制,当然拿不到getLeft的值,我们需要对ImageView设置一个监听,onLayout方法执行完成之后再获取点之间的间距。
代码如下:
//计算两个圆点之间的距离
iv_home_point_yellow.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onGlobalLayout() {
iv_home_point_yellow.getViewTreeObserver().removeOnGlobalLayoutListener(this);
//ll_home_point.getChildAt(1),获取线性布局中的第二个小圆点
//ll_home_point.getChildAt(0),获取线性布局中的第一个小圆点
int pointDis = ll_home_point.getChildAt(1).getLeft() - ll_home_point.getChildAt(0).getLeft();
Log.i("圆点间距", "showButtomDialog: "+pointDis);
}});
得到了两个点之间的间距,得到了滑动百分比,那么现在就得到了小黄点随ViewPager滑动的时时距离。
那么现在就开始修改小黄点的布局参数,更新其左侧边距即可。但是这里要注意的是,当滑动到新的页面是,滑动距离百分比会变为0,因此需要加上一段距离,这段距离可以用position*pointsDis,两个圆点之间的距离*页面位置position。第一个页面的position为0
代码如下:
home_bottom_vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//更新小黄点的移动的距离
float leftMargin = positionOffset * pointDis + position * pointDis;
Log.i("小黄点移动的距离", "onPageScrolled: "+leftMargin +"-------"+positionOffset);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)iv_home_point_yellow.getLayoutParams(); layoutParams.leftMargin =(int) leftMargin;
iv_home_point_yellow.setLayoutParams(layoutParams);
}
@Override
public void onPageSelected(int position) { }
@Override
public void onPageScrollStateChanged(int state) { }});