最近一個(gè)項(xiàng)目中有這樣一個(gè)需求,就是一個(gè)ViewPager,下面帶有幾個(gè)指示器的小圓點(diǎn),這樣的需求很容易實(shí)現(xiàn),網(wǎng)上也有很多的開(kāi)源框架都可以滿(mǎn)足這個(gè)需求,但是最近已經(jīng)不太想用開(kāi)源框架了,比較簡(jiǎn)單的功能都自己寫(xiě)代碼實(shí)現(xiàn)。今天就來(lái)記錄一下ViewPager指示器的實(shí)現(xiàn)。
效果圖:

就是這樣一個(gè)需求,布局分析如下:

三個(gè)小圓點(diǎn)是根據(jù)填充ViewPager集合的size動(dòng)態(tài)添加到線(xiàn)性布局中的。
小圓點(diǎn)使用ImageView畫(huà)出來(lái),背景使用shape文件來(lái)定義
未選中時(shí)的白色:

選中時(shí)的黃色:

定義好了小圓點(diǎn),需要給小圓點(diǎn)設(shè)置寬高,Margin等參數(shù),此時(shí)就需要設(shè)置小圓點(diǎn)的布局參數(shù)。從第二個(gè)小圓點(diǎn)開(kāi)始設(shè)置左側(cè)Margin值
for(int i =0;i<data.size();i++){
ImageView imageView = new ImageView(mActivity);
imageView.setBackgroundResource(R.drawable.home_point_white);
//布局參數(shù),父控件是什么布局就創(chuàng)建什么布局的布局參數(shù)
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
if(i>0){
params.leftMargin = 20;//從第二個(gè)小圓點(diǎn)開(kāi)始設(shè)置左側(cè)邊距
}
imageView.setLayoutParams(params);
ll_home_point.addView(imageView);}
小黃點(diǎn)是跟著ViewPager走的,給ViewPager添加一個(gè)頁(yè)面切換的監(jiān)聽(tīng)setOnPageChangeListener,其中方法onPageScrolled是在ViewPager滑動(dòng)過(guò)程中調(diào)用的,其中的參數(shù)positionOffset是指滑動(dòng)的百分比。
那么我們計(jì)算滑動(dòng)距離是,用兩個(gè)圓點(diǎn)之間的間距*滑動(dòng)百分比,就可以時(shí)時(shí)得到滑動(dòng)的距離。那么兩個(gè)圓點(diǎn)之間的間距怎么求呢

如上圖所示,兩個(gè)圓點(diǎn)之間的距離就是兩個(gè)圓點(diǎn)左側(cè)的距離,用第二個(gè)圓點(diǎn)getLeft - 第一個(gè)圓點(diǎn)getLeft就可以得到。
但這樣寫(xiě)是無(wú)法獲取到兩者間距的,如果在Activity中,控件的繪制是在onCreate()方法之后,那么此時(shí)控件還未繪制,當(dāng)然拿不到getLeft的值,我們需要對(duì)ImageView設(shè)置一個(gè)監(jiān)聽(tīng),onLayout方法執(zhí)行完成之后再獲取點(diǎn)之間的間距。
代碼如下:
//計(jì)算兩個(gè)圓點(diǎn)之間的距離
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),獲取線(xiàn)性布局中的第二個(gè)小圓點(diǎn)
//ll_home_point.getChildAt(0),獲取線(xiàn)性布局中的第一個(gè)小圓點(diǎn)
int pointDis = ll_home_point.getChildAt(1).getLeft() - ll_home_point.getChildAt(0).getLeft();
Log.i("圓點(diǎn)間距", "showButtomDialog: "+pointDis);
}});
得到了兩個(gè)點(diǎn)之間的間距,得到了滑動(dòng)百分比,那么現(xiàn)在就得到了小黃點(diǎn)隨ViewPager滑動(dòng)的時(shí)時(shí)距離。
那么現(xiàn)在就開(kāi)始修改小黃點(diǎn)的布局參數(shù),更新其左側(cè)邊距即可。但是這里要注意的是,當(dāng)滑動(dòng)到新的頁(yè)面是,滑動(dòng)距離百分比會(huì)變?yōu)?,因此需要加上一段距離,這段距離可以用position*pointsDis,兩個(gè)圓點(diǎn)之間的距離*頁(yè)面位置position。第一個(gè)頁(yè)面的position為0
代碼如下:
home_bottom_vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//更新小黃點(diǎn)的移動(dòng)的距離
float leftMargin = positionOffset * pointDis + position * pointDis;
Log.i("小黃點(diǎn)移動(dòng)的距離", "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) { }});