四.自定義View之ViewPager指示器

最近一個(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) { }});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容