底部导航栏
目标:
只需添加相应的按钮和相应的视图,然后就可在Activity中切换显示。
大概思路:
在底部的LinearLayout中添加相应的图标,然后设置tag,绑定相应的Fragment数组对应的下标值。点击切换的时候,根据获取到的tag值,取出数组中对应下标的Fragment,并显示出来。
新建一个BaseBottomDelegate对底部导航栏进行组装
public abstract class BaseBottomDelegate extends LatteDelegate implements View.OnClickListener{
//将传过来的LinkedHashMap集合里面的键值对拆分之后,分别存入两个ArrayList
private final ArrayList<BottomTabBean> TAB_BEANS=new ArrayList<>();
private final ArrayList<BottomItemDelegate> ITEM_DELEGATES=new ArrayList<>();
//定义一个LinkedHashMap接受传过来的页面数据
private final LinkedHashMap<BottomTabBean,BottomItemDelegate> ITEMS=new LinkedHashMap<>();
//当前显示fragment的页面标记
private int mCurrentDelegate=0;
//首次加载页面时显示的主页标记
private int mIndexDelegate=0;
//点击之后按钮显示的颜色
private int mClickedColor= Color.RED;
@BindView(R2.id.bottom_bar)
LinearLayoutCompat mBottomBar=null;
//让子类传入布局所需要的按钮和布局
public abstract LinkedHashMap<BottomTabBean,BottomItemDelegate> setItems(ItemBuilder builder);
@Override
public Object setLayout() {
return R.layout.delegate_bottom;
}
//让子类传入设置首次加载的主页
public abstract int setIndexDelegate();
// 让子类传入设置点击之后按钮的颜色
@ColorInt
public abstract int setClickedColor();
@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循环取出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, View rootView) {
final int size=ITEMS.size();
//for循环填充底部布局
for (int i=0;i<size;i++){
LayoutInflater.from(getContext()).inflate(R.layout.bottom_item_icon_text_layou,mBottomBar);
final RelativeLayout item= (RelativeLayout) mBottomBar.getChildAt(i);
//设置每个item的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_BEANS.get(i);
itemIcon.setText(bean.getIcon());
itemTitle.setText(bean.getTitle());
if(i == mIndexDelegate){
itemIcon.setTextColor(mClickedColor);
itemTitle.setTextColor(mClickedColor);
}
}
//框架需要SupportFragment的数组,所以要将fragments的ArrayList转化为SupportFragment的数组
final SupportFragment[] delegateArray=ITEM_DELEGATES.toArray(new SupportFragment[size]);
//Fragmentation提供的设置方法
loadMultipleRootFragment(R.id.bottom_bar_delegate_container,mIndexDelegate,delegateArray);
}
//重置按钮的颜色
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);
}
}
//点击之后重新导入delegate,切换显示的内容。并设置按钮的颜色
@Override
public void onClick(View v) {
final int tag= (int) v.getTag();
resetColor();
final RelativeLayout item= (RelativeLayout) v;
final IconTextView itemIcon= (IconTextView) item.getChildAt(0);
itemIcon.setTextColor(mClickedColor);
final AppCompatTextView itemTitle= (AppCompatTextView) item.getChildAt(1);
itemTitle.setTextColor(mClickedColor);
//Fragmentation提供的方法
showHideFragment(ITEM_DELEGATES.get(tag),ITEM_DELEGATES.get(mCurrentDelegate));
//注意先后顺序
mCurrentDelegate=tag;
}
}
其中BottomTabBean为底部导航栏按钮对象的封装,使用的是字体图标。
字体图标是指iconify字体图标库,它是一个矢量图标库,有超过370个矢量字体图标。这些图标都是矢量字体图标,所以不仅可以无限放大而不会失真,模糊,还可以将适用于text的属性 应用于这些矢量图标上,从而实现改变图标颜色、添加阴影等效果等。具体的使用可以参考GitHub上的使用说明。
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;
}
}
其中ItemBuilder的 目的是把每一个Fragment和底部按钮的对象进行绑定组装进一个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;
}
}
最后就是 底部按钮的item布局和根Fragment的布局
<?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_centerHorizontal="true"
android:layout_alignParentTop="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>
<?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_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_bar"
/>
<!-- 底部导航栏 -->
<android.support.v7.widget.LinearLayoutCompat
android:id="@+id/bottom_bar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
/>
</RelativeLayout>
到这里 底部导航栏封的封装就完成了,之后只要新建底部导航栏的实例,并填充数据就可以了
public class EcBottomDelegate extends BaseBottomDelegate {
private String backgroundColor = "#ffff8800"; //底部导航栏背景色
@Override
public LinkedHashMap<BottomTabBean, BottomItemDelegate> setItems(ItemBuilder builder) {
final LinkedHashMap<BottomTabBean, BottomItemDelegate> items=new LinkedHashMap<>();
items.put(new BottomTabBean("{fa-home}","首页"),new IndexDelegate());
items.put(new BottomTabBean("{fa-fort-awesome}","公会"),new GuildDelegate());
items.put(new BottomTabBean("{fa-file-image-o}","图集"),new AldumDelegate());
items.put(new BottomTabBean("{fa-user}","我的"),new PersonalDelegate());
return builder.addItems(items).build();
}
@Override
public int setIndexDelegate() {
return 0;
}
@Override
public int setClickedColor() {
return Color.parseColor(backgroundColor);
}
}