HarmonyOS官方模板学习 之 Category Ability(Java)

Posted 公众号码个蛋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS官方模板学习 之 Category Ability(Java)相关的知识,希望对你有一定的参考价值。

Category Ability(Java)


介绍

使用Java语言开发,用于Phone设备的Feature Ability模板,使用XML布局,显示分类页效果。

搭建环境

安装DevEco Studio,详情请参考DevEco Studio下载。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

代码结构解读

注意:'#'代表注释
功能逻辑代码

├─java
│  └─com
│      └─buty
│          └─categoryabilityjava
│              │  MainAbility.java
│              │  MyApplication.java
│              │
│              ├─data
│              │      CategoryData.java #用来构造分类数据
│              │
│              ├─model
│              │      CategoryList.java #分类列表模型
│              │      Item.java #子项模型
│              │      ItemChild.java #小子项模型
│              │      ItemList.java #子项列表模型
│              │
│              ├─provider
│              │      CategoryListProvider.java #继承自BaseItemProvider为ListContainer提供数据
│              │
│              ├─slice
│              │      MainAbilitySlice.java #主页片
│              │
│              ├─utils
│              │      ElementUtil.java #获取element颜色值,
│              │      LogUtils.java #日志工具类
│              │      Toast.java #Toast工具类
│              │
│              └─view
│                      GridAdapter.java #grid适配器,适配不同的gridview
│                      GridView.java #自定义组件,类似grid,继承自TableLayout并且实现Component.LayoutRefreshedListener

布局及样式代码

└─resources
    ├─base
    │  ├─element
    │  │      color.json
    │  │      float.json
    │  │      string.json
    │  │
    │  ├─graphic
    │  │      background_ability_main.xml
    │  │      background_item_grid_per.xml
    │  │      background_search_bar.xml
    │  │
    │  ├─layout
    │  │      ability_main.xml  #主页面
    │  │      category_list_per.xml #每个分类组件
    │  │      item_child_per.xml #分类下面的子类别
    │  │      item_child_per_grid_per.xml #子类别下的网格项组件
    │  │      item_grid_per.xml #分类下面的网格项
    │  │      search_bar.xml #search组件
    │  │      tab.xml #单个tab组件
    │  │      title_bar.xml #标题组件
    │  │
    │  ├─media
    │  │      addIcon.png
    │  │      icon.png
    │  │      icon_actived.png
    │  │      icon_normal.png
    │  │      rightIcon.png
    │  │      searchIcon.png
    │  │
    │  └─profile
    ├─en
    │  └─element
    │          string.json
    │
    ├─rawfile
    └─zh
        └─element
                string.json


效果展示

我们先看一下运行起来的效果

相关权限

不需要额外申请权限

页面布局

1.ability_main.xml #主页面

页面的布局包括DependentLayout和DirectionalLayout布局。
包括ListContainer、ScrollView、自定义的GridView 等组件

还使用了include标签来导入预设的组件,导入了search组件和标题组件

2.category_list_per.xml #每个分类组件

分类组件比较简单,DirectionalLayout包含一个Text

<?xml version="1.0" encoding="utf-8"?>


<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:bottom_margin="$float:defaultMargin"
    ohos:orientation="vertical"
    ohos:top_margin="$float:defaultMargin">


    <Text
        ohos:id="$+id:categoryListPerText"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:bottom_padding="$float:componentPadding"
        ohos:end_padding="$float:defaultPadding"
        ohos:multiple_lines="true"
        ohos:text_alignment="vertical_center|left"
        ohos:text_size="16vp"
        ohos:top_padding="$float:componentPadding"/>


3.item_child_per.xml #分类下面的子类别

包含了一个自定义的GridView,我们可以学习一下如何自定义组件


4.item_child_per_grid_per.xml #子类别下的网格项组件

比较简单

<?xml version="1.0" encoding="utf-8"?>


<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="60vp"
    ohos:alpha="0"
    ohos:top_margin="$float:defaultMargin">


    <Image
        ohos:height="60vp"
        ohos:width="match_parent"
        ohos:background_element="$graphic:background_item_grid_per"/>


    <Text
        ohos:id="$+id:itemChildPerGridPerText"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:bottom_padding="$float:componentPadding"
        ohos:multiple_lines="true"
        ohos:text_alignment="center"
        ohos:text_size="16vp"
        ohos:top_padding="$float:componentPadding"/>
</DirectionalLayout>


5.item_grid_per.xml #分类下面的网格项

<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="108vp"
    ohos:background_element="$graphic:background_item_grid_per">


    <Image
        ohos:id="$+id:itemGridPerImage"
        ohos:height="65vp"
        ohos:width="match_parent"/>


    <Text
        ohos:id="$+id:itemGridPerText"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:align_parent_start="true"
        ohos:align_parent_top="true"
        ohos:bottom_padding="$float:componentPadding"
        ohos:end_padding="$float:defaultPadding"
        ohos:multiple_lines="true"
        ohos:start_padding="$float:defaultPadding"
        ohos:text_alignment="vertical_center"
        ohos:text_size="16vp"
        ohos:top_padding="$float:componentPadding"/>
</DependentLayout>


6.search_bar.xml #search组件

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:background_element="$color:colorSubBackground">


    <DependentLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:background_element="$graphic:background_search_bar"
        ohos:bottom_margin="$float:componentPadding"
        ohos:end_margin="$float:defaultMargin"
        ohos:start_margin="$float:defaultMargin"
        ohos:top_margin="$float:componentPadding">


        <Image
            ohos:id="$+id:searchImage"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:image_src="$media:searchIcon"
            ohos:start_margin="$float:defaultMargin"
            ohos:vertical_center="true"/>


        <TextField
            ohos:id="$+id:searchTextField"
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:bottom_padding="$float:componentPadding"
            ohos:element_cursor_bubble="#00000000"
            ohos:end_of="$id:searchImage"
            ohos:end_padding="$float:defaultPadding"
            ohos:hint="$string:search"
            ohos:multiple_lines="false"
            ohos:start_padding="$float:defaultPadding"
            ohos:text_alignment="vertical_center"
            ohos:text_size="16fp"
            ohos:top_padding="$float:componentPadding"
            ohos:vertical_center="true"/>
    </DependentLayout>


</DirectionalLayout>


7.tab.xml #单个tab组件

<?xml version="1.0" encoding="utf-8"?>


<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:id="$+id:tab"
    ohos:height="match_content"
    ohos:width="0vp"
    ohos:alignment="center"
    ohos:orientation="vertical"
    ohos:weight="1">


    <Image
        ohos:id="$+id:bottom_tab_button_image"
        ohos:height="$float:heightTab"
        ohos:width="$float:widthTab"/>


    <Text
        ohos:id="$+id:bottom_tab_button_text"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text_alignment="top|horizontal_center"
        ohos:text_color="$color:colorTabTextNormal"
        ohos:text_size="$float:textSizeTab"
        ohos:top_margin="2vp"/>


</DirectionalLayout>

8.title_bar.xml #标题组件

两个Text 加上一个Image

<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="$float:defaultHeight"
    ohos:width="match_parent"
    ohos:background_element="$color:colorSubBackground">


    <Text
        ohos:id="$+id:title_text"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:align_parent_bottom="true"
        ohos:bottom_padding="$float:defaultPadding"
        ohos:end_padding="$float:defaultPadding"
        ohos:multiple_lines="true"
        ohos:start_padding="$float:defaultPadding"
        ohos:text="$string:entry_MainAbility"
        ohos:text_color="$color:appbar_title_color"
        ohos:text_size="$float:appbar_title_text_size"/>


    <Text
        ohos:id="$+id:describe_text"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:align_parent_bottom="true"
        ohos:bottom_padding="$float:defaultPadding"
        ohos:end_of="$id:title_text"
        ohos:multiple_lines="true"
        ohos:text="$string:describe"
        ohos:text_color="$color:appbar_subtitle_color"
        ohos:text_size="$float:appbar_text_size"/>


    <Image
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:align_parent_bottom="true"
        ohos:align_parent_end="true"
        ohos:bottom_padding="$float:defaultPadding"
        ohos:end_padding="$float:defaultPadding"
        ohos:image_src="$media:addIcon"/>


</DependentLayout>


业务逻辑

1.CategoryListProvider

部分关键代码

@Override
    public Component getComponent(int index, Component component, ComponentContainer componentContainer) {




        Component itemComponent = component;
        CategoryListViewHolder viewHolder;


        //获取布局组件
        if (itemComponent == null) {
            itemComponent =
                    LayoutScatter.getInstance(context)
                            .parse(ResourceTable.Layout_category_list_per, componentContainer, false);
        }


        //初始化ViewHolder
        viewHolder = new CategoryListViewHolder();
        viewHolder.text = (Text) itemComponent.findComponentById(ResourceTable.Id_categoryListPerText);
        viewHolder.text.setText(getItem(index));


        //对齐方式
        if (TextTool.isLayoutRightToLeft(Locale.getDefault())) {
            viewHolder.text.setTextAlignment(TextAlignment.VERTICAL_CENTER | TextAlignment.RIGHT);
        } else {
            viewHolder.text.setTextAlignment(TextAlignment.VERTICAL_CENTER | TextAlignment.LEFT);
        }
        //获取color.json中的颜色值,设置Text组件的颜色
        if (selectIndex == index) {
            viewHolder.text.setTextColor(new Color(ElementUtil.getColor(context, ResourceTable.Color_primary_color)));
        } else {
            viewHolder.text.setTextColor(new Color(ElementUtil.getColor(context, ResourceTable.Color_primary_default)));
        }


        return itemComponent;
    }


    /**
     * 定义视图持有者
     */
    private static class CategoryListViewHolder {
        Text text;
    }

2.ElementUtil

学习如何获取element color.json的颜色值,用java代码设置给组件

package com.buty.categoryabilityjava.utils;


import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;


import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * The ElementUtil
 */
public class ElementUtil {
    /**
     * The getColor
     *
     * @param context    context
     * @param resColorId resColorId
     * @return color
     */
    public static int getColor(Context context, int resColorId) {
        try {
            //
            String strColor = context.getResourceManager().getElement(resColorId).getString();


            if (strColor.length() == 7) {
                //返回7位颜色值
                return context.getResourceManager().getElement(resColorId).getColor();
            } else if (strColor.length() == 9) {
                //返回9位颜色值
                return Color.getIntColor(strColor);
            } else {
                return 0x000000;
            }
        } catch (WrongTypeException | NotExistException | IOException e) {
            Logger.getLogger(ElementUtil.class.getName()).log(Level.SEVERE, e.getMessage());
        }
        return 0x000000;
    }
}

3.GridAdapter

package com.buty.categoryabilityjava.view;


import com.buty.categoryabilityjava.utils.LogUtils;


import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.app.Context;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;


/**
 * The GridAdapter, adapter of the gridView
 */
public class GridAdapter {
    private final List<Component> componentList = new ArrayList<>();


    /**
     * The GridAdapter, adapter of the gridView
     *
     * @param context context
     * @param xmlId   xmlId, the xml layout of each item of gridView
     * @param data    data, the number of key-value also the number of item
     * @param from    from, the collection for the key in de data
     * @param to      to, the value from the data to the component target
     */
    public GridAdapter(Context context, int xmlId, List<Map<String, Object>> data, String[] from, int[] to) {
        for (Map<String, Object> datum : data) {
            // get component for the xml
            Component layoutComponent = LayoutScatter.getInstance(context).parse(xmlId, null, false);


            // create each itemComponent for the args:data、from、to
            IntStream.range(0, to.length)
                    .forEach(
                            index -> {
                                Component itemComponent = layoutComponent.findComponentById(to[index]);
                                if (itemComponent instanceof Image) {
                                    Image image = (Image) itemComponent;
                                    if (datum.get(from[index]) instanceof int[]) {
                                        try {
                                            image.setPixelMap(((int[]) datum.get(from[index]))[index]);
                                        } catch (IndexOutOfBoundsException e) {
                                            LogUtils.error("GridAdapter", "IndexOutOfBoundsException");
                                        }
                                    }
                                } else {
                                    if (itemComponent instanceof Text) {
                                        Text text = (Text) itemComponent;
                                        if (datum.get(from[index]) instanceof String[]) {
                                            try {
                                                text.setText(((String[]) datum.get(from[index]))[index]);
                                            } catch (IndexOutOfBoundsException e) {
                                                LogUtils.error("GridAdapter", "IndexOutOfBoundsException");
                                                text.setText("null");
                                            }
                                        } else if (datum.get(from[index]) instanceof int[]) {
                                            try {
                                                text.setText(((int[]) datum.get(from[index]))[index]);
                                            } catch (IndexOutOfBoundsException e) {
                                                LogUtils.error("GridAdapter", "IndexOutOfBoundsException");
                                                text.setText("null");
                                            }
                                        } else {
                                            text.setText("null");
                                        }
                                    }
                                }
                            });


            componentList.add(layoutComponent);
        }
    }


    /**
     * The getComponentList
     *
     * @return componentList
     */
    List<Component> getComponentList() {
        return componentList;
    }
}


4.GridView

package com.buty.categoryabilityjava.view;


import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.TableLayout;
import ohos.agp.utils.TextTool;
import ohos.app.Context;


import java.util.Locale;


/**
 * The GridView, a custom component like grid
 */
public class GridView extends TableLayout implements Component.LayoutRefreshedListener {
    private OnItemClickListener onItemClickListener;
    private OnRefreshedListener onRefreshedListener;


    private GridAdapter adapter;


    // custom Attr
    private int columnMargin;
    private int rowMargin;


    //add custom attr
    private int rowPadding;


    private boolean isOnRefreshed = false;


    public GridView(Context context) {
        super(context);
        setLayoutRefreshedListener(this);
    }


    public GridView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        setLayoutRefreshedListener(this);
        //获取自定义属性的预设值
        columnMargin =
                attrSet.getAttr("columnMargin").isPresent()
                        ? attrSet.getAttr("columnMargin").get().getDimensionValue()
                        : 0;


        rowMargin =
                attrSet.getAttr("rowMargin").isPresent() ? attrSet.getAttr("rowMargin").get().getDimensionValue() : 0;
    }


    public GridView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setLayoutRefreshedListener(this);
        columnMargin =
                attrSet.getAttr("columnMargin").isPresent()
                        ? attrSet.getAttr("columnMargin").get().getDimensionValue()
                        : 0;
        rowMargin =
                attrSet.getAttr("rowMargin").isPresent() ? attrSet.getAttr("rowMargin").get().getDimensionValue() : 0;
    }


    @Override
    public void onRefreshed(Component component) {
        if (isOnRefreshed) {
            return;
        }
        isOnRefreshed = true;


        layoutAdapter();
        if (onRefreshedListener != null) {
            onRefreshedListener.onRefreshed(component);
        }
    }


    /**
     * The setAdapter
     *
     * @param adapter adapter
     */
    public void setAdapter(GridAdapter adapter) {
        this.adapter = adapter;
        isOnRefreshed = false;
    }


    private void layoutAdapter() {
        removeAllComponents();


        for (int i = 0; i < adapter.getComponentList().size(); i++) {
            Component componentItem = adapter.getComponentList().get(i);


            ComponentContainer.LayoutConfig configComponent = componentItem.getLayoutConfig();
            int totalWidth = getWidth() - getPaddingStart() - getPaddingEnd();
            int columnMarginTmp = columnMargin;
            if (columnMargin == 0) {
                columnMarginTmp = (totalWidth - componentItem.getWidth() * getColumnCount()) / (getColumnCount() - 1);
            } else {
                configComponent.width = (totalWidth - columnMargin * (getColumnCount() - 1)) / getColumnCount();
                componentItem.setLayoutConfig(configComponent);
            }


            if (i % getColumnCount() != 0) {
                if (TextTool.isLayoutRightToLeft(Locale.getDefault())) {
                    componentItem.setMarginRight(columnMarginTmp);
                } else {
                    componentItem.setMarginLeft(columnMarginTmp);
                }
            }


            if (i / getColumnCount() != 0) {
                componentItem.setMarginTop(rowMargin);
            }


            final int index = i;


            componentItem.setClickedListener(
                    component -> {
                        if (onItemClickListener != null) {
                            onItemClickListener.onclick(component, index);
                        }
                    });


            addComponent(componentItem);
        }
    }


    /**
     * The setOnItemClickListener
     *
     * @param onItemClickListener onItemClickListener
     */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }


    /**
     * The setOnRefreshedListener
     *
     * @param onRefreshedListener onRefreshedListener
     */
    public void setOnRefreshedListener(OnRefreshedListener onRefreshedListener) {
        this.onRefreshedListener = onRefreshedListener;
    }


    /**
     * The OnItemClickListener
     */
    public static class OnItemClickListener {
        /**
         * The onclick
         *
         * @param component component
         * @param index     index
         */
        public void onclick(Component component, int index) {
        }
    }


    /**
     * The onRefreshedListener
     */
    public static class OnRefreshedListener {
        /**
         * The onRefreshed
         *
         * @param component component
         */
        public void onRefreshed(Component component) {
        }
    }
}


3.MainAbilitySlice

package com.buty.categoryabilityjava.slice;


import com.buty.categoryabilityjava.MainAbility;
import com.buty.categoryabilityjava.ResourceTable;
import com.buty.categoryabilityjava.data.CategoryData;
import com.buty.categoryabilityjava.model.Item;
import com.buty.categoryabilityjava.model.ItemChild;
import com.buty.categoryabilityjava.provider.CategoryListProvider;
import com.buty.categoryabilityjava.utils.ElementUtil;
import com.buty.categoryabilityjava.utils.Toast;
import com.buty.categoryabilityjava.view.GridAdapter;
import com.buty.categoryabilityjava.view.GridView;


import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.ScrollView;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.utils.TextAlignment;
import ohos.agp.utils.TextTool;
import ohos.global.configuration.Configuration;
import ohos.multimodalinput.event.KeyEvent;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.IntStream;


/**
 * The MainAbilitySlice, the first page of app
 */
public class MainAbilitySlice extends AbilitySlice {
    // Button number on the bottom
    private static final int BOTTOM_TAB_BUTTON_NUM = 4;


    private CategoryData categoryData;


    private CategoryListProvider categoryListProvider;
    private TextField searchTextField;
    private ListContainer categoryList;
    private ScrollView itemListScroll;
    private GridView itemLayoutGrid;
    private DirectionalLayout itemChildLayout;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_ability_main);
        this.getWindow().setStatusBarColor(ElementUtil.getColor(this, ResourceTable.Color_colorSubBackground));
        this.getWindow().setNavigationBarColor(ElementUtil.getColor(this, ResourceTable.Color_colorSubBackground));


        categoryData = new CategoryData(this);


        initView();
        initListener();
        initBottomTab();
    }


    /**
     * The initView, get component from xml
     */
    private void initView() {
        // Init component
        searchTextField = (TextField) findComponentById(ResourceTable.Id_searchTextField);


        //ListContainer组件
        categoryList = (ListContainer) findComponentById(ResourceTable.Id_categoryList);
        //ScrollView组件
        itemListScroll = (ScrollView) findComponentById(ResourceTable.Id_itemListScroll);
        //子项布局grid
        itemLayoutGrid = (GridView) findComponentById(ResourceTable.Id_itemLayoutGrid);
        //获取子项布局组件
        itemChildLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_itemChildLayout);


        //设置样式
        searchTextField.setTextAlignment(TextAlignment.START | TextAlignment.VERTICAL_CENTER);
        if (TextTool.isLayoutRightToLeft(Locale.getDefault())) {
            searchTextField.setLayoutDirection(Component.LayoutDirection.RTL);
        } else {
            searchTextField.setLayoutDirection(Component.LayoutDirection.LTR);
        }
    }


    private void initLocaleChange() {
        ((MainAbility) getAbility())


                .setLocaleChangeListener(
                        //区域更改监听器
                        new MainAbility.LocaleChangeListener() {
                            @Override
                            public void onLocaleChange(Configuration configuration) {
                                super.onLocaleChange(configuration);
                                if (!configuration
                                        .getFirstLocale()
                                        .getLanguage()
                                        .equals(Locale.getDefault().getLanguage())) {
                                    categoryData = new CategoryData(MainAbilitySlice.this);
                                    int index = categoryListProvider.getSelectIndex();
                                    categoryListProvider =
                                            new CategoryListProvider(
                                                    categoryData.getCategoryList().getListText(),
                                                    MainAbilitySlice.this);
                                    categoryList.setItemProvider(categoryListProvider);
                                    categoryListProvider.setSelectIndex(index);


                                    refreshItemGrid(
                                            categoryData
                                                    .getItemList(
                                                            categoryData.getCategoryList().getListText().get(index))
                                                    .getListItem());
                                    initItemChild(
                                            categoryData
                                                    .getItemList(
                                                            categoryData.getCategoryList().getListText().get(index))
                                                    .getListItemChild());


                                    categoryListProvider.notifyDataChanged();
                                }
                            }
                        });
    }


    /**
     * The initListener, set listener of component
     */
    private void initListener() {
        initLocaleChange();


        searchTextField.setKeyEventListener(
                (component, keyEvent) -> {
                    if (keyEvent.isKeyDown() && keyEvent.getKeyCode() == KeyEvent.KEY_ENTER) {
                        Toast.makeToast(
                                MainAbilitySlice.this,
                                getString(ResourceTable.String_you_search) + searchTextField.getText(),
                                Toast.TOAST_SHORT)
                                .show();
                    }
                    return false;
                });


        // Init categoryList
        categoryList.setItemClickedListener(
                (listContainer, component, index, l1) -> {
                    if (categoryListProvider.getSelectIndex() == index) {
                        return;
                    }


                    String categoryName = categoryData.getCategoryList().getListText().get(index);
                    categoryListProvider.setSelectIndex(index);


                    refreshItemGrid(categoryData.getItemList(categoryName).getListItem());


                    initItemChild(categoryData.getItemList(categoryName).getListItemChild());


                    categoryListProvider.notifyDataChanged();


                    itemListScroll.fluentScrollYTo(0);
                });


        categoryListProvider = new CategoryListProvider(categoryData.getCategoryList().getListText(), this);
        categoryList.setItemProvider(categoryListProvider);


        // Init itemGrid
        itemLayoutGrid.setOnItemClickListener(
                new GridView.OnItemClickListener() {
                    @Override
                    public void onclick(Component component, int index) {
                        String text = ((Text) component.findComponentById(ResourceTable.Id_itemGridPerText)).getText();
                        Toast.makeToast(
                                MainAbilitySlice.this,
                                getString(ResourceTable.String_you_clicked) + text,
                                Toast.TOAST_SHORT)
                                .show();
                    }
                });


        refreshItemGrid(categoryData.getItemList(categoryData.getCategoryList().getListText().get(0)).getListItem());
        initItemChild(categoryData.getItemList(categoryData.getCategoryList().getListText().get(0)).getListItemChild());
    }


    /**
     * The refreshItemGrid, refresh the itemGrid each time when select a category
     *
     * @param itemList itemList, the bean of itemGrid
     */
    private void refreshItemGrid(List<Item> itemList) {
        List<Map<String, Object>> adapterData = new ArrayList<>();


        // Create adapterData
        IntStream.range(0, itemList.size()).forEach(index -> {
            Map<String, Object> showItem = new HashMap<>();
            String[] itemText = new String[]{itemList.get(index).getItemText()};
            showItem.put("itemGridPerText", itemText);
            adapterData.add(showItem);
        });


        // Create gridAdapter
        GridAdapter gridAdapter =
                new GridAdapter(
                        this,
                        ResourceTable.Layout_item_grid_per,
                        adapterData,
                        new String[]{"itemGridPerText"},
                        new int[]{ResourceTable.Id_itemGridPerText});


        // Set adapter
        itemLayoutGrid.setAdapter(gridAdapter);
    }


    /**
     * The initItemChild, init the itemChild each time when select a category
     *
     * @param itemChildList itemChildList, the bean of itemChild
     */
    private void initItemChild(List<ItemChild> itemChildList) {


        //清空组件
        itemChildLayout.removeAllComponents();
        itemChildList.add(new ItemChild());
        // Create itemChild
        for (ItemChild itemChild : itemChildList) {
            Component childComponent =
                    LayoutScatter.getInstance(this).parse(ResourceTable.Layout_item_child_per, null, false);


            Text text = (Text) childComponent.findComponentById(ResourceTable.Id_itemChildPerText);
            Text more = (Text) childComponent.findComponentById(ResourceTable.Id_itemChildPerMore);
            GridView gridView = (GridView) childComponent.findComponentById(ResourceTable.Id_itemChildPerGrid);


            gridView.setOnItemClickListener(
                    new GridView.OnItemClickListener() {
                        @Override
                        public void onclick(Component component, int index) {
                            String text =
                                    ((Text) component.findComponentById(ResourceTable.Id_itemChildPerGridPerText))
                                            .getText();
                            Toast.makeToast(
                                    MainAbilitySlice.this,
                                    getString(ResourceTable.String_you_clicked) + text,
                                    Toast.TOAST_SHORT)
                                    .show();
                        }
                    });


            gridView.setOnRefreshedListener(
                    new GridView.OnRefreshedListener() {
                        @Override
                        public void onRefreshed(Component component) {
                            text.setText(itemChild.getItemChildText());
                            more.setVisibility(Component.VISIBLE);
                        }
                    });


            List<Map<String, Object>> adapterData = new ArrayList<>();


            // Create adapterData
            for (int j = 0; j < itemChild.getListItem().size(); j++) {
                Map<String, Object> showitem = new HashMap<>();
                String[] itemText = new String[]{itemChild.getListItem().get(j).getItemText()};
                showitem.put("itemChildPerGridPerText", itemText);
                adapterData.add(showitem);
            }


            // Create gridAdapter
            GridAdapter gridAdapter =
                    new GridAdapter(
                            this,
                            ResourceTable.Layout_item_child_per_grid_per,
                            adapterData,
                            new String[]{"itemChildPerGridPerText"},
                            new int[]{ResourceTable.Id_itemChildPerGridPerText});


            // set adapter
            gridView.setAdapter(gridAdapter);


            itemChildLayout.addComponent(childComponent);
        }
    }


    /**
     * The initBottomTab, init the bottomTab
     */
    private void initBottomTab() {
        DirectionalLayout bottomTab = (DirectionalLayout) findComponentById(ResourceTable.Id_bottom_tabMenu);
        List<DirectionalLayout> tabList = new ArrayList<>();
        //遍历创建tab 按钮
        IntStream.range(0, BOTTOM_TAB_BUTTON_NUM).forEach(count -> {


            // Use LayoutScatter to convert xml file into Component instance
            DirectionalLayout tab =
                    (DirectionalLayout)
                            LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_tab, bottomTab, false);


            //按钮icon
            Image buttonImage = (Image) tab.findComponentById(ResourceTable.Id_bottom_tab_button_image);
            if (buttonImage != null) {
                buttonImage.setScaleMode(Image.ScaleMode.STRETCH);
                if (count == BOTTOM_TAB_BUTTON_NUM - 1) {
                    buttonImage.setPixelMap(ResourceTable.Media_icon_actived);
                } else {
                    buttonImage.setPixelMap(ResourceTable.Media_icon_normal);
                }
            }
            //按钮文本
            Text buttonText = (Text) tab.findComponentById(ResourceTable.Id_bottom_tab_button_text);
            if (buttonText != null) {
                //string.json 获取value的方法
                buttonText.setText(getString(ResourceTable.String_tab));
            }
            //点击事件
            tab.setClickedListener(
                    component -> {
                        // Deselect all tabs in tab menu
                        for (DirectionalLayout btn : tabList) {
                            ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image))
                                    .setPixelMap(ResourceTable.Media_icon_normal);
                        }


                        // Set seleted state on the clicked tab
                        ((Image) component.findComponentById(ResourceTable.Id_bottom_tab_button_image))
                                .setPixelMap(ResourceTable.Media_icon_actived);
                    });
            //初始化好的tab,添加道tab 列表中
            tabList.add(tab);
            //添加道主页片的布局中
            bottomTab.addComponent(tab);
        });
    }


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


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

去掉页面顶部标题的方法

config.json文件中在abilities后面增加metaData代码:

 ,"metaData":{
      "customizeData": [
        {
          "name": "hwc-theme",
          "value": "androidhwext:style/Theme.Emui.Light.NoTitleBar",
          "extra": ""
        }
      ]
    }

--完--

关注「HarmonyOS应用开发者」,一起学习成长

后台回复"教程" 获得最新鸿蒙开发者教程,助你快速上手鸿蒙开发!

以上是关于HarmonyOS官方模板学习 之 Category Ability(Java)的主要内容,如果未能解决你的问题,请参考以下文章

#过年不停更#HarmonyOS-ETS之紧急拨号

HarmonyOS-Android混合开发之APK混入

HarmonyOS之DevEco2中真实手机调试应用

从HarmonyOS过渡到OpenHarmony应用开发指南&埋坑

HarmonyOS 实战——万字分析并学习 JsFACard 项目

鸿蒙HarMonyOS的UI组件学习五之面试宝典