Android 自定义底部导航栏

GitHub

使用:

  • 添加依赖
    1.项目gradle添加一下配置:

      allprojects {
      repositories {
          ...
          maven { url 'https://jitpack.io' }
          }
      }  
    

    2.module中的gradle添加依赖:

      dependencies {
          implementation 'com.github.truemi:bottomBar:v1.1'
      } 
    
  • xml中添加view:

      
        
    
  • activity中初始化:

      BottomBar bottomBar = findViewById(R.id.bottom_bar);
      bottomBar.init(getSupportFragmentManager(),R.id.fl_home)//.setRippleColor(R.drawable.bottom_bar_bg)//水波纹效果
              .addItem("消息", getResources().getDrawable(R.drawable.bottom_bar_selected_01), new MessageFragment(), true)
              .addItem("首页", getResources().getDrawable(R.drawable.bottom_bar_selected_02), new HomeFragment(), false)
              .addItem("我的", getResources().getDrawable(R.drawable.bottom_bar_selected_03), new MyFragment(), true)
              .create(1);//默认显示第几个界面从0开始
      bottomBar.setOnBottomBarOnClick(this);//设置点击监听  
    

自定义属性:

属性 描述
mTextNormalColor #999999 标题的默认(未选中状态)颜色
mTextSelectColor #FF0000 标题选中状态颜色
mtextSize 10dp 标题的文字大小
mIconSize 20dp 图片的大小(不设置,使用图片的实际大小)

公开方法:

  • setOnBottomBarOnClick(this);//设置点击监听
  • showRedPoint(1,0,0);//只有初始化时设置可显示小红点为true时,设置显示才有效
  • showRed(2);//显示小红点,从0开始,从左到右
  • hideRed(0);//隐藏小红点,从0开始,从左到右
  • showSubPage(1);//显示第几个界面,从0开始,从左到右
需求
  1. 每个按钮包括文字,图标,以及消息小红点,并且有状态选择器
  2. 可以动态添加按钮
  3. 按钮与Fragment绑定,点击按钮切换到对应的Fragment
思路
  1. 自定义View 继承自LinearLayout,设置横向布局
  2. 代码动态设置Item,设置权重为 1 ,然后添加到View中.
  3. 处理点击事件与fragment绑定
步骤
  1. 自定义属性,在attrs.xml中设置自定义属性
 
        
        
        
    
  1. 自定义View初始化
    public BottomAppBar(Context context) {
        this(context, null);
    }

    public BottomAppBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public BottomAppBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
       //设置ViewId,为了避免重复,这里使用时间戳,
        TEXTVIEW_ID = (int) (System.currentTimeMillis()%100*10000);
        IMAGEVIEW_ID = (int) (System.currentTimeMillis()%100*1000);
        ITEM_ID = (int) (System.currentTimeMillis()%100*100);
    }

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.BottomAppBar);
            float dimension = typedArray.getDimension(R.styleable.BottomAppBar_mtextSize, 0);
            textSize = Uiutils.px2sp(context,dimension);
            textNormalColor = typedArray.getColor(R.styleable.BottomAppBar_mTextNormalColor, 0);
            textSelectColor = typedArray.getColor(R.styleable.BottomAppBar_mTextSelectColor, 0);
            typedArray.recycle();
        }
        setOrientation(LinearLayout.HORIZONTAL);//设置布局为横向布局
    }

  1. 初始化item,Item的根布局使用RelativeLayout,包含一个TextView和一个ImageView(小红点),textView的文字上面添加一个Drawable显示图标,这一部分的重点就是,在代码中把控件放到指定位置上(其实很简单)
    首先new出TextView
 TextView textView = new TextView(context,null);
        textView.setText(title);//设置Item名称
        textView.setTextSize(textSize);//文字大小
        textView.setTextColor(textNormalColor);//默认颜色
        textView.setId(TEXTVIEW_ID);//textView id
        itemTextViews.add(textView);//添加到集合中
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());测量Item图标大小
        textView.setCompoundDrawables(null, drawable, null, null);//设置Item图标

把TextView放到RelativeLayout的中间位置

     RelativeLayout relativeLayout = new RelativeLayout(context);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);//textView居中
        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
        textView.setGravity(Gravity.CENTER_HORIZONTAL);//文字居中
        relativeLayout.addView(textView, layoutParams);

设置小红点

          if (haveRedPoint) {
            ImageView  imageView = new ImageView(context);
            int imageId = IMAGEVIEW_ID + items.size(); 
            imageView.setId(imageId);设置id
            Drawable redPoint = context.getResources().getDrawable(R.drawable.red_dot_circle_14px);
            imageView.setImageDrawable(redPoint);
            RelativeLayout.LayoutParams layoutParamsDot = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            layoutParamsDot.addRule(RelativeLayout.ALIGN_RIGHT, TEXTVIEW_ID);
            layoutParamsDot.addRule(RelativeLayout.ALIGN_TOP, TEXTVIEW_ID);
            relativeLayout.addView(imageView, layoutParamsDot);
            imageView.setVisibility(View.GONE);
            itemImageViews.put(itemTextViews.size(),imageView);
        }
  1. 点击按钮显示指定fragment
    private void showFragment(int viewId) {//viewId为Item的id
        Fragment selectedFragment = null;
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        for (Map.Entry viewFragmentEntry : itemFragment.entrySet()) {
            Fragment fragment = viewFragmentEntry.getValue();
            if (!fragment.isAdded()) {
                fragmentTransaction.add(layoutFragment, fragment);
            }
            RelativeLayout view = (RelativeLayout) viewFragmentEntry.getKey();
            int id = view.getId();
            if (viewId == id) {//是所当前点击的view
                selectedFragment = fragment;
                view.setSelected(true);
            } else {
                fragmentTransaction.hide(fragment);//隐藏其他fragment
                view.setSelected(false);
            }
        }
        if (selectedFragment != null) {
            fragmentTransaction.show(selectedFragment);//显示当前fragment
        }
        fragmentTransaction.commit();
    }

完整代码

public class BottomAppBar extends LinearLayout {

    private float textSize;
    private int TEXTVIEW_ID ;
    private int IMAGEVIEW_ID ;
    private int ITEM_ID ;
    private ArrayList items = new ArrayList<>();
    private ArrayList itemTextViews = new ArrayList<>();
    private HashMap itemFragment = new HashMap<>();
    private HashMap itemImageViews = new HashMap<>();
    private Context context;
    private FragmentManager supportFragmentManager;
    private int layoutFragment;
    private BottomBarOnClick onClick;
    private ColorStateList colorStateList;
    private int textNormalColor;
    private int textSelectColor;
    private int itemRippleColor =-1;

    public BottomAppBar(Context context) {
        this(context, null);
    }

    public BottomAppBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public BottomAppBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
        TEXTVIEW_ID = (int) (System.currentTimeMillis()%100*10000);
        IMAGEVIEW_ID = (int) (System.currentTimeMillis()%100*1000);
        ITEM_ID = (int) (System.currentTimeMillis()%100*100);
    }

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.BottomAppBar);
            float dimension = typedArray.getDimension(R.styleable.BottomAppBar_mtextSize, 0);
            textSize = Uiutils.px2sp(context,dimension);
            textNormalColor = typedArray.getColor(R.styleable.BottomAppBar_mTextNormalColor, 0);
            textSelectColor = typedArray.getColor(R.styleable.BottomAppBar_mTextSelectColor, 0);

            typedArray.recycle();
        }
        setOrientation(LinearLayout.HORIZONTAL);
    }
    /**
     * 初始化的第一步
     *
     * @param Manager FragmentManager
     * @param layout  Fragment将要显示的容器控件 ViewGroup...
     * @return
     */
    public BottomAppBar init(FragmentManager Manager, @IdRes int layout) {
        this.supportFragmentManager = Manager;
        this.layoutFragment = layout;

        return this;
    }

    /**
     * 设置Item
     *
     * @param title item标题
     * @param drawable 图标选择器
     * @param fragment fragment
     * @param redPoint Item是否有小红点
     * @return
     */
    public BottomAppBar addItem(String title, Drawable drawable, Fragment fragment, boolean redPoint) {
        RelativeLayout relativeLayout = initItem(title, drawable, redPoint);
        relativeLayout.setId(items.size() + ITEM_ID);
        LinearLayout.LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f);//设置权重为1
        relativeLayout.setLayoutParams(lp);
        relativeLayout.setTag(items.size());
        relativeLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                showFragment(view.getId());
                RelativeLayout view1 = (RelativeLayout) view;
                view1.setSelected(true);
                onClick.onClickBar(view);
            }
        });
        items.add(relativeLayout);
       itemFragment.put(relativeLayout, fragment);

        return this;
    }

    /**
     * 初始化Item数据
     *
     * @param title
     * @param drawable
     * @param haveRedPoint
     * @return
     */
    private RelativeLayout initItem(String title, Drawable drawable, boolean haveRedPoint) {

        TextView textView = new TextView(context,null);
        textView.setText(title);
        textView.setTextSize(textSize);
        textView.setTextColor(textNormalColor);
        textView.setId(TEXTVIEW_ID);
        itemTextViews.add(textView);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        textView.setCompoundDrawables(null, drawable, null, null);
        RelativeLayout relativeLayout = new RelativeLayout(context);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
        textView.setGravity(Gravity.CENTER_HORIZONTAL);
        relativeLayout.addView(textView, layoutParams);
        if (haveRedPoint) {
            ImageView  imageView = new ImageView(context);
            int imageId = IMAGEVIEW_ID + items.size();
            imageView.setId(imageId);
            Drawable redPoint = context.getResources().getDrawable(R.drawable.red_dot_circle_14px);
            imageView.setImageDrawable(redPoint);
            RelativeLayout.LayoutParams layoutParamsDot = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            layoutParamsDot.addRule(RelativeLayout.ALIGN_RIGHT, TEXTVIEW_ID);
            layoutParamsDot.addRule(RelativeLayout.ALIGN_TOP, TEXTVIEW_ID);
            relativeLayout.addView(imageView, layoutParamsDot);
            imageView.setVisibility(View.GONE);
            itemImageViews.put(itemTextViews.size(),imageView);
        }
        TEXTVIEW_ID++;
        return relativeLayout;
    }


    /**
     * 显示fragment
     *
     * @param viewId
     */
    private void showFragment(int viewId) {
        Fragment selectedFragment = null;
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        for (Map.Entry viewFragmentEntry : itemFragment.entrySet()) {
            Fragment fragment = viewFragmentEntry.getValue();
            if (!fragment.isAdded()) {
                fragmentTransaction.add(layoutFragment, fragment);
            }
            RelativeLayout view = (RelativeLayout) viewFragmentEntry.getKey();
            int id = view.getId();
            TextView childAt = (TextView) view.getChildAt(0);
            if (viewId == id) {
                selectedFragment = fragment;
                view.setSelected(true);
                if (childAt!=null){
                    childAt.setTextColor(textSelectColor);
                }
            } else {
                fragmentTransaction.hide(fragment);
                view.setSelected(false);
                if (childAt!=null){
                    childAt.setTextColor(textNormalColor);
                }
            }
        }
        if (selectedFragment != null) {
            fragmentTransaction.show(selectedFragment);
        }
        fragmentTransaction.commit();
    }

    /**
     * 设置标题大小
     *
     * @param sp
     * @return
     */
    public BottomAppBar setTextSize(float sp) {
        this.textSize = sp;
        for (TextView itemTextView : itemTextViews) {
            itemTextView.setTextSize(textSize);
        }
        return this;
    }

    /**
     * 设置text颜色选择器
     *
     * @param resColor
     * @return
     */
    public BottomAppBar setTextColor(int resColor) {
         colorStateList = getResources().getColorStateList(resColor);
        for (TextView itemTextView : itemTextViews) {
            itemTextView.setTextColor(colorStateList);
        }
        return this;
    }

    /**
     * 设置item水波纹颜色,apis>21
     *
     * @param rippleColorRes
     * @return
     */
    public BottomAppBar setRippleColor(int rippleColorRes) {
        itemRippleColor =rippleColorRes;
        if (Build.VERSION.SDK_INT>=21) {
            for (RelativeLayout item : items) {
                Drawable itemBg = context.getResources().getDrawable(rippleColorRes);//R.drawable.bottom_bar_bg
                item.setBackground(itemBg);
            }

        }
        return this;
    }
    /**
     * 显示小红点
     * @param pointPlace 从左到右第几个小红点,从 1 开始
     *
     */
    public void showRed(int pointPlace)  {
        ImageView imageView = itemImageViews.get(pointPlace);
        if (imageView!=null) {
            imageView.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 隐藏小红点
     * @param pointPlace 从左到右第几个小红点,从 1 开始
     *
     */
    public void hideRed(int pointPlace)  {
        ImageView imageView = itemImageViews.get(pointPlace);
        if (imageView!=null) {
            imageView.setVisibility(View.GONE);
        }
    }

    /**
     * 设置全部的小红点, setRedPoint(1,0,0) 表示从左到右第一个小红点显示,后面两个不显示
     * @param show 当前位置的小红点是否显示
     */
    public void setRedPoint(int... show)  {
        for (int i = 0; i < show.length; i++) {
            int point = show[i];
            ImageView imageView = itemImageViews.get(i+1);
            if (imageView!=null) {
                if (point > 0) {
                    imageView.setVisibility(View.VISIBLE);
                } else {
                    imageView.setVisibility(View.GONE);
                }
            }else{
                Log.e("BottomBar","Not founded fragment");
            }
        }
    }

    /**
     * 把Item添加到bottomBar中
     * @param defshow 默认显示第几个fragment,从 1 开始
     */
    public void carete(int defshow) {
        for (int i = 0; i < items.size(); i++) {
            RelativeLayout relativeLayout = (RelativeLayout) items.get(i);
            if (itemRippleColor!=-1&&Build.VERSION.SDK_INT>=21) {
                Drawable itemBg = context.getResources().getDrawable(itemRippleColor);//R.drawable.bottom_bar_bg
                relativeLayout.setBackground(itemBg);
            }
            addView(relativeLayout);
        }
        RelativeLayout relativeLayout =null;
        try {
            relativeLayout = items.get(defshow-1);
        }catch (Exception e){
            Log.e("BottomBar","Not founded fragment");

        }
        int id = relativeLayout.getId();
       showFragment(id);
    }

    /**
     * 公开的外地调用方法,跳转到指定fragment
     * @param page 为导航栏从左到右Item的位置,最左边Item为1
     */
    public void showSubPage(int page){
        RelativeLayout relativeLayout =null;
        try {
            relativeLayout = items.get(page-1);
        }catch (Exception e){
            Log.e("BottomBar","Not founded fragment");

        }
        int viewId = relativeLayout.getId();
        Fragment selectedFragment = null;
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        for (Map.Entry viewFragmentEntry : itemFragment.entrySet()) {
            Fragment fragment = viewFragmentEntry.getValue();
            RelativeLayout view = (RelativeLayout) viewFragmentEntry.getKey();
            int id = view.getId();
            TextView childAt = (TextView) view.getChildAt(0);
            if (viewId == id) {
                selectedFragment = fragment;
                view.setSelected(true);
                if (childAt!=null){
                    childAt.setTextColor(textSelectColor);
                }
            } else {
                fragmentTransaction.hide(fragment);
                view.setSelected(false);
                if (childAt!=null){
                    childAt.setTextColor(textNormalColor);
                }
            }
        }
        if (selectedFragment != null) {
            fragmentTransaction.show(selectedFragment);
        }
        fragmentTransaction.commit();
    }

    public void setOnBottomBarOnClick(BottomBarOnClick click) {
        this.onClick = click;
    }
}

总结

看到你的赞,我从天台走了下来!

你可能感兴趣的:(Android 自定义底部导航栏)