Android 引導頁動態新增圓點指示器
本來工作很忙,沒時間寫什麼部落格或研究小技術。昨晚實在是太無奈了,被兄弟拿槍頂著寫了個引導頁指示器的動態新增功能。描述的不詳細,來張圖片:
其實 實現原理很簡單,一般都在app的初次啟動時出現,一個左右滑動的viewpager,頁面底部再搭配一個標識位置的小點點。
有人或立馬噴飯,說這不是很簡單嗎?
確實簡單,我現在做的不是靜態在Activity底部寫死幾個view標識。我是自定義了一個容器,根據開發者切換頁面的個數,來動態建立下面需要幾個view控制元件。
其實這也是很簡單,對於那些3~5年經驗的老牛們,小鳥值得看看。沒什麼神奇的,但還是分享下吧。
原理+程式碼段解釋+demo:
如何Activity底部有一個控制元件,能在程式碼裡動態設定view的個數生成小點點就好了。
<com.example.viewpager_bottom_line_test.BottomLineLayout android:id="@+id/bottomlayoutl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="50dp" />
試一試吧,接下來定義這個類。
/** * @Author: duke * @DateTime: 2017-04-22 21:59 * @Description: */ public class BottomLineLayout extends LinearLayout { private int itemDefaultBgResId = R.drawable.normal;//單個元素預設背景樣式 private int itemSelectedBgResId = R.drawable.select;//單個元素選中背景樣式 private int currentPosition;//當前選中位置 private int itemHeight = 50;//item寬高 private int itemMargin = 5;//item間距 public BottomLineLayout(Context context) { this(context, null, 0); } public BottomLineLayout(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public BottomLineLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOrientation(HORIZONTAL); setGravity(Gravity.CENTER); } }
我選擇了繼承LinearLayout佈局,原因很簡單:設定好方向,放心新增view就可以了。還需要兩個drawable,一個是選中的樣式,一個是未選中的。還有當前選中的view的position,還得設定view的寬高和外間距,不能捱得太近了。
(如果你不會自動以控制元件的話,此處略有遺憾。我之前也是不會,然後勵志學習。研究了整個自定義控制元件的原理,review了網上90%的自定義控制元件。後來本打算寫一序列自定義控制元件的文章與大家分享,但是時間總是不知道去哪兒了。如果你不會,還是要提醒你,自定義控制元件不是什麼高深的東西,但是想成為大牛哥,還是快速搞定這傢伙。)
自定義控制元件有三大方法,onMeasure、onLayout、onDraw。對於自定義ViewGroup,onDraw就不存在了。由於我繼承的是LinearLayout,排版的活兒也就不用了,故忽略onLayout。測量?根據自己的需要吧,我懶得測量了,每個child的寬高都從外面傳過來,省事。也是這三大方法我都忽略了。
那麼接下來我需要做的是什麼呢?新增child,容器類控制元件都有addView方法。
那建立什麼view呢!button?imageview?textview?還是view?
隨便了,我textview。你可以拿我的demo去擴充套件下,沒切換到一個小點點,就顯示順序數字,更酷,我懶沒寫這個。
加下來新增view吧。
public void initViews(int count, int itemHeight, int itemMargin) {
this.itemHeight = itemHeight;
this.itemMargin = itemMargin;
removeAllViews();
if(count == 0 || itemHeight == 0){
return;
}
View view = createView(itemHeight,itemMargin);
view.setBackgroundResource(itemSelectedBgResId);
addView(view);
if(count == 1){
return;
}
for (int i = 1; i < count; i++) {
view = createView(itemHeight,itemMargin);
view.setBackgroundResource(itemDefaultBgResId);
addView(view);
}
}
在程式碼裡面初始化控制元件,傳遞引數過來(item個數,item的寬高,item的外間距)
既然是初始化,第一個就設定成選中樣式了,第二個開始後面的都用預設樣式了。你也許會想,我這程式碼寫的,一個迴圈搞定,在裡面判斷不行嗎?遺憾的 告訴你,個人感覺在迴圈裡面判斷會損耗效能,不跟你扯了。
在每次初始化的時候,移除所有child,萬一使用者無聊多次呼叫這個方法呢!然後建立第一個child,設定選中樣式並新增到容器中。後面的來個迴圈,搞定。
那裡面的createView方法是個什麼模樣?莫急:
/**
* 建立view
* @param sideLength 邊長
* @param itemMargin 外間距
* @return
*/
public View createView(int sideLength,int itemMargin){
TextView textview = new TextView(getContext());
LinearLayout.LayoutParams params = new LayoutParams(sideLength, sideLength);
if(itemMargin > 0){
params.setMargins(itemMargin,0,itemMargin,0);
}
textview.setLayoutParams(params);
return textview;
}
簡單吧,建立TextView,建立LinearLayout.LayoutParams,設定寬高,設定Margin。
最後,還有個切換選中位置的方法,那更是簡單了。
//切換到目標位置
public void changePosition(int position) {
if(getChildCount() <= 1){
return;
}
getChildAt(currentPosition).setBackgroundResource(itemDefaultBgResId);
currentPosition = position % getChildCount();
getChildAt(currentPosition).setBackgroundResource(itemSelectedBgResId);
}
先修改當前位置的view為預設樣式,然後把這次的位置賦給當前位置,同時修改成選中樣式。
?咋了?完事了,就這麼多。
在Activity中怎麼用呢?
bottomLineLayout = (BottomLineLayout) findViewById(R.id.bottomlayoutl);
bottomLineLayout.initViews(item個數,item寬高,item外間距);
在viewpager每次切換時,更新指示器的狀態:
viewPager.addOnPageChangeListener(new MyOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
if(bottomLineLayout != null){
bottomLineLayout.changePosition(position);
}
}
});
主要程式碼就這些,沒啥了。viewpager的程式碼不貼出來了。都在demo裡,後面提供下載。