電商式導(dǎo)航欄禽车,多Fragment切換
- 本文默認(rèn)在已經(jīng)搭建好的框架上進(jìn)行開發(fā)
點(diǎn)此鏈接到上一篇基礎(chǔ)框架的搭建
-
設(shè)計(jì)思路
在底部的LinearLayout中添加相應(yīng)的圖標(biāo),然后設(shè)置tag綁定相應(yīng)的 Fragment數(shù)組對(duì)應(yīng)的下標(biāo)值刊殉,再點(diǎn)擊切換的時(shí)候殉摔,根據(jù)獲取到的tag值,取出數(shù)組中對(duì)應(yīng)下標(biāo)的Fragment记焊,在通過相關(guān)方法顯示逸月。
封裝目標(biāo):只需添加相應(yīng)的按鈕對(duì)象和相應(yīng)的視圖即可,然后在Activity中顯示即可遍膜。
- 先創(chuàng)建可切換的Fragment的基類BottomItemFragment(實(shí)現(xiàn)一個(gè)雙擊退出功能)
// 定義為抽象類即每個(gè)itemfragment的基類
public abstract class BottomItemFragment extends MyFragment implements View.OnKeyListener{
// 當(dāng)前按下返回按鈕的時(shí)間
private long mExitTime = 0;
// 雙擊返回鍵之間的延遲
private static final int EXIT_TIME = 2000;
@Override
public void onResume(){
super.onResume();
View rootView = getView();
// 防止雙擊退出失效
if (rootView!=null){
rootView.setFocusableInTouchMode(true);
rootView.requestFocus();
rootView.setOnKeyListener(this);
}
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){
if ((System.currentTimeMillis() - mExitTime) > EXIT_TIME) {
Toast.makeText(getContext(), "雙擊退出", Toast.LENGTH_SHORT).show();
mExitTime = System.currentTimeMillis();
} else {
_mActivity.finish();
if (mExitTime != 0) {
mExitTime = 0;
}
}
return true;
}
}
}
- 底部導(dǎo)航欄按鈕對(duì)象的封裝(這邊的icon用的是字體圖標(biāo)碗硬,不明白的請(qǐng)移步我的博客)
- 字體圖標(biāo)庫的使用鏈接
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;
}
}
- 新建一個(gè)ItemBuilder瓤湘,目的是用來把每一個(gè)Fragment和底部的按鈕對(duì)象進(jìn)行綁定組裝進(jìn)一個(gè)LinkedHashMap的集合
public final class ItemBuilder{
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;
}
}
- 接下來貼兩個(gè)布局文件,一個(gè)是根Fragment的布局恩尾,其實(shí)就是一個(gè)FrameLayout加上一個(gè)底部按鈕的LinearLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.ContentFrameLayout
android:id="@+id/bottom_bar_delegate_container"
android:layout_above="@+id/bottom_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.v7.widget.LinearLayoutCompat
android:id="@+id/bottom_bar"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:layout_height="60dp"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingBottom="6dp"
android:paddingTop="6dp">
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/icon_bottom_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center"
android:textSize="25sp" />
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv_bottom_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:gravity="center" />
</RelativeLayout>
- 萬事俱備弛说,接下來就是新建一個(gè)BaseBottomFragment,將頁面進(jìn)行組裝
public abstract class BaseBottomFragment extends MyFragment implements View.OnClickListener {
// 將傳過來的LinkedHashMap集合里面的鍵值對(duì)拆分之后,分別存入兩個(gè)ArrayList
private final ArrayList<BottomTabBean> TAB_BEAN = new ArrayList<>();
private final ArrayList<BottomItemFragment> ITEM_FRAGMENT = new ArrayList<>();
// 定義一個(gè)LinkedHashMap接受傳過來的頁面數(shù)據(jù)
private final LinkedHashMap<BottomTabBean, BottomItemFragment> ITEMS = new LinkedHashMap<>();
// 當(dāng)前顯示fragment的頁面標(biāo)記
private int mCurrentFragment = 0;
// 首次加載頁面時(shí)顯示的主頁標(biāo)記 = 0
private int mIndexFragment = 0;
// 點(diǎn)擊之后按鈕顯示的顏色
private int mClickColor = Color.RED;
//對(duì)子類提供的設(shè)置的抽象方法
// 讓子類傳入布局所需要的按鈕和布局
public abstract LinkedHashMap<BottomTabBean, BottomItemDelegate> setItems(ItemBuilder itemBuilder);
// 讓子類傳入設(shè)置首次加載的主頁
public abstract int setIndexDelegate();
// 讓子類傳入設(shè)置點(diǎn)擊之后按鈕的顏色
@ColorInt
public abstract int setClickColor();
@Override
public Object setLayout() {
return R.layout.delegate_bottom;
}
// ButterKnife綁定特笋,自己去Github上看使用的方法剃浇,我這邊是在Android Library里面使用的,所以是R2文件
@BindView(R2.id.bottom_bar)
LinearLayoutCompat mBottomBar = null;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIndexDelegate = setIndexDelegate();
if (setClickColor()!=0){
mClickColor = setClickColor();
}
final ItemBuilder builder = ItemBuilder.builder();
final LinkedHashMap<BottomTabBean, BottomItemDelegate> items = setItems(builder);
ITEMS.putAll(items);
// for 循環(huán)取出ITEMS中的鍵值對(duì)的值
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 saveInstanceState, View rootView){
final size = ITEMS.size();
// for循環(huán)填充底部布局,比較核心的內(nèi)容
for(int i = 0 ;i < size; i++){
LayoutInflater.from(getContext()).inflate(R.layout.bottom_item_icon_text_layout, mBottomBar);
final RelativeLayout item = mBottomBar.getChildAt(i);
// 設(shè)置tag
item.setTag(i);
item.setOnClickListener(this);
final IconTextView itemIcon = (IconTextView)item.getChildAt(0);
final AppCompatTextView itemTitle = (AppCompatTextView)item.getChildAt(1);
final BottomTabBean bean = TAB_BEAN.get(i);
itemIcon.setText(bean.getICON());
itemTitle.setText(bean.getTITLE());
if (i == mIndexFragment){
itemIcon.setTextColor(mClickColor);
itemTitle.setTextColor(mClickColor);
}
}
// 將fragments的ArrayList轉(zhuǎn)化為SupportFragment的數(shù)組猎物,框架需要
final SupportFragment[] fragmentArray = ITEM_FRAGMENTS.toArray(new SupportFragment[size]);
// Fragmentation提供的設(shè)置方法
loadMultipleRootFragment(R.id.bottom_bar_delegate_container, mIndexFragment, fragmentArray);
}
// 重置按鈕的顏色
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);
}
}
// 點(diǎn)擊之后重新導(dǎo)入delegate虎囚,設(shè)置按鈕的顏色
@Override
public void onClick(View view) {
final int tag = (int) view.getTag();
resetColor();
final RelativeLayout item = (RelativeLayout) view;
final IconTextView itemIcon = (IconTextView) item.getChildAt(0);
itemIcon.setTextColor(mClickColor);
final AppCompatTextView itemTitle = (AppCompatTextView) item.getChildAt(1);
itemTitle.setTextColor(mClickColor);
// Fragmentation提供的方法
showHideFragment(ITEM_DELEGATES.get(tag), ITEM_DELEGATES.get(mCurrentDelegate));
mCurrentDelegate = tag;
}
}
- 至此,封裝完成蔫磨,底部帶導(dǎo)航欄的多Fragment界面已經(jīng)ok了淘讥,接下來就是新建一個(gè)底部導(dǎo)航欄的實(shí)例,將數(shù)據(jù)填充進(jìn)去就OK了
public class MyBottomFragment extends BaseBottomFragment{
@Override
public LinkedHashMap<BottomTabBean, BottomItemFragment> setItems(ItemBuilder itemBuilder) {
final LinkedHashMap<BottomTabBean, BottomItemFragment> items = new LinkedHashMap<>();
items.put(new BottomTabBean("{fa-home}","主頁"),new IndexFragment());
items.put(new BottomTabBean("{fa-sort}","分類"),new SortFragment());
items.put(new BottomTabBean("{fa-compass}","發(fā)現(xiàn)"),new IndexFragment());
items.put(new BottomTabBean("{fa-shopping-cart}","購物車"),new IndexFragment());
items.put(new BottomTabBean("{fa-user}","我的"),new IndexFragment());
return itemBuilder.addItems(items).build();
}
@Override
public int setIndexDelegate() {
return 0;
}
@Override
public int setClickColor() {
return Color.parseColor("#FF0000");
}
}
- 最后在單一的Activity中的setRootFragment方法中設(shè)置MyBottomFragment頁面堤如,顯示即可蒲列。