一. 前言 仿照系统的BottomNavigationView而做的效果。
Github地址:XLBottomView 
二. 自定义View 1. 自定义用到的属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private  int  normal_color = Color.BLACK;private  int  select_color = Color.MAGENTA;private  boolean  hasLeftOrRightSize = true ;private  int  item_size = 50 ;private  int  item_layout;private  boolean  isSelectClick = false ;private  MyItem lastItem;private  XLBottomViewItemListener listener;private  List<BottomViewItem> items;
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  static  class  BottomViewItem   {         private  int  icon_id;          private  String title;          public  BottomViewItem (int  icon_id, String title)   {         this .icon_id = icon_id;         this .title = title;     } } 
 
2. 在values文件夹下自定义属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?xml version="1.0" encoding="utf-8"?> <resources >     <declare-styleable  name ="XLBottomView" >                   <attr  name ="normal_color"  format ="color" />                   <attr  name ="select_color"  format ="color" />                   <attr  name ="hasLeftOrRightSize"  format ="boolean" />                   <attr  name ="item_size"  format ="integer" />                   <attr  name ="item_layout"  format ="reference" />                   <attr  name ="isSelectClick"  format ="boolean" />      </declare-styleable >  </resources > 
 
3. 创建构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public  XLBottomView (Context context, int  normal_color, int  select_color, boolean  hasLeftOrRightSize, int  item_size, int  item_layout)   {    super (context);     this .normal_color = normal_color;     this .select_color = select_color;     this .hasLeftOrRightSize = hasLeftOrRightSize;     this .item_size = item_size;     this .item_layout = item_layout;          init(); } public  XLBottomView (Context context, AttributeSet attrs)   {    super (context, attrs);          if  (attrs != null ){                  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XLBottomView);                  normal_color = typedArray.getColor(R.styleable.XLBottomView_normal_color,normal_color);         select_color = typedArray.getColor(R.styleable.XLBottomView_select_color,select_color);         hasLeftOrRightSize = typedArray.getBoolean(R.styleable.XLBottomView_hasLeftOrRightSize,hasLeftOrRightSize);         item_size = typedArray.getInteger(R.styleable.XLBottomView_item_size,item_size);         isSelectClick = typedArray.getBoolean(R.styleable.XLBottomView_isSelectClick,isSelectClick);                  typedArray.recycle();     }          init(); } private  void  init ()   {}
 
4. layout的过程中添加视图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 @Override protected  void  onLayout (boolean  changed, int  l, int  t, int  r, int  b)   {         if  (changed){                  if  (items.size() != 0 ) {             Log.d(TAG,"数据来了" );                          int  space_num = hasLeftOrRightSize ? items.size()+1  : items.size()-1 ;             int  horizon_size = (getWidth() - items.size() * PxUtil.dpToPx(item_size,getContext())) / space_num;             int  vertical_size = (getHeight()- PxUtil.dpToPx(item_size,getContext())) / 2 ;                          for  (int  i = 0 ; i < items.size(); i++) {                                  BottomViewItem item = items.get(i);                                  @SuppressLint("DrawAllocation")  MyItem item_view = new  MyItem(                         getContext(),                         item.icon_id,                         item.title,                         i,                         normal_color,                         select_color                 );                                  int  left = hasLeftOrRightSize ?                         horizon_size + (horizon_size + PxUtil.dpToPx(item_size,getContext())) * i                         :                         (horizon_size + PxUtil.dpToPx(item_size,getContext())) * i;                 if  (!hasLeftOrRightSize){                                          if  (i == 0 ) left += PxUtil.dpToPx(20 ,getContext());                     if  (i == items.size()-1 ) left -= PxUtil.dpToPx(20 ,getContext());                 }                 int  top = vertical_size;                 int  right = left + PxUtil.dpToPx(item_size,getContext());                 int  bottom = top + PxUtil.dpToPx(item_size,getContext());                 item_view.layout(left,top,right,bottom);                 Log.d(TAG,"left:" +left+" top:" +top);                                  addView(item_view);                                  if  (i == 0 ) {                     item_view.changeStatus(MyItem.STATUS_SELECT);                     lastItem = item_view;                 }else  {                     item_view.changeStatus(MyItem.STATUS_NORMAL);                 }                                  item_view.setOnClickListener(new  OnClickListener() {                     @Override                      public  void  onClick (View v)   {                         MyItem selectItem = (MyItem) v;                         if  (!lastItem.equals(selectItem)) {                                                          lastItem.changeStatus(MyItem.STATUS_NORMAL);                                                          selectItem.changeStatus(MyItem.STATUS_SELECT);                                                          lastItem = selectItem;                                                          if  (listener != null ){                                 listener.itemStatusDidChange(selectItem.getItem_index());                             }                         }                     }                 });             }         }     } } 
 
5. 子项类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 public  class  MyItem  extends  androidx .appcompat .widget .AppCompatTextView   {         private  int  icon_id;          private  String title;          private  int  item_index;          private  int  normal_color;          private  int  select_color;          public  static  final  int  STATUS_NORMAL = 0 ;          public  static  final  int  STATUS_SELECT = 1 ;          public  MyItem (Context context, int  icon_id, String title, int  item_index, int  normal_color, int  select_color)   {         super (context);                  this .icon_id = icon_id;         this .title = title;         this .item_index = item_index;         this .normal_color = normal_color;         this .select_color = select_color;         setBackground(null );                  init(STATUS_NORMAL);     }          private  void  init (int  status)   {                                    Drawable drawable = getResources().getDrawable(icon_id).mutate();                  drawable.setBounds(0 ,PxUtil.dpToPx(5 ,getContext()),PxUtil.dpToPx(25 ,getContext()),PxUtil.dpToPx(25 ,getContext())+PxUtil.dpToPx(5 ,getContext()));         setCompoundDrawables(null ,drawable,null ,null );         setCompoundDrawablePadding(PxUtil.dpToPx(8 ,getContext()));                  setText(title);         setTextSize(PxUtil.spToPx(5 ,getContext()));         setGravity(Gravity.CENTER);         setTextColor(normal_color);     }          public  void  changeStatus (int  status)  {         if  (status == STATUS_SELECT){                          getCompoundDrawables()[1 ].mutate().setColorFilter(select_color, PorterDuff.Mode.SRC_ATOP);                          setTextColor(select_color);         }else  if  (status == STATUS_NORMAL){                          getCompoundDrawables()[1 ].mutate().setColorFilter(normal_color, PorterDuff.Mode.SRC_ATOP);                          setTextColor(normal_color);         }     }          public  int  getItem_index ()   {         return  item_index;     } } 
 
在这里,我们需要了解ColorFilter。
简单的理解可以参考这篇文章:ColorFilter的使用  以及 Android-使用 SetColorFilter 神奇地改变图片的颜色 
但是,如果使用setColorFilter,还是有一个坑需要了解,参考这篇文章:Android-Drawable setColorFilter方法踩坑 
三. 具体的使用 首先需要添加依赖,添加依赖之后,在布局文件中这样调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout  xmlns:android ="http://schemas.android.com/apk/res/android"      xmlns:app ="http://schemas.android.com/apk/res-auto"      xmlns:tools ="http://schemas.android.com/tools"      android:layout_width ="match_parent"      android:layout_height ="match_parent"      tools:context =".MainActivity" >     <swu.xl.bottomview.XLBottomView         android:id="@+id/bottom_view"         android:layout_width="match_parent"         android:layout_height="60dp"         android:background="#999999"         app:normal_color="#000000"         app:select_color="#ff9900"         app:hasLeftOrRightSize="false"         app:item_size="50"         android:layout_alignParentBottom="true"         /> </RelativeLayout > 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public  class  MainActivity  extends  AppCompatActivity   {    @Override      protected  void  onCreate (Bundle savedInstanceState)   {         super .onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         XLBottomView bottomView = findViewById(R.id.bottom_view);         List<XLBottomView.BottomViewItem> items = new  ArrayList<>();         XLBottomView.BottomViewItem item1 = new  XLBottomView.BottomViewItem(                 R.drawable.contact,                 "用户1"          );         XLBottomView.BottomViewItem item2 = new  XLBottomView.BottomViewItem(                 R.drawable.contact,                 "用户2"          );         XLBottomView.BottomViewItem item3 = new  XLBottomView.BottomViewItem(                 R.drawable.contact,                 "用户3"          );         XLBottomView.BottomViewItem item4 = new  XLBottomView.BottomViewItem(                 R.drawable.contact,                 "用户4"          );         items.add(item1);         items.add(item2);         items.add(item3);         items.add(item4);         bottomView.setItems(items);                  bottomView.setXLBottomViewItemListener(new  XLBottomView.XLBottomViewItemListener() {             @Override              public  void  itemStatusDidChange (int  index)   {                 Toast toast = Toast.makeText(MainActivity.this , "第"  + (index + 1 ) + "个按钮被点击" , Toast.LENGTH_SHORT);                 toast.setGravity(Gravity.CENTER,0 ,0 );                 toast.show();             }         });     } }