About Feature Ability(Java)
介绍
使用Java语言开发,用于Phone设备的Feature Ability模板,使用XML布局。
展示了一个名片详情页的样例工程,主要由一个ScrollView嵌套的两个ListContainer组成。
搭建环境
安装DevEco Studio,详情请参考DevEco Studio下载。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
代码结构解读
功能逻辑代码
- └─businesscardabilityjava
- │ MainAbility.java
- │ MyApplication.java
- │
- ├─datamodel //数据模型
- │ DefaultDoubleLineListItemInfo.java
- │ ItemInfo.java
- │ SingleButtonDoubleLineListItemInfo.java
- │
- ├─itemprovider //子项提供者
- │ ListItemProvider.java
- │
- ├─slice //核心页面
- │ MainAbilitySlice.java
- │
- ├─typefactory //列表类型工厂
- │ ListTypeFactory.java
- │ TypeFactory.java
- │
- └─viewholder //视图持有者
- DefaultDoubleLineList.java
- SingleButtonDoubleLineList.java
- ViewHolder.java
布局及样式代码
- └─resources
- ├─base
- │ ├─element
- │ │ color.json //存储了页面的一些颜色值
- │ │ float.json
- │ │ string.json
- │ │
- │ ├─graphic
- │ │ bottom_tab_background.xml //tab栏背景样式
- │ │ card_background.xml //卡片背景样式
- │ │ divider.xml //分割线样式
- │ │ ic_about.xml
- │ │ ic_actived.xml
- │ │ ic_add.xml
- │ │ ic_back.xml
- │ │ ic_call.xml
- │ │ ic_chat.xml
- │ │ ic_edit.xml //编辑tab按钮icon
- │ │ ic_edit_actived.xml //激活状态编辑tab按钮icon
- │ │ ic_enabled.xml
- │ │ ic_favorite.xml //收藏tab按钮icon
- │ │ ic_favorite_actived.xml //激活状态收藏tab按钮icon
- │ │ ic_header.xml //联系人头像icon
- │ │ ic_more.xml
- │ │ ic_mores.xml //更多tab按钮icon
- │ │ ic_mores_actived.xml //激活状态更多tab按钮icon
- │ │ ic_next.xml
- │ │ ic_normal.xml
- │ │ ic_qrcode.xml
- │ │ ic_video.xml
- │ │
- │ ├─layout
- │ │ ability_main.xml //名片主页面
- │ │ default_doublelinelist.xml //默认双行列表项组件页面
- │ │ singlebutton_doublelinelist.xml //单按钮双行列表项组件页面
- │ │ tab.xml //tab按钮组件页面
- │ │
- │ ├─media
- │ │ icon.png
- │ │ ic_next.png
- │ │ ic_update.png
- │ │ like_icon.jpg
- │ │ profile.png
- │ │ profile_mask.png
- │ │ search.jpg
- │ │ share_icon.jpg
- │ │
- │ └─profile
- └─rawfile
页面布局
1.主页面
本页面的布局包括DependentLayout和DirectionalLayout布局,由ScrollView、ListContainer、Image、Text组件共同来构成,整体分为上中下布局。
上方是应用工具栏,使用了DirectionalLayout嵌套横向布局,布局中用Image组件提供了返回和二维码的功能,2个布局权重是1:1。
中间是联系人的头像和姓名以及联系人其它信息列表,由于列表长度不固定采用了ScrollView组件,内部使用DependentLayout布局嵌套的方式,用DependentLayout包裹ListContainer组件用于列表的展示,其中列表项是由后台通过自定义的2行列表组件动态创建。
底部是联系人可操作的功能区,包括收藏、编辑、更多,采用了DirectionalLayout 嵌套布局,外层DirectionalLayout 用户背景显示,内层DirectionalLayout 用户内容的显示,其中内容的显示是通过自定义tab组件由后台动态创建实现的。
页面在resources\base\layout\ability_main.xml 代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <DependentLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:root_layout"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <DirectionalLayout
- ohos:id="$+id:background"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:align_parent_top="true"
- ohos:background_element="$color:color_background"/>
- <DirectionalLayout
- ohos:id="$+id:appBar"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:align_parent_top="true"
- ohos:end_padding="$float:max_padding_appBar"
- ohos:layout_direction="locale"
- ohos:orientation="horizontal"
- ohos:start_padding="$float:max_padding_start">
- <DirectionalLayout
- ohos:id="$+id:appBar_leftPart"
- ohos:height="$float:height_backButton_touchTarget"
- ohos:width="0vp"
- ohos:alignment="center"
- ohos:orientation="horizontal"
- ohos:weight="1">
- <Image
- ohos:id="$+id:appBar_backButton"
- ohos:height="$float:height_appBar_Buttons"
- ohos:width="$float:width_appBar_buttons"
- ohos:image_src="$graphic:ic_back"/>
- <Text
- ohos:id="$+id:appBar_userName"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alpha="0"
- ohos:left_margin="$float:leftMargin_userName"
- ohos:text="$string:title_contactsDetail"
- ohos:text_size="$float:textSize_userName"/>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:id="$+id:appBar_rightPart"
- ohos:height="match_parent"
- ohos:width="0vp"
- ohos:alignment="vertical_center|right"
- ohos:focusable_in_touch="false"
- ohos:orientation="horizontal"
- ohos:start_margin="$float:start_margin_appBar"
- ohos:weight="1">
- <DirectionalLayout
- ohos:id="$+id:appBar_button3_touchTarget"
- ohos:height="$float:height_touchTarget"
- ohos:width="$float:width_touchTarget"
- ohos:alignment="center">
- <Image
- ohos:id="$+id:appBar_button3"
- ohos:height="$float:height_appBar_Buttons"
- ohos:width="$float:width_appBar_buttons"
- ohos:image_src="$graphic:ic_qrcode"/>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
- <ScrollView
- ohos:id="$+id:contacts_detail_scroll"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:below="$id:appBar"
- ohos:bottom_margin="$float:height_bottom_tab">
- <DependentLayout
- ohos:id="$+id:contacts_detail"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <DependentLayout
- ohos:id="$+id:contacts_detail_upperCard"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:align_parent_top="true"
- ohos:background_element="$graphic:card_background"
- ohos:left_padding="$float:max_padding_start"
- ohos:orientation="vertical"
- ohos:right_padding="$float:max_padding_end"
- ohos:top_margin="$float:topMargin_contactsDetail_upperCard">
- <ListContainer
- ohos:id="$+id:contacts_detail_upperCard_list"
- ohos:height="0vp"
- ohos:width="match_parent"
- ohos:below="$+id:contacts_detail_title"/>
- </DependentLayout>
- <Image
- ohos:id="$+id:contacts_detail_profile"
- ohos:height="$float:height_contacts_profile"
- ohos:width="$float:width_contacts_profile"
- ohos:align_parent_top="true"
- ohos:alpha="1"
- ohos:center_in_parent="true"
- ohos:image_src="$graphic:ic_header"
- ohos:top_margin="$float:topMargin_contacts_profile"/>
- <Text
- ohos:id="$+id:contacts_detail_title"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:align_parent_top="true"
- ohos:text="$string:title_contactsDetail"
- ohos:text_alignment="horizontal_center"
- ohos:text_size="$float:textSize_contactsDetail_title"
- ohos:top_margin="$float:topMargin_contactsDetail_title"/>
- </DependentLayout>
- </ScrollView>
- <DirectionalLayout
- ohos:id="$+id:bottom_tab"
- ohos:height="$float:height_bottom_tab"
- ohos:width="match_parent"
- ohos:align_parent_bottom="true"
- ohos:alignment="vertical_center"
- ohos:background_element="$graphic:bottom_tab_background"
- ohos:left_padding="$float:max_padding_start"
- ohos:right_padding="$float:max_padding_end">
- <DirectionalLayout
- ohos:id="$+id:bottom_tabMenu"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:orientation="horizontal"/>
- </DirectionalLayout>
- </DependentLayout>
2.默认双行列表项组件页面
本页面的布局包括DirectionalLayout布局,由Image、Text组件共同来构成,整体是横向布局,布局如下:
页面在resources\layout\default_doublelinelist.xml ,代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:default_doubleLineList"
- ohos:height="$float:height_doubleLineList"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:doubleLineList"
- ohos:height="$float:height_doubleLineList_text"
- ohos:width="match_parent"
- ohos:bottom_margin="$float:bottomMargin_doubleLineList"
- ohos:orientation="horizontal"
- ohos:top_margin="$float:topMargin_doubleLineList">
- <DirectionalLayout
- ohos:id="$+id:doubleLineList_text"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alignment="vertical_center"
- ohos:orientation="vertical"
- ohos:weight="2">
- <DirectionalLayout
- ohos:id="$+id:doubleLineList_text_layout"
- ohos:height="match_parent"
- ohos:width="match_content"
- ohos:layout_direction="locale">
- <Text
- ohos:id="$+id:doubleLineList_text_primary"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:bottom_margin="$float:bottomMargin_doubleLineList"
- ohos:layout_direction="locale"
- ohos:text_color="$color:color_doubleLineList_primary_text"
- ohos:text_size="$float:textSize_primaryText"/>
- <Text
- ohos:id="$+id:doubleLineList_text_secondary"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:layout_direction="locale"
- ohos:text_color="$color:color_doubleLineList_secondary_text"
- ohos:text_size="$float:textSize_secondaryText"/>
- </DirectionalLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:id="$+id:doubleLineList_right"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alignment="vertical_center|right"
- ohos:orientation="horizontal"
- ohos:right_of="$+id:doubleLineList_text"
- ohos:weight="2">
- <DirectionalLayout
- ohos:id="$+id:doubleLineList_right_touchTarget1"
- ohos:height="$float:height_touchTarget"
- ohos:width="$float:width_touchTarget"
- ohos:alignment="center">
- <Image
- ohos:id="$+id:doubleLineList_right_img1"
- ohos:height="$float:height_doubleLineList_button"
- ohos:width="$float:width_doubleLineList_button"/>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:id="$+id:doubleLineList_right_touchTarget2"
- ohos:height="$float:height_touchTarget"
- ohos:width="$float:width_touchTarget"
- ohos:alignment="center">
- <Image
- ohos:id="$+id:doubleLineList_right_img2"
- ohos:height="$float:height_doubleLineList_button"
- ohos:width="$float:width_doubleLineList_button"/>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:id="$+id:doubleLineList_right_touchTarget3"
- ohos:height="$float:height_touchTarget"
- ohos:width="$float:width_touchTarget"
- ohos:alignment="center">
- <Image
- ohos:id="$+id:doubleLineList_right_img3"
- ohos:height="$float:height_doubleLineList_button"
- ohos:width="$float:width_doubleLineList_button"/>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
- <Image
- ohos:id="$+id:divider"
- ohos:height="$float:height_divider"
- ohos:width="match_parent"
- ohos:image_src="$graphic:divider"/>
- </DirectionalLayout>
3.单按钮双行列表项组件页面
本页面和默认双行列表组件页面基本一致,只是布局中只有一个操作按钮,使用DirectionalLayout布局,由Image、Text组件共同来构成,整体是横向布局,布局如下:
页面在/resources/base/layout/singlebutton_doublelinelist.xml,代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:singleButton_doubleLineList"
- ohos:height="$float:height_doubleLineList"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:id="$+id:singleButtonList"
- ohos:height="$float:height_doubleLineList_text"
- ohos:width="match_parent"
- ohos:bottom_margin="$float:bottomMargin_doubleLineList"
- ohos:orientation="horizontal"
- ohos:top_margin="$float:topMargin_doubleLineList">
- <DirectionalLayout
- ohos:id="$+id:singleButtonList_text"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alignment="vertical_center"
- ohos:orientation="vertical"
- ohos:weight="2">
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_content"
- ohos:layout_direction="locale">
- <Text
- ohos:id="$+id:singleButtonList_text_primary"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:bottom_margin="$float:bottomMargin_doubleLineList"
- ohos:layout_direction="locale"
- ohos:text_color="$color:color_doubleLineList_primary_text"
- ohos:text_size="$float:textSize_primaryText"/>
- <Text
- ohos:id="$+id:singleButtonList_text_secondary"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_direction="locale"
- ohos:text_color="$color:color_doubleLineList_secondary_text"
- ohos:text_size="$float:textSize_secondaryText"/>
- </DirectionalLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:id="$+id:singleButtonList_right"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:alignment="vertical_center|right"
- ohos:layout_direction="locale"
- ohos:weight="1">
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_direction="locale">
- <DirectionalLayout
- ohos:id="$+id:singleButtonList_right_touchTarget"
- ohos:height="$float:height_touchTarget"
- ohos:width="$float:width_touchTarget"
- ohos:alignment="center">
- <Image
- ohos:id="$+id:singleButtonList_right_img"
- ohos:height="$float:height_doubleLineList_switch"
- ohos:width="$float:width_doubleLineList_switch"/>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
- <Image
- ohos:id="$+id:divider"
- ohos:height="$float:height_divider"
- ohos:width="match_parent"
- ohos:image_src="$graphic:divider"/>
- </DirectionalLayout>
4.Tab 组件页面
自定义的tab组件,用于动态渲染tab栏,使用DirectionalLayout布局,由Image、Text组件共同来构成,整体是垂直布局。
页面在resources/base/layout/tab.xml,代码如下:
- <?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:height_tab"
- ohos:width="$float:width_tab"
- />
- <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:color_tabText_normal"
- ohos:text_size="$float:textSize_tab"
- />
- </DirectionalLayout>
说明:
布局文件中使用到了一些样式和图片,在resources\base\graphic下有做定义,详情可以参考完整代码。
相关权限
不需要额外申请权限
tab 按钮切换的业务逻辑
将动态添加的tab按钮存储到List中并进行遍历,设置当前点击的tab按钮为激活样式,其它tab按钮设置为普通效果。
后台代码在 /slice/MainAbilitySlice.java 关键代码如下:
- tab.setClickedListener(component -> {
- Text focusTab = (Text) component.findComponentById(ResourceTable.Id_bottom_tab_button_text);
- //Set active tab image
- setActiveTabImage(tabList, focusTab.getText());
- });
- /**
- *
- * @param tabList tab按钮列表
- * @param focusText 需要激活的tab名称
- */
- private void setActiveTabImage(List<DirectionalLayout> tabList, String focusText) {
- Element tabNormal = null;
- Element tabActived = null;
- for (DirectionalLayout btn : tabList) {
- Text text = (Text) btn.findComponentById(ResourceTable.Id_bottom_tab_button_text);
- if ("收藏".equals(text.getText())) {
- tabNormal = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_ic_favorite);
- tabActived = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_ic_favorite_actived);
- if ("收藏".equals(focusText)) {
- ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image)).setImageElement(tabActived);
- } else {
- ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image)).setImageElement(tabNormal);
- }
- }
- if ("编辑".equals(text.getText())) {
- tabNormal = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_ic_edit);
- tabActived = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_ic_edit_actived);
- if ("编辑".equals(focusText)) {
- ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image)).setImageElement(tabActived);
- } else {
- ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image)).setImageElement(tabNormal);
- }
- }
- if ("更多".equals(text.getText())) {
- tabNormal = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_ic_mores);
- tabActived = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_ic_mores_actived);
- if ("更多".equals(focusText)) {
- ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image)).setImageElement(tabActived);
- } else {
- ((Image) btn.findComponentById(ResourceTable.Id_bottom_tab_button_image)).setImageElement(tabNormal);
- }
- }
- }
- }
滑动效果实现的业务逻辑
向上/下滑动滚动条,显示和隐藏顶部应用栏中联系人姓名(通过设置文字透明度实现)和更改背景的效果(更改背景色)
后台代码在 /slice/MainAbilitySlice.java 关键代码如下:
- private void initScrollView() {
- ScrollView scrollView = (ScrollView) findComponentById(ResourceTable.Id_contacts_detail_scroll);
- int profileSizePx = AttrHelper.vp2px(COLOR_CHANGE_RANGE, this);
- if (scrollView != null) {
- scrollView.setReboundEffectParams(OVERSCROLL_PERCENT, OVERSCROLL_RATE, REMAIN_VISIBLE_PERCENT);
- scrollView.setReboundEffect(true);
- //获取appbar显示的contact name
- Text userName = (Text) findComponentById(ResourceTable.Id_appBar_userName);
- DirectionalLayout backGround = (DirectionalLayout) findComponentById(ResourceTable.Id_background);
- ShapeElement shapeElement = new ShapeElement();
- shapeElement.setShape(ShapeElement.RECTANGLE);
- // Set Scrolled listener
- scrollView.getComponentTreeObserver().addScrolledListener(() -> {
- float curY = scrollView.getScrollValue(Component.AXIS_Y);
- HiLog.info(LABEL, "curY:" + curY);
- int colorChange = (int) ((BACKGROUND_COLOR - ORIGINAL_BACKGROUND_COLOR) * curY / profileSizePx);
- HiLog.info(LABEL, "colorChange:" + colorChange);
- HiLog.info(LABEL, "colorValue:" + (ORIGINAL_BACKGROUND_COLOR + colorChange));
- //设置颜色的方法
- //1.设置ability_main.xml组件中的背景色,如:240/160/110,这是一个橙色
- //2.手动加上刚才的值,如240/160/110
- shapeElement.setRgbColor(new RgbColor(ORIGINAL_BACKGROUND_COLOR + colorChange+240,
- ORIGINAL_BACKGROUND_COLOR + colorChange+160, ORIGINAL_BACKGROUND_COLOR + colorChange+110));
- backGround.setBackground(shapeElement);
- userName.setAlpha(1 * curY / profileSizePx);
- });
- }
- }
效果展示:
向下滚动
向上滚动
点击tab图标
文章相关附件可以点击下面的原文链接前往下载
https://harmonyos.51cto.com/posts/4776