安卓自定義底部導(dǎo)航欄NagivationBar

不管什么APP,都會用到底部導(dǎo)航欄,一般實現(xiàn)方式有兩種:

  • 自定義組合控件
  • RadioGroup+RadioButton

本文將通過自定義組合控件的方式手把手教大家擼一個簡單實用的底部導(dǎo)航欄。

首先我們需要自定義一個NagivationTab。

public class NavigateTab extends LinearLayout {

    private ImageView navTabIv = null;
    private TextView navTabTv = null;

    private int curPosition = 0;

    public NavigateTab(Context context) {
        super(context);
        init(context, null);
    }

    public NavigateTab(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public NavigateTab(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.navigate_tab_layout, this);

        navTabIv = (ImageView) view.findViewById(R.id.navigate_tab_iv);
        navTabTv = (TextView) view.findViewById(R.id.navigate_tab_tv);
    }

    public void setCurPosition(int position){
        curPosition = position;
    }

    public int getCurPosition() {
        return curPosition;
    }

    public void setImageResource(int resId){
        navTabIv.setImageResource(resId);
    }

    public void setText(String text){
        navTabTv.setText(text);
    }

    public void setTextColor(int textColor){
        navTabTv.setTextColor(textColor);
    }

    public void setTextSize(float textSize){
        navTabTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
}

這里自定義的tab是繼承一個線性布局,代碼很簡單,就不多解釋了。

下面是tab引用的布局文件。

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/navigate_tab_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/navigate_tab_iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/navigate_tab_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dimen_size_2"
            android:text="text" />

    </LinearLayout>

</merge>

值得注意的是這里根布局使用的是merge標(biāo)簽,減少了布局嵌套。

接下來我們在自定義一個NagivationBar。

public class NavigateBar extends LinearLayout implements OnLimitClickListener {
    // 導(dǎo)航欄tab個數(shù)
    private int tabCount = 0;
    // 默認(rèn)狀態(tài)下tab圖片集合
    private List<Integer> defaultImageList = null;
    // 選中狀態(tài)下tab圖片集合
    private List<Integer> focusImageList = null;
    // tab文字集合
    private List<String> tabTextList = null;
    // 導(dǎo)航欄tab默認(rèn)字體顏色
    private int defaultTextColor = 0xFF555555;
    // 導(dǎo)航欄tab選中字體顏色
    private int focusTextColor = 0xFF000000;
    // 字體大小
    private float textSize = 14F;

    private Context context = null;

    private ArrayList<NavigateTab> tabList = null;

    private OnNavigateListener listener = null;

    public NavigateBar(Context context) {
        super(context);
        this.context = context;
        init(context, null);
    }

    public NavigateBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init(context, attrs);
    }

    public NavigateBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        defaultImageList = new ArrayList<>();
        focusImageList = new ArrayList<>();

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.NavigateBar);

        tabCount = array.getInt(R.styleable.NavigateBar_tabCount, 0);

        int defaultImageArrResId = array.getResourceId(R.styleable.NavigateBar_defaultImageArray, 0);
        int focusImageArrResId = array.getResourceId(R.styleable.NavigateBar_focusImageArray, 0);
        int textArrResId = array.getResourceId(R.styleable.NavigateBar_textArray, 0);

        TypedArray defaultImageTypeArray = context.getResources().obtainTypedArray(defaultImageArrResId);
        if (defaultImageTypeArray != null && defaultImageTypeArray.length() > 0) {
            for (int i = 0; i < defaultImageTypeArray.length(); i++) {
                defaultImageList.add(defaultImageTypeArray.getResourceId(i, 0));
            }
        }

        TypedArray focusImageTypeArray = context.getResources().obtainTypedArray(focusImageArrResId);
        if (focusImageTypeArray != null && focusImageTypeArray.length() > 0) {
            for (int i = 0; i < focusImageTypeArray.length(); i++) {
                focusImageList.add(focusImageTypeArray.getResourceId(i, 0));
            }
        }

        String[] tabTextArray = context.getResources().getStringArray(textArrResId);
        if (tabTextArray != null && tabTextArray.length > 0) {
            tabTextList = Arrays.asList(tabTextArray);
        }

        defaultTextColor = array.getColor(R.styleable.NavigateBar_defaultTextColor, 0xFF555555);
        focusTextColor = array.getColor(R.styleable.NavigateBar_focusTextColor, 0xFF000000);
        textSize = array.getDimension(R.styleable.NavigateBar_textSize, 14F);
        // 回收
        array.recycle();

        setOrientation(HORIZONTAL);

        initTabs();
    }

    public void setOnNavigateListener(OnNavigateListener listener) {
        this.listener = listener;

        registerListener();
    }

    private void registerListener() {
        if (tabList != null && tabList.size() > 0) {
            for (NavigateTab tab : tabList) {
                tab.setOnClickListener(new OnLimitClickHelper(this));
            }
        }
    }

    public void setFocusPosition(int position) {
        for (int i = 0; i < tabList.size(); i++) {
            if (i == position) {
                tabList.get(i).setImageResource(focusImageList.get(i));
                tabList.get(i).setTextColor(focusTextColor);
            } else {
                tabList.get(i).setImageResource(defaultImageList.get(i));
                tabList.get(i).setTextColor(defaultTextColor);
            }
        }
    }

    private void initTabs() {
        this.removeAllViews();
        tabList = new ArrayList<>();

        if (tabCount > 0) {
            for (int i = 0; i < tabCount; i++) {
                NavigateTab navigateTab = new NavigateTab(context);
                navigateTab.setCurPosition(i);
                navigateTab.setImageResource(defaultImageList.get(i));
                navigateTab.setText(tabTextList.get(i));
                navigateTab.setTextSize(textSize);
                navigateTab.setTextColor(defaultTextColor);

                LinearLayout.LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT, 1.0F);
                navigateTab.setLayoutParams(params);

                tabList.add(navigateTab);
                this.addView(navigateTab);
            }
        }
    }

    @Override
    public void onClick(View view) {
        if (listener != null) {
            if (view instanceof NavigateTab) {
                int position = ((NavigateTab) view).getCurPosition();
                setFocusPosition(position);
                listener.onClickNavigate(position);
            }
        }
    }

    public interface OnNavigateListener {
        void onClickNavigate(int position);
    }
}

大家可以看到,我們通過自定義的屬性來配置nagivationTab個數(shù)、文字、焦點/默認(rèn) 圖片和文字顏色。

<declare-styleable name="NavigateBar">
        <attr name="tabCount" format="integer" />
        <attr name="defaultImageArray" format="reference" />
        <attr name="focusImageArray" format="reference" />
        <attr name="textArray" format="reference" />
        <attr name="defaultTextColor" format="color" />
        <attr name="focusTextColor" format="color" />
        <attr name="textSize" format="dimension" />
</declare-styleable>

至此,我們自定義的底部導(dǎo)航欄已完成,是不是很簡單??????。下面給大家看看activity和布局文件的使用。

Activity

public class NavTestActivity extends AppCompatActivity implements OnNavigateListener {
    NavigateBar navigateBar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_nav);

        navigateBar = findViewById(R.id.navigate_bar);
        navigateBar.setOnNavigateListener(this);
        navigateBar.setFocusPosition(0);
    }

    @Override
    public void onClickNavigate(int position) {
        Toast.makeText(this, "" + position, Toast.LENGTH_SHORT).show();
    }
}

布局文件

<com.tbh.library.widgets.NavigateBar
        android:id="@+id/navigate_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:defaultImageArray="@array/navigate_default_image"
        app:focusImageArray="@array/navigate_focus_image"
        app:textArray="@array/navigate_bar_text"
        app:tabCount="4"
        app:defaultTextColor="#000000"
        app:focusTextColor="#0000FF"
        app:textSize="14sp"/>

strings.XML

    <string-array name="navigate_bar_text">
        <item>首頁</item>
        <item>直播</item>
        <item>關(guān)注</item>
        <item>廣場</item>
        <item>我的</item>
    </string-array>

    <integer-array name="navigate_default_image">
        <item>@drawable/home_default</item>
        <item>@drawable/live_default</item>
        <item>@drawable/attention_default</item>
        <item>@drawable/square_default</item>
        <item>@drawable/mine_default</item>
    </integer-array>

    <integer-array name="navigate_focus_image">
        <item>@drawable/home_focus</item>
        <item>@drawable/live_focus</item>
        <item>@drawable/attention_focus</item>
        <item>@drawable/square_focus</item>
        <item>@drawable/mine_focus</item>
    </integer-array>

最后附上效果圖,第一次寫技術(shù)文章,歡迎大家轉(zhuǎn)載評論。

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

相關(guān)閱讀更多精彩內(nèi)容

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