鸿蒙系统—打造通用的底部导航栏

2020-12-23  本文已影响0人  裴云飞

一、效果图

二、设计方案

三、定义接口

1、定义一个IBarLayout接口,第一个泛型就是底部导航栏中的每个条目,第二个泛型是每个条目的数据。在接口里面提供一些方法,可以根据数据查找条目,可以添加监听,可以设置默认选中的条目,可以初始化所有的条目,当某个条目被选中后需要告知外界。

/**
 * 外层容器的接口,第一个泛型就是底部导航栏中的每个条目,第二个泛型是每个条目的数据
 *
 * @author 裴云飞
 * @date 2020/12/22
 */
public interface IBarLayout<Bar extends ComponentContainer, D> {

    /**
     * 根据数据查找条目
     *
     * @param data 数据
     * @return 条目
     */
    Bar findBar(D data);

    /**
     * 添加监听
     *
     * @param listener
     */
    void addBarSelectedChangeListener(OnBarSelectedListener<D> listener);

    /**
     * 默认选中的条目
     *
     * @param defaultInfo
     */
    void defaultSelected(D defaultInfo);

    /**
     * 初始化所有的条目
     *
     * @param infoList
     */
    void initInfo(List<D> infoList);

    interface OnBarSelectedListener<D> {

        /**
         * 当某个条目被选中后的回调,该方法会被调用多次
         *
         * @param index 点击后选中条目的下标
         * @param preInfo 点击前选中的条目
         * @param nextInfo 点击后选中的条目
         */
        void onBarSelectedChange(int index, D preInfo, D nextInfo);
    }
}

2、再定义一个单个条目的接口,泛型就是每个条目的数据,接口里面定义方法,可以设置条目的数据,可以动态修改某个条目的大小

/**
 * 单个条目的接口
 *
 * @author 裴云飞
 * @date 2020/12/22
 */
public interface IBar<D> extends IBarLayout.OnBarSelectedListener<D> {

    /**
     * 设置条目的数据
     *
     * @param data
     */
    void setBarInfo(D data);

    /**
     * 动态修改某个条目的大小
     *
     * @param height
     */
    void resetHeight(int height);
}

三、每个条目所对应的实体类

每个条目都有自己的图片、文字、文字的颜色,我们把这些属性定义在一个实体类中。由于颜色可以是整型,也可以是字符串,这里定义泛型,泛型就是文字的颜色。具体是哪种类型的颜色,由调用者来决定。
注意下BarType这个枚举,我们的底部导航栏支持两种类型,IMAGE代表下图,某个条目只显示图片,也可以让某个条目凸出来,只需要将条目的高度变高即可。

image.png

IMAGE_TEXT代表条目显示图片和文字。如下图


image.png
/**
 * 每个条目的数据,泛型对应的是文字的颜色,颜色可以是整型,也可以是字符串,具体是哪种类型的颜色,由调用者来决定
 *
 * @author 裴云飞
 * @date 2020/12/22
 */
public class BottomBarInfo<Color> {

    public enum BarType {
        /**
         * 显示图片和文案
         */
        IMAGE_TEXT,
        /**
         * 只显示图片
         */
        IMAGE
    }

    /**
     * 默认的图片
     */
    public int defaultImage;
    /**
     * 选中后的图片
     */
    public int selectedImage;
    /**
     * 默认的文字颜色
     */
    public Color defaultColor;
    /**
     * 选中后的文字颜色
     */
    public Color tintColor;
    /**
     * 条目的名称
     */
    public String name;
    public BarType tabType;

    public BottomBarInfo(String name, int defaultImage, int selectedImage) {
        this.name = name;
        this.defaultImage = defaultImage;
        this.selectedImage = selectedImage;
        this.tabType = BarType.IMAGE;
    }

    public BottomBarInfo(String name, int defaultImage, int selectedImage, Color defaultColor, Color tintColor) {
        this.name = name;
        this.defaultImage = defaultImage;
        this.selectedImage = selectedImage;
        this.defaultColor = defaultColor;
        this.tintColor = tintColor;
        this.tabType = BarType.IMAGE_TEXT;
    }
}

四、单个条目的布局

1、在布局文件实现单个条目的布局,很简单,使用相对布局,文字位于屏幕的底部,图片位于文字的上面。

<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:orientation="vertical"
    ohos:width="match_parent">

    <Image
        ohos:top_margin="4vp"
        ohos:bottom_margin="4vp"
        ohos:height="match_content"
        ohos:horizontal_center="1"
        ohos:id="$+id:image"
        ohos:above="$id:name"
        ohos:width="match_content"/>

    <Text
        ohos:id="$+id:name"
        ohos:align_parent_bottom="1"
        ohos:height="match_content"
        ohos:text="首页"
        ohos:text_size="10vp"
        ohos:bottom_margin="5vp"
        ohos:width="match_content"
        ohos:horizontal_center="1"/>
</DependentLayout>

五、单个条目的封装

1、定义BottomBar,继承相对布局,实现之前定义的IBar接口,泛型就是每个条目所对应的实体类,由于目前并不知道泛型的具体类型,所以泛型直接使用问号来代替。BottomBar就是单个条目。

/**
 * 单个条目的封装,由于目前并不知道泛型的具体类型,所以泛型直接使用问号来代替
 *
 * @author 裴云飞
 * @date 2020/12/22
 */
public class BottomBar extends DependentLayout implements IBar<BottomBarInfo<?>> {

    /**
     * 当前条目所对应的数据
     */
    private BottomBarInfo<?> tabInfo;
    private Text mTabName;
    private Image mTabImage;

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

    public BottomBar(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public BottomBar(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        Component component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_tab_bottom, this, true);
        mTabImage = (Image) component.findComponentById(ResourceTable.Id_image);
        mTabName = (Text) component.findComponentById(ResourceTable.Id_name);
        mTabImage.setScaleMode(Image.ScaleMode.INSIDE);
    }

    /**
     * 设置条目的数据
     *
     * @param data
     */
    @Override
    public void setBarInfo(BottomBarInfo<?> data) {
        tabInfo = data;
        inflateInfo(false, true);
    }

    /**
     * 初始化条目
     *
     * @param selected true 选中
     * @param init true 初始化
     */
    private void inflateInfo(boolean selected, boolean init) {
        if (tabInfo.tabType == BottomBarInfo.TabType.IMAGE_TEXT) {
            if (init) {
                mTabName.setVisibility(VISIBLE);
                mTabImage.setVisibility(VISIBLE);
                if (!TextUtils.isEmpty(tabInfo.name)) {
                    mTabName.setText(tabInfo.name);
                }
            }
            if (selected) {
                mTabImage.setPixelMap(tabInfo.selectedImage);
                mTabName.setTextColor(new Color(parseColor(tabInfo.tintColor)));
            } else {
                mTabImage.setPixelMap(tabInfo.defaultImage);
                mTabName.setTextColor(new Color(parseColor(tabInfo.defaultColor)));
            }
        } else if (tabInfo.tabType == BottomBarInfo.TabType.IMAGE) {
            if (init) {
                mTabName.setVisibility(HIDE);
                mTabImage.setVisibility(VISIBLE);
            }
            if (selected) {
                mTabImage.setPixelMap(tabInfo.selectedImage);
            } else {
                mTabImage.setPixelMap(tabInfo.defaultImage);
            }
        }
    }

    private int parseColor(Object color) {
        if (color instanceof String) {
            return Color.getIntColor((String) color);
        } else {
            return (int) color;
        }
    }

    /**
     * 动态修改某个tab的高度
     *
     * @param height tab的高度
     */
    @Override
    public void resetHeight(int height) {
        ComponentContainer.LayoutConfig config = getLayoutConfig();
        config.height = height;
        setLayoutConfig(config);
        mTabName.setVisibility(HIDE);
    }

    /**
     * 当某个条目被选中后的回调,该方法会被调用多次
     *
     * @param index 点击后选中条目的下标
     * @param preInfo 点击前选中的条目
     * @param nextInfo 点击后选中的条目
     */
    @Override
    public void onBarSelectedChange(int index, BottomBarInfo<?> preInfo, BottomBarInfo<?> nextInfo) {
        if (nextInfo.tabType == BottomBarInfo.TabType.IMAGE) {
            return;
        }
        if (preInfo == nextInfo) {
            // 假设当前选中的是tab1,同时点击的也是tab1,那就不需要做任何操作了
            return;
        }
        if (preInfo != tabInfo && nextInfo != tabInfo) {
            /**
             * 假设有三个条目,条目1、条目2、条目3,preInfo是条目1,nextInfo是条目3,tabInfo是条目2,
             * 点击前选中的是条目1,点击后选中的条目3,此时条目2就不需要做任何操作了
             */
            return;
        }
        if (preInfo == tabInfo) {
            // 将点击前的条目反选
            inflateInfo(false, false);
        } else {
            // 选中被点击的条目
            inflateInfo(true, false);
        }
    }

    public BottomBarInfo<?> getTabInfo() {
        return tabInfo;
    }

    public Text getTabName() {
        return mTabName;
    }

    public Image getImage() {
        return mTabImage;
    }
}
public BottomBar(Context context) {
    this(context, null);
}

public BottomBar(Context context, AttrSet attrSet) {
    this(context, attrSet, "");
}

public BottomBar(Context context, AttrSet attrSet, String styleName) {
    super(context, attrSet, styleName);
    Component component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_tab_bottom, this, true);
    mTabImage = (Image) component.findComponentById(ResourceTable.Id_image);
    mTabName = (Text) component.findComponentById(ResourceTable.Id_name);
    mTabImage.setScaleMode(Image.ScaleMode.INSIDE);
}
/**
 * 设置条目的数据
 *
 * @param data
 */
@Override
public void setBarInfo(BottomBarInfo<?> data) {
    tabInfo = data;
    inflateInfo(false, true);
}
    /**
     * 动态修改某个tab的高度
     *
     * @param height tab的高度
     */
    @Override
    public void resetHeight(int height) {
        ComponentContainer.LayoutConfig config = getLayoutConfig();
        config.height = height;
        setLayoutConfig(config);
        mTabName.setVisibility(HIDE);
    }
    /**
     * 当某个条目被选中后的回调,该方法会被调用多次
     *
     * @param index 点击后选中条目的下标
     * @param preInfo 点击前选中的条目
     * @param nextInfo 点击后选中的条目
     */
    @Override
    public void onBarSelectedChange(int index, BottomBarInfo<?> preInfo, BottomBarInfo<?> nextInfo) {
        if (nextInfo.tabType == BottomBarInfo.BarType.IMAGE) {
            // 当前条目的类型是IMAGE类型,则不做任何处理
            return;
        }
        if (preInfo == nextInfo) {
            // 假设当前选中的是条目1,同时点击的也是条目1,那就不需要做任何操作了
            return;
        }
        if (preInfo != tabInfo && nextInfo != tabInfo) {
            /**
             * 假设有三个条目,条目1、条目2、条目3,preInfo是条目1,nextInfo是条目3,tabInfo是条目2,
             * 点击前选中的是条目1,点击后选中的条目3,此时条目2就不需要做任何操作了
             */
            return;
        }
        if (preInfo == tabInfo) {
            // 将点击前的条目反选
            inflateInfo(false, false);
        } else {
            // 选中被点击的条目
            inflateInfo(true, false);
        }
    }

六、底部导航栏的封装。

定义BottomNavigationBar,继承栈布局。第一个泛型就是底部导航栏的条目,第二个泛型就是每个条目的数据

/**
 * 底部导航栏的封装,第一个泛型就是底部导航栏的条目,第二个泛型就是每个条目的数据
 *
 * @author 裴云飞
 * @date 2020/12/20
 */
public class BottomNavigationBar extends StackLayout implements IBarLayout<BottomBar, BottomBarInfo<?>> {

    private static final int ID_TAB_BOTTOM = 0XFF;
    /**
     * 事件监听的集合
     */
    private List<OnBarSelectedListener<BottomBarInfo<?>>> tabSelectedListeners = new ArrayList<>();
    /**
     * 当前选中的条目
     */
    private BottomBarInfo<?> selectedInfo;
    /**
     * 底部导航栏的透明度
     */
    private float barBottomAlpha = 1;
    /**
     * 底部导航栏的高度
     */
    private float barBottomHeight = 50;
    /**
     * 底部导航栏线条的高度
     */
    private float barBottomLineHeight = 0.5f;
    /**
     * 底部导航栏线条的颜色
     */
    private RgbColor barBottomLineColor = new RgbColor(223, 224, 225);
    /**
     * 所有的tab
     */
    private List<BottomBarInfo<?>> infoList;

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

    public BottomNavigationBar(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public BottomNavigationBar(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    /**
     * 根据数据查找条目
     *
     * @param info 条目的数据
     * @return 条目
     */
    @Override
    public BottomBar findBar(BottomBarInfo<?> info) {
        ComponentContainer componentContainer = (ComponentContainer) findComponentById(ID_TAB_BOTTOM);
        for (int i = 0; i < componentContainer.getChildCount(); i++) {
            Component component = componentContainer.getComponentAt(i);
            if (component instanceof BottomBar) {
                BottomBar bottomBar = (BottomBar) component;
                if (bottomBar.getTabInfo() == info) {
                    return bottomBar;
                }
            }
        }
        return null;
    }

    /**
     * 添加监听
     *
     * @param listener 监听
     */
    @Override
    public void addBarSelectedChangeListener(OnBarSelectedListener<BottomBarInfo<?>> listener) {
        tabSelectedListeners.add(listener);
    }

    /**
     * 默认选中的条目
     *
     * @param defaultInfo 默认选中条目的信息
     */
    @Override
    public void defaultSelected(BottomBarInfo<?> defaultInfo) {
        onSelected(defaultInfo);
    }

    /**
     * 初始化所有的条目
     *
     * @param infoList 所有条目的信息
     */
    @Override
    public void initInfo(List<BottomBarInfo<?>> infoList) {
        if (infoList == null || infoList.isEmpty()) {
            return;
        }
        this.infoList = infoList;
        // 移除之前已经添加的组件,防止重复添加
        removeComponent();
        selectedInfo = null;
        // 添加背景
        addBackground();
        // 添加条目
        addBottomBar();
        // 添加线条
        addBottomLine();
    }

    /**
     * 添加线条
     */
    private void addBottomLine() {
        Component line = new Component(getContext());
        // 目前不支持直接设置背景颜色,只能通过Element来设置背景
        ShapeElement element = new ShapeElement();
        element.setShape(ShapeElement.RECTANGLE);
        element.setRgbColor(barBottomLineColor);
        line.setBackground(element);
        LayoutConfig config = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                DisplayUtils.vp2px(getContext(), barBottomLineHeight));
        // 位于底部
        config.alignment = LayoutAlignment.BOTTOM;
        config.setMarginBottom(DisplayUtils.vp2px(getContext(), barBottomHeight - barBottomLineHeight));
        line.setAlpha(barBottomAlpha);
        addComponent(line, config);
    }

    /**
     * 添加条目
     */
    private void addBottomBar() {
        int width = DisplayUtils.getDisplayWidthInPx(getContext()) / infoList.size();
        int height = DisplayUtils.vp2px(getContext(), barBottomHeight);
        StackLayout stackLayout = new StackLayout(getContext());
        stackLayout.setId(ID_TAB_BOTTOM);
        for (int i = 0; i < infoList.size(); i++) {
            BottomBarInfo<?> info = infoList.get(i);
            LayoutConfig config = new LayoutConfig(width, height);
            config.alignment = LayoutAlignment.BOTTOM;
            config.setMarginLeft(i * width);
            BottomBar bottomBar = new BottomBar(getContext());
            tabSelectedListeners.add(bottomBar);
            bottomBar.setBarInfo(info);
            stackLayout.addComponent(bottomBar, config);
            bottomBar.setClickedListener(component -> onSelected(info));
        }
        LayoutConfig layoutConfig = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_CONTENT);
        layoutConfig.alignment = LayoutAlignment.BOTTOM;
        addComponent(stackLayout, layoutConfig);
    }

    private void onSelected(BottomBarInfo<?> nextInfo) {
        for (OnBarSelectedListener<BottomBarInfo<?>> listener : tabSelectedListeners) {
            listener.onBarSelectedChange(infoList.indexOf(nextInfo), selectedInfo, nextInfo);
        }
        if (nextInfo.tabType == BottomBarInfo.BarType.IMAGE_TEXT) {
            selectedInfo = nextInfo;
        }
    }

    /**
     * 添加背景
     */
    private void addBackground() {
        Component component = new Component(getContext());
        // 目前还不能直接设置背景颜色,只能通过Element来设置背景
        ShapeElement element = new ShapeElement();
        element.setShape(ShapeElement.RECTANGLE);
        RgbColor rgbColor = new RgbColor(255, 255, 255);
        element.setRgbColor(rgbColor);
        component.setBackground(element);
        component.setAlpha(barBottomAlpha);
        LayoutConfig config = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                DisplayUtils.vp2px(getContext(), barBottomHeight));
        config.alignment = LayoutAlignment.BOTTOM;
        addComponent(component, config);
    }

    /**
     * 移除之前已经添加的组件,防止重复添加
     */
    private void removeComponent() {
        for (int i = getChildCount() - 1; i > 0; i--) {
            removeComponentAt(i);
        }
        tabSelectedListeners.removeIf(listener ->
                listener instanceof BottomBar);
    }

    /**
     * 设置底部导航栏的透明度
     *
     * @param barBottomAlpha 底部导航栏的透明度
     */
    public void setBarBottomAlpha(float barBottomAlpha) {
        this.barBottomAlpha = barBottomAlpha;
    }

    /**
     * 设置底部导航栏的高度
     *
     * @param barBottomHeight 底部导航栏的高度
     */
    public void setBarBottomHeight(float barBottomHeight) {
        this.barBottomHeight = barBottomHeight;
    }

    /**
     * 设置底部导航栏线条的高度
     *
     * @param barBottomLineHeight 底部导航栏线条的高度
     */
    public void setBarBottomLineHeight(float barBottomLineHeight) {
        this.barBottomLineHeight = barBottomLineHeight;
    }

    /**
     * 设置底部导航栏线条的颜色
     *
     * @param barBottomLineColor 底部导航栏线条的颜色
     */
    public void setBarBottomLineColor(RgbColor barBottomLineColor) {
        this.barBottomLineColor = barBottomLineColor;
    }
}
    private void removeComponent() {
        for (int i = getChildCount() - 1; i > 0; i--) {
            removeComponentAt(i);
        }
        tabSelectedListeners.removeIf(listener ->
                listener instanceof BottomBar);
    }
移除之前已经添加的组件,防止重复添加
    /**
     * 添加背景
     */
    private void addBackground() {
        Component component = new Component(getContext());
        // 目前还不能直接设置背景颜色,只能通过Element来设置背景
        ShapeElement element = new ShapeElement();
        element.setShape(ShapeElement.RECTANGLE);
        RgbColor rgbColor = new RgbColor(255, 255, 255);
        element.setRgbColor(rgbColor);
        component.setBackground(element);
        component.setAlpha(barBottomAlpha);
        LayoutConfig config = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                DisplayUtils.vp2px(getContext(), barBottomHeight));
        config.alignment = LayoutAlignment.BOTTOM;
        addComponent(component, config);
    }
目前还不能直接设置背景颜色,只能通过Element来设置背景。在添加组件之前,需要创建布局配置对象,布局配置对象里面有组件的宽度、高度、对齐方式等。
    /**
     * 添加条目
     */
    private void addBottomBar() {
        // 每个条目的宽度就是屏幕宽度除以条目的总个数
        int width = DisplayUtils.getDisplayWidthInPx(getContext()) / infoList.size();
        // 高度是固定的值,这里需要做屏幕适配,将vp转换成像素
        int height = DisplayUtils.vp2px(getContext(), barBottomHeight);
        StackLayout stackLayout = new StackLayout(getContext());
        stackLayout.setId(ID_TAB_BOTTOM);
        for (int i = 0; i < infoList.size(); i++) {
            BottomBarInfo<?> info = infoList.get(i);
            // 创建布局配置对象
            LayoutConfig config = new LayoutConfig(width, height);
            // 设置底部对齐
            config.alignment = LayoutAlignment.BOTTOM;
            // 设置左边距
            config.setMarginLeft(i * width);
            BottomBar bottomBar = new BottomBar(getContext());
            tabSelectedListeners.add(bottomBar);
            // 初始化每个条目
            bottomBar.setBarInfo(info);
            // 添加条目
            stackLayout.addComponent(bottomBar, config);
            // 设置点击事件
            bottomBar.setClickedListener(component -> onSelected(info));
        }
        LayoutConfig layoutConfig = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_CONTENT);
        layoutConfig.alignment = LayoutAlignment.BOTTOM;
        // 将条目添加度导航栏
        addComponent(stackLayout, layoutConfig);
    }
    /**
     * 点击条目后给外界回调
     *
     * @param nextInfo 点击后需要选中的条目
     */
    private void onSelected(BottomBarInfo<?> nextInfo) {
        for (OnBarSelectedListener<BottomBarInfo<?>> listener : tabSelectedListeners) {
            listener.onBarSelectedChange(infoList.indexOf(nextInfo), selectedInfo, nextInfo);
        }
        if (nextInfo.tabType == BottomBarInfo.BarType.IMAGE_TEXT) {
            selectedInfo = nextInfo;
        }
    }

七、外界调用

至此,底部导航栏已经封装完成,外界如何使用呢?
1、在布局文件中添加BottomNavigationBar,这个就是我们封装好的底部导航栏

<?xml version="1.0" encoding="utf-8"?>
<com.pyf.ui.bar.bottom.BottomNavigationBar
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:id="$+id:bottom_navigationBar"
    ohos:height="match_parent"
    ohos:orientation="vertical"
    ohos:width="match_parent">

</com.pyf.ui.bar.bottom.BottomNavigationBar>

2、在AlibitySlice里面使用,这里使用MVP模式,将业务逻辑放入presenter层中。
先定义接口

/**
 * @author 裴云飞
 * @date 2020/12/22
 */
/**
 * AbilitySlice实现该接口
 *
 * @author 裴云飞
 * @date 2020/12/22
 */
public interface AbilitySliceProvider {

    /**
     * 系统已有的方法,不需要单独实现
     *
     * @param id
     * @return
     */
    Component findComponentById(int id);

    /**
     * 系统已有的方法,不需要单独实现
     *
     * @return
     */
    ResourceManager getResourceManager();

    /**
     * 获取string.json文件中定义的字符串
     *
     * @param resId
     * @return
     */
    String getString(int resId);

    /**
     * 获取color.json文件中定义的颜色值
     *
     * @param colorId
     * @return
     */
    int getColor(int colorId);

    /**
     * 获取上下文,系统已有的方法,不需要单独实现
     *
     * @return
     */
    Context getContext();
}

3、MainAbilitySlice实现AbilitySliceProvider接口,getContext、getResourceManager、findComponentById这三个方法AbilitySlice的父类已经帮我们实现了,这些方法其实就是系统的方法。getString和getColor需要我们自己来实现,我们在BaseAbilitySlice中手动实现这两个方法。在MainAbilitySlice的onStart方法中创建MainAbilitySlicePresenter对象,这样就能在MainAbilitySlicePresenter处理具体的业务逻辑。

public class MainAbilitySlice extends BaseAbilitySlice implements AbilitySliceProvider {

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        // 使用MVP模式,将业务逻辑放到presenter中
        new MainAbilitySlicePresenter(this);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

}

4、MainAbilitySlicePresenterr处理具体的业务逻辑

/**
 * 业务逻辑放到这个类来做
 *
 * @author 裴云飞
 * @date 2020/12/22
 */
public class MainAbilitySlicePresenter {

    private AbilitySliceProvider mAbilitySliceProvider;
    private List<BottomBarInfo<?>> infoList;
    private BottomNavigationBar tabBottomLayout;
    private Context mContext;
    public MainAbilitySlicePresenter(AbilitySliceProvider abilitySliceProvider) {
        mAbilitySliceProvider = abilitySliceProvider;
        mContext = abilitySliceProvider.getContext();
        initBottom();
    }

    private void initBottom() {
        tabBottomLayout = (BottomNavigationBar) mAbilitySliceProvider.findComponentById(ResourceTable.Id_bottom_navigationBar);
        infoList = new ArrayList<>();
        // 获取color.json文件中定义的颜色值
        int defaultColor = mAbilitySliceProvider.getColor(ResourceTable.Color_default_color);
        int tintColor = mAbilitySliceProvider.getColor(ResourceTable.Color_tint_color);
        // 获取string.json文件中定义的字符串
        String home = mAbilitySliceProvider.getString(ResourceTable.String_home);
        String favorite = mAbilitySliceProvider.getString(ResourceTable.String_favorite);
        String category = mAbilitySliceProvider.getString(ResourceTable.String_category);
        String recommend = mAbilitySliceProvider.getString(ResourceTable.String_recommend);
        String profile = mAbilitySliceProvider.getString(ResourceTable.String_profile);
        // 首页
        BottomBarInfo<Integer> honeInfo = new BottomBarInfo<>(home,
                ResourceTable.Media_home_normal,
                ResourceTable.Media_home_selected,
                defaultColor, tintColor);
        // 收藏
        BottomBarInfo<Integer> favoriteInfo = new BottomBarInfo<>(favorite,
                ResourceTable.Media_favorite_normal,
                ResourceTable.Media_favorite_selected,
                defaultColor, tintColor);
        // 分类
        BottomBarInfo<Integer> categoryInfo = new BottomBarInfo<>(category,
                ResourceTable.Media_category_normal,
                ResourceTable.Media_category_selected,
                defaultColor, tintColor);
        // 推荐
        BottomBarInfo<Integer> recommendInfo = new BottomBarInfo<>(recommend,
                ResourceTable.Media_recommend_normal,
                ResourceTable.Media_recommend_selected,
                defaultColor, tintColor);
        // 我的
        BottomBarInfo<Integer> profileInfo = new BottomBarInfo<>(profile,
                ResourceTable.Media_profile_normal,
                ResourceTable.Media_profile_selected,
                defaultColor, tintColor);
        // 将每个条目的数据放入到集合
        infoList.add(honeInfo);
        infoList.add(favoriteInfo);
        infoList.add(categoryInfo);
        infoList.add(recommendInfo);
        infoList.add(profileInfo);
        // 设置底部导航栏的透明度
        tabBottomLayout.setBarBottomAlpha(0.85f);
        // 初始化所有的条目
        tabBottomLayout.initInfo(infoList);
        tabBottomLayout.addBarSelectedChangeListener((index, prevInfo, nextInfo) ->
                        // 点击条目后给出提示信息
                        Toast.show(mContext, nextInfo.name));
        // 设置默认选中的条目,该方法一定要在最后调用
        tabBottomLayout.defaultSelected(honeInfo);
        // 如果想让某个条目凸出来,可以按照下面的方式
        // 创建凸出来的条目,这张凸出来的图片肯定是要比不凸出来的图片大点
//        BottomBarInfo<Integer> message = new BottomBarInfo<>(recommend,
//                ResourceTable.Media_recommend_normal,
//                ResourceTable.Media_recommend_selected);
//        // 将条目添加集合
//        infoList.add(message);
//        // 在底部导航栏中查找该条目
//        BottomBar bottomBar = tabBottomLayout.findBar(message);
//        // 修改该条目的高度
//        bottomBar.resetHeight(DisplayUtils.vp2px(mContext, 66));
    }
}

5、如果想让某个条目凸出来,可以按照下面的方式

        // 创建凸出来的条目,这张凸出来的图片肯定是要比不凸出来的图片大点
        BottomBarInfo<Integer> message = new BottomBarInfo<>(recommend,
                ResourceTable.Media_recommend_normal,
                ResourceTable.Media_recommend_normal);
        // 将条目添加集合
        infoList.add(message);
        // 在底部导航栏中查找该条目
        BottomBar bottomBar = tabBottomLayout.findBar(message);
        // 修改该条目的高度
        bottomBar.resetHeight(DisplayUtils.vp2px(mContext, 66));

最后附上源码
注:项目用到的图片全部来源于阿里矢量图库,如果缺少图片,可以阿里矢量图里面找图片。

上一篇 下一篇

猜你喜欢

热点阅读