全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Android自定义控件实现底部菜单(下)

在app中经常会用到底部菜单的控件,每次都需要写好多代码,今天我们用到了前几篇博客里的控件来进一步封装底部菜单。先看效果图:

主要包括以下功能:
1 设置icon以及点击之后的icon
2 设置文字
3 设置文字颜色以及点击之后的文字颜色
4 设置未读数量、更多以及new

我们先看如何使用,然后再看如何实现的

1 在布局文件中引用MenuM

<com.landptf.view.MenuM
  android:id="@+id/mm_bottom"
  android:layout_width="match_parent"
  android:layout_height="56dp"
  android:layout_alignParentBottom="true"
  landptf:backColor="@color/content"
  landptf:textColor="@color/text"
  landptf:textColorPress="@color/colorPrimary"
  landptf:count="4"
  />

这里主要说一下count属性,表示菜单项的个数。

2 在Activity中初始化

final MenuM mmBottom = (MenuM) findViewById(R.id.mm_bottom);
mmBottom.setText(text);
mmBottom.setIconDrawable(iconDrawable);
mmBottom.setIconDrawablePress(iconDrawablePress);
//设置默认选中第一项
mmBottom.setPressState(0, MotionEvent.ACTION_DOWN);
mmBottom.setOnItemClickListener(new MenuM.OnItemClickListener() {
  @Override
  public void onItemClick(int position) {
    Toast.makeText(MenuMTestActivity.this, mmBottom.getText(position), Toast.LENGTH_SHORT).show();
  }
});

mmBottom.setUnReadCount(0, 100);
mmBottom.setUnReadCount(1, 15);
mmBottom.setVisibilityMore(2, View.VISIBLE);
mmBottom.setVisibilityNew(3, View.VISIBLE);

有以下几个全局变量

text = new String[]{"首页", "通讯录", "发现", "我"};
//为了演示方便我只找了两张icon,在实际开发中一般需要从网络上下载,然后在设置
Drawable drawable = getResources().getDrawable(R.drawable.icon_home_page);
Drawable drawablePress = getResources().getDrawable(R.drawable.icon_home_page_press);
iconDrawable = new Drawable[]{drawable, drawable, drawable, drawable};
iconDrawablePress = new Drawable[]{drawablePress, drawablePress, drawablePress, drawablePress};

以上就是全部代码是不是很方便呢!!!
接下来我们来看下如何实现的

1 在style里定义了几个属性这里就不贴出来了,大家可以查看源码,在本文的最后会给出全部源码的下载地址
2 MenuM.java

package com.landptf.view;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.landptf.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by landptf on 2017/01/15.
 * 菜单,可用于底部导航菜单,以及内容区的菜单列表
 */
public class MenuM extends LinearLayout {
  private static final String TAG = MenuM.class.getSimpleName();

  private Context mContext;
  private List<MenuItemM> menuList;
  private List<RelativeLayout> rlList;
  private OnItemClickListener mOnItemClickListener;
  private int count = 0;

  public MenuM(Context context) {
    this(context, null, 0);
  }

  public MenuM(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public MenuM(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mContext = context;
    init(attrs, defStyle);
  }

  private void init(AttributeSet attrs, int defStyle) {
    setOrientation(LinearLayout.HORIZONTAL);
    TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.menuM, defStyle, 0);
    if (a != null) {
      //初始化菜单数量
      count = a.getInteger(R.styleable.menuM_count, 0);
      if (count > 0) {
        initControl();
      }
      //设置背景色
      ColorStateList colorList = a.getColorStateList(R.styleable.menuM_backColor);
      if (colorList != null) {
        int backColor = colorList.getColorForState(getDrawableState(), 0);
        if (backColor != 0) {
          setBackColor(backColor);
        }
      }
      //设置文字的颜色
      ColorStateList textColorList = a.getColorStateList(R.styleable.menuM_textColor);
      if (textColorList != null) {
        int textColor = textColorList.getColorForState(getDrawableState(), 0);
        if (textColor != 0) {
          setTextColor(textColor);
        }
      }
      //记录View被按下时文字的颜色
      ColorStateList textColorPressList = a.getColorStateList(R.styleable.menuM_textColorPress);
      if (textColorPressList != null) {
        int textColorPress = textColorPressList.getColorForState(getDrawableState(), 0);
        if (textColorPress != 0) {
          setTextColorPress(textColorPress);
        }
      }
      //设置文本字体大小
      float textSize = a.getFloat(R.styleable.menuM_textSize, 0);
      if (textSize != 0) {
        setTextSize(textSize);
      }
      a.recycle();
    }
  }

  /**
   * 由于MenuItemM是有ButtonExtendM扩展而来,为了适应上下左右不同的样式
   * 需要在MenuItemM外层嵌套一层RelativeLayout,暂时没有找到更好的替代方案
   */
  private void initControl() {
    rlList = new ArrayList<>(count);
    menuList = new ArrayList<>(count);
    for (int i = 0; i < count; i++) {
      RelativeLayout rlPanel = new RelativeLayout(mContext);
      LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
      lp.weight = 1;
      rlPanel.setLayoutParams(lp);
      final MenuItemM menuItem = new MenuItemM(mContext);
      RelativeLayout.LayoutParams lpR = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
      lpR.addRule(RelativeLayout.CENTER_IN_PARENT);
      menuItem.setLayoutParams(lpR);
      menuItem.setOnClickListener(new MenuItemM.OnClickListener() {
        @Override
        public void onClick(View v) {
          //此处需要根据view获取position
          MenuM.this.onClick(getPosition(menuItem));
        }
      });
      rlPanel.addView(menuItem);
      menuList.add(menuItem);
      rlList.add(rlPanel);
      addView(rlPanel);
    }
  }

  /**
   * 设置View的背景色
   *
   * @param backColor
   */
  public void setBackColor(int backColor) {
    if (backColor == 0) return;
    if (!checkCount()) {
      return;
    }
    for (RelativeLayout item : rlList) {
      item.setBackgroundColor(backColor);
    }
    for (MenuItemM item : menuList) {
      item.setBackColor(backColor);
    }
  }

  /**
   * 设置文字的颜色
   *
   * @param textColor
   */
  public void setTextColor(int textColor) {
    if (textColor == 0) return;
    if (!checkCount()) {
      return;
    }
    for (MenuItemM item : menuList) {
      item.setTextColor(textColor);
    }
  }

  /**
   * 设置View被按下时文字的颜色
   *
   * @param textColorPress
   */
  public void setTextColorPress(int textColorPress) {
    if (textColorPress == 0) return;
    if (!checkCount()) {
      return;
    }
    for (MenuItemM item : menuList) {
      item.setTextColorPress(textColorPress);
    }
  }

  /**
   * 设置icon的图片
   *
   * @param iconDrawable
   */
  public void setIconDrawable(Drawable[] iconDrawable) {
    if (count != iconDrawable.length) {
      Log.e(TAG, "the iconDrawable length do not equals count");
      return;
    }
    for (int i = 0; i < count; i++) {
      if (iconDrawable[i] != null) {
        menuList.get(i).setIconDrawable(iconDrawable[i]);
      }
    }
  }

  /**
   * 设置icon的图片
   *
   * @param iconDrawable
   */
  public void setIconDrawable(List<Drawable> iconDrawable) {
    if (count != iconDrawable.size()) {
      Log.e(TAG, "the iconDrawable length do not equals count");
      return;
    }
    for (int i = 0; i < count; i++) {
      if (iconDrawable.get(i) != null) {
        menuList.get(i).setIconDrawable(iconDrawable.get(i));
      }
    }
  }

  /**
   * 设置View被按下时的icon的图片
   *
   * @param iconDrawablePress
   */
  public void setIconDrawablePress(Drawable[] iconDrawablePress) {
    if (count != iconDrawablePress.length) {
      Log.e(TAG, "the iconDrawablePress length do not equals count");
      return;
    }
    for (int i = 0; i < count; i++) {
      if (iconDrawablePress[i] != null) {
        menuList.get(i).setIconDrawablePress(iconDrawablePress[i]);
      }
    }
  }

  /**
   * 设置View被按下时的icon的图片
   *
   * @param iconDrawablePress
   */
  public void setIconDrawablePress(List<Drawable> iconDrawablePress) {
    if (count != iconDrawablePress.size()) {
      Log.e(TAG, "the iconDrawablePress length do not equals count");
      return;
    }
    for (int i = 0; i < count; i++) {
      if (iconDrawablePress.get(i) != null) {
        menuList.get(i).setIconDrawablePress(iconDrawablePress.get(i));
      }
    }
  }

  /**
   * 设置显示的文本内容
   *
   * @param text
   */
  public void setText(CharSequence[] text) {
    for (int i = 0; i < count; i++) {
      menuList.get(i).setText(text[i]);
    }
  }

  /**
   * 设置显示的文本内容
   *
   * @param text
   */
  public void setText(List<CharSequence> text) {
    if (count != text.size()) {
      Log.e(TAG, "the text length do not equals count");
      return;
    }
    for (int i = 0; i < count; i++) {
      menuList.get(i).setText(text.get(i));
    }
  }

  /**
   * 获取显示的文本
   *
   * @return
   */
  public String getText(int index) {
    if (!checkIndex(index)) {
      return "";
    }
    return menuList.get(index).getText();
  }

  /**
   * 设置文本字体大小
   *
   * @param size
   */
  public void setTextSize(float size) {
    if (!checkCount()) {
      return;
    }
    for (MenuItemM item : menuList) {
      item.setTextSize(size);
    }
  }

  /**
   * 设置更多提示是否显示
   * 如果显示则先重置new和未读数量图标
   *
   * @param visibleMore
   */
  public void setVisibilityMore(int index, int visibleMore) {
    if (!checkIndex(index)) {
      return;
    }
    menuList.get(index).setVisibilityMore(visibleMore);
  }

  /**
   * 设置New提示是否显示
   * 如果显示则先重置更多和未读数量图标
   *
   * @param visibleNew
   */
  public void setVisibilityNew(int index, int visibleNew) {
    if (!checkIndex(index)) {
      return;
    }
    menuList.get(index).setVisibilityNew(visibleNew);
  }

  /**
   * 设置未读数量
   * 如果小于等于0,表示隐藏
   * 如果大于99,则将其隐藏,同时显示更多的提示
   * 如果在0-99区间,则隐藏更多和new图标
   *
   * @param unReadCount
   */
  public void setUnReadCount(int index, int unReadCount) {
    if (!checkIndex(index)) {
      return;
    }
    menuList.get(index).setUnReadCount(unReadCount);
  }

  /**
   * 设置为被选中状态
   *
   * @param index
   * @param state in MotionEvent.ACTION_DOWN or MotionEvent.ACTION_UP
   */
  public void setPressState(int index, int state) {
    if (!checkIndex(index)) {
      return;
    }
    menuList.get(index).setPressState(state);
  }

  /**
   * 设置菜单点击事件
   *
   * @param listener
   */
  public void setOnItemClickListener(@Nullable OnItemClickListener listener) {
    mOnItemClickListener = listener;
  }

  private void onClick(int position) {
    for (int i = 0; i < count; i++) {
      if (i == position) {
        setPressState(i, MotionEvent.ACTION_DOWN);
      } else {
        setPressState(i, MotionEvent.ACTION_UP);
      }
    }
    mOnItemClickListener.onItemClick(position);
  }

  /**
   * 获取点击菜单项的位置
   * @param item
   * @return
   */
  private int getPosition(MenuItemM item) {
    for (int i = 0; i < count; i++) {
      if (item == menuList.get(i)) {
        return i;
      }
    }
    return -1;
  }

  /**
   * 检查是否设置了Count参数
   *
   * @return
   */
  private boolean checkCount() {
    if (count == 0) {
      Log.e(TAG, "You must set the count first");
      return false;
    }
    return true;
  }

  /**
   * 校验输入参数是否合法
   *
   * @param index
   * @return
   */
  private boolean checkIndex(int index) {
    if (!checkCount()) {
      return false;
    }
    if (index < 0 || index >= count) {
      Log.e(TAG, "the index is wrong");
      return false;
    }
    return true;
  }

  public interface OnItemClickListener {
    void onItemClick(int position);
  }
}


代码比较简单,相信大家看一遍都可以理解,这里面使用了MenuItemM自定义控件,有不了解的可以参考以前的博客https://www./article/103913.htm或者查看源码。
全部代码已托管到开源中国的码云上,欢迎下载,地址:https://git.oschina.net/landptf/landptf.git

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Android  # 底部菜单  # Android使用CoordinatorLayout实现底部弹出菜单  # Android底部菜单栏实现的实例代码  # android SectorMenuView底部导航扇形菜单的实现代码  # android实现上滑屏幕隐藏底部菜单栏的示例  # Android仿微信底部菜单栏效果  # Android仿网易严选底部弹出菜单效果  # Android使用Activity实现从底部弹出菜单或窗口的方法  # Android自定义控件实现底部菜单(上)  # Android如何实现底部菜单固定到底部  # 按下  # 几个  # 先看  # 如何实现  # 背景色  # 菜单项  # 来了  # 是有  # 下载地址  # 就不  # 我只  # 而来  # 一遍  # 博客  # 上下左右  # 找了  # 自定义  # 会给  # 不了解  # 再看 


相关文章: 较简单的网站制作软件有哪些,手机版网页制作用什么软件?  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  网站制作公司排行榜,抖音怎样做个人官方网站  娃派WAP自助建站:免费模板+移动优化,快速打造专业网站  免费公司网站制作软件,如何申请免费主页空间做自己的网站?  如何在阿里云虚拟主机上快速搭建个人网站?  如何零成本快速生成个人自助网站?  建站主机是否属于云主机类型?  油猴 教程,油猴搜脚本为什么会网页无法显示?  如何快速生成专业多端适配建站电话?  建站之星客服服务时间及联系方式如何?  如何登录建站主机?访问步骤全解析  如何在万网开始建站?分步指南解析  广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?  网站制作价目表怎么做,珍爱网婚介费用多少?  潍坊网站制作公司有哪些,潍坊哪家招聘网站好?  如何在Tomcat中配置并部署网站项目?  如何快速生成高效建站系统源代码?  北京营销型网站制作公司,可以用python做一个营销推广网站吗?  家庭建站与云服务器建站,如何选择更优?  如何通过VPS建站无需域名直接访问?  大型企业网站制作流程,做网站需要注册公司吗?  建站之星下载版如何获取与安装?  建站主机无法访问?如何排查域名与服务器问题  保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?  建站主机是否等同于虚拟主机?  如何通过多用户协作模板快速搭建高效企业网站?  制作网站的基本流程,设计网站的软件是什么?  建站之星多图banner生成与模板自定义指南  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  简历在线制作网站免费版,如何创建个人简历?  建站之星上传入口如何快速找到?  制作网站怎么制作,*游戏网站怎么搭建?  建站主机选购指南与交易推荐:核心配置解析  盐城做公司网站,江苏电子版退休证办理流程?  简单实现Android文件上传  建站之星安装后如何自定义网站颜色与字体?  网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?  大连 网站制作,大连天途有线官网?  如何在宝塔面板创建新站点?  php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】  如何通过万网虚拟主机快速搭建网站?  网站制作的步骤包括,正确网址格式怎么写?  如何在建站之星网店版论坛获取技术支持?  ,网站推广常用方法?  ,想在网上投简历,哪几个网站比较好?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  如何选择香港主机高效搭建外贸独立站?  如何快速搭建高效WAP手机网站?  建站之星如何优化SEO以实现高效排名? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。