1. 程式人生 > >Android 引導頁動態新增圓點指示器

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裡,後面提供下載。