底部导航BottomBar设计与实现

    技术2022-07-11  91

    前言

    底部导航栏是一个通用组件。 为了让开发者可以快捷、高效地开发底部导航组件及其驱动的页面,我对相关代码进行了封装。

    1. public abstract class BottomItemDelegate

    抽象类BottomItemDelegate是所有由底部导航栏驱动的页面实例的父类。

    package com.qilu.core.delegates.bottom; import android.widget.Toast; import com.qilu.core.R; import com.qilu.core.app.Qilu; import com.qilu.core.delegates.QiluDelegate; public abstract class BottomItemDelegate extends QiluDelegate { // 再点一次退出程序时间设置 private static final long WAIT_TIME = 2000L; private long TOUCH_TIME = 0; @Override public boolean onBackPressedSupport() { if (System.currentTimeMillis() - TOUCH_TIME < WAIT_TIME) { _mActivity.finish(); } else { TOUCH_TIME = System.currentTimeMillis(); Toast.makeText(_mActivity, "再按一次退出" + Qilu.getApplicationContext().getString(R.string.app_name), Toast.LENGTH_SHORT).show(); } return true; } }

    3. public final class BottomTabBean

    类BottomTabBean存储有关底部导航栏元素的相关信息。

    package com.qilu.core.delegates.bottom; public final class BottomTabBean { private final CharSequence ICON; private final CharSequence TITLE; public BottomTabBean(CharSequence icon, CharSequence title) { this.ICON = icon; this.TITLE = title; } public CharSequence getIcon() { return ICON; } public CharSequence getTitle() { return TITLE; } }

    3. public final class ItemBuilder

    类ItemBuilder构建由导航栏按钮和相关页面一一对应的数据结构。

    package com.qilu.core.delegates.bottom; import java.util.LinkedHashMap; public final class ItemBuilder { //LinkedHashMap是有先后顺序的,HashMap是无序的 private final LinkedHashMap<BottomTabBean, BottomItemDelegate> ITEMS = new LinkedHashMap<>(); static ItemBuilder builder() { return new ItemBuilder(); } public final ItemBuilder addItem(BottomTabBean bean, BottomItemDelegate delegate) { ITEMS.put(bean, delegate); return this; } public final ItemBuilder addItems(LinkedHashMap<BottomTabBean, BottomItemDelegate> items) { ITEMS.putAll(items); return this; } public final LinkedHashMap<BottomTabBean, BottomItemDelegate> build() { return ITEMS; } }

    4. public abstract class BaseBottomDelegate

    抽象类BaseBottomDelegate是所有底部导航实例的父类。

    package com.qilu.core.delegates.bottom; import android.graphics.Color; import android.os.Bundle; import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; import android.support.v7.widget.LinearLayoutCompat; import android.view.LayoutInflater; import android.view.View; import android.widget.RelativeLayout; import com.joanzapata.iconify.widget.IconTextView; import com.qilu.core.R; import com.qilu.core.delegates.QiluDelegate; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import me.yokeyword.fragmentation.ISupportFragment; public abstract class BaseBottomDelegate extends QiluDelegate implements View.OnClickListener { private final ArrayList<BottomTabBean> TAB_BEANS = new ArrayList<>(); private final ArrayList<BottomItemDelegate> ITEM_DELEGATES = new ArrayList<>(); private final LinkedHashMap<BottomTabBean, BottomItemDelegate> ITEMS = new LinkedHashMap<>(); private int mCurrentDelegate = 0; private int mIndexDelegate = 0; private int mClickedColor =Color.RED; private LinearLayoutCompat mBottomBar = null; public abstract LinkedHashMap<BottomTabBean, BottomItemDelegate> setItems(ItemBuilder builder); public abstract int setIndexDelegate(); @ColorInt public abstract int setClickedColor(); public ArrayList<BottomItemDelegate> getItemDelegates() { return ITEM_DELEGATES; } @Override public Object setLayout() { return R.layout.delegate_bottom; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mIndexDelegate = setIndexDelegate(); if (setClickedColor() != 0) { mClickedColor = setClickedColor(); } final ItemBuilder builder = ItemBuilder.builder(); final LinkedHashMap<BottomTabBean, BottomItemDelegate> items = setItems(builder); ITEMS.putAll(items); //遍历->添加“键-值”对 for (Map.Entry<BottomTabBean, BottomItemDelegate> item : ITEMS.entrySet()) { final BottomTabBean key = item.getKey(); final BottomItemDelegate value = item.getValue(); TAB_BEANS.add(key); ITEM_DELEGATES.add(value); } } @Override public void onBindView(@Nullable Bundle savedInstanceState, @NonNull View rootView) { mBottomBar = $(R.id.bottom_bar); final int size = ITEMS.size(); for (int i = 0; i < size; i++) { LayoutInflater.from(getContext()).inflate(R.layout.bottom_item_icon_text_layout, mBottomBar); final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(i); //设置每个item的点击事件 item.setTag(i); item.setOnClickListener(this); final IconTextView itemIcon = (IconTextView) item.getChildAt(0); final AppCompatTextView itemTitle = (AppCompatTextView) item.getChildAt(1); final BottomTabBean bean = TAB_BEANS.get(i); //初始化数据 itemIcon.setText(bean.getIcon()); itemTitle.setText(bean.getTitle()); if (i == mIndexDelegate) { itemIcon.setTextColor(mClickedColor); itemTitle.setTextColor(mClickedColor); } } final ISupportFragment[] delegateArray = ITEM_DELEGATES.toArray(new ISupportFragment[size]); getSupportDelegate().loadMultipleRootFragment(R.id.bottom_bar_delegate_container, mIndexDelegate, delegateArray); } public void changeColor(int tabIndex) { resetColor(); final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(tabIndex); final IconTextView itemIcon = (IconTextView) item.getChildAt(0); itemIcon.setTextColor(mClickedColor); final AppCompatTextView itemTitle = (AppCompatTextView) item.getChildAt(1); itemTitle.setTextColor(mClickedColor); } private void resetColor() { final int count = mBottomBar.getChildCount(); for (int i = 0; i < count; i++) { final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(i); final IconTextView itemIcon = (IconTextView) item.getChildAt(0); itemIcon.setTextColor(Color.GRAY); final AppCompatTextView itemTitle = (AppCompatTextView) item.getChildAt(1); itemTitle.setTextColor(Color.GRAY); } } @Override public void onClick(View v) { final int tabIndex = (int) v.getTag(); changeColor(tabIndex); getSupportDelegate().showHideFragment(ITEM_DELEGATES.get(tabIndex), ITEM_DELEGATES.get(mCurrentDelegate)); //注意先后顺序 mCurrentDelegate = tabIndex; } }
    Processed: 0.014, SQL: 9