鸿蒙组件和布局
简介
我们把内容呈现在手机屏幕上给用户进行观看的时候,内容的组成就是由一个个的布局和组价元素组成的,所以这里了解一下HarmonyOS开发中常用的组件和布局。
组件
我们把显示在手机或者其他设备上可供用户观看或者操作的元素称之为组件,在harmonyOS中组件的对应对象是 Component,作用是提供内容显示或操作,是界面中所有组件的基类,开发者可以给Component设置事件处理回调(比如点击事件、手势事件)来创建一个可交互的组件。
更多组件内容可以查阅官方文档:常用组件开发指导
一些和Android差别不大的组件,比如Text Image CheckBox RadioButton Switch Scrollview等组件这里就不做过多的介绍了,针对一些和Android差别较大的组件进行介绍。
ListContainer
ListContainer是用来呈现连续、多行数据的组件,包含一系列相同类型的列表项。有些类似于Android里面的ListView,这里就介绍一下数据ListContainer的使用过程,更多的ListContainer自行查阅官方文档进行操作。
- 布局文件添加ListContainer组件
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<ListContainer
ohos:id="$+id:data_list"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="horizontal_center"/>
</DirectionalLayout>
- 编写数据源
private ArrayList<SampleItemEntity> getData(){
ArrayList<SampleItemEntity> initList = new ArrayList<>();
initList.add(new SampleItemEntity("张三","法外狂徒张三"));
initList.add(new SampleItemEntity("李四","默罕默德李四"));
initList.add(new SampleItemEntity("王五","辣鸡米德王五"));
initList.add(new SampleItemEntity("赵四","尼古拉斯赵四"));
initList.add(new SampleItemEntity("刘能","默罕默德刘能"));
return initList;
}
- 编写Provider,继承至BaseItemProvider
package com.example.demo1.provider;
import com.example.demo1.ResourceTable;
import com.example.demo1.entity.SampleItemEntity;
import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.components.*;
import java.util.List;
public class SampleItemProvider extends BaseItemProvider {
private List<SampleItemEntity> dataList;
private AbilitySlice abilitySlice;
public SampleItemProvider(List<SampleItemEntity> dataList, AbilitySlice abilitySlice) {
this.dataList = dataList;
this.abilitySlice = abilitySlice;
}
@Override
public int getCount() {
return dataList == null ? 0 : dataList.size();
}
@Override
public Object getItem(int i) {
if (dataList != null && i >= 0 && i< dataList.size())
return dataList.get(i);
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
final Component cpt;
if (component == null){
cpt = LayoutScatter.getInstance(abilitySlice).parse(ResourceTable.Layout_item_list,null,false);
}else {
cpt = component;
}
SampleItemEntity itemEntity = dataList.get(i);
Text tvItem = (Text) cpt.findComponentById(ResourceTable.Id_item_tv);
tvItem.setText(itemEntity.getItemName());
return cpt;
}
}
- 给ListContainer设置Provider
ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_data_list); listContainer.setOrientation(Component.VERTICAL);
List<SampleItemEntity> dataList = getData();
SampleItemProvider provider = new SampleItemProvider(dataList,this);
listContainer.setItemProvider(provider);
效果如下:
PageSlider
PageSlider是用于页面之间切换的组件,它通过响应滑动事件完成页面间的切换。有点类似于Android里面的ViewPager。用法有点和ListContainer类似,步骤如下:
- xml添加PageSlider组件
<PageSlider
ohos:id="$+id:page_slider"
ohos:height="400vp"
ohos:width="match_parent"/>
- 编写Provider继承至PageSliderProvider
public class DataPagerSlideProvider extends PageSliderProvider {
private List<PageSlideEntity> pageList;
public DataPagerSlideProvider(List<PageSlideEntity> pageList) {
this.pageList = pageList;
}
@Override
public int getCount() {
return pageList == null ?0 : pageList.size();
}
@Override
public Object createPageInContainer(ComponentContainer componentContainer, int i) {
PageSlideEntity itemPage = pageList.get(i);
Text pageTv = new Text(null);
pageTv.setTextAlignment(LayoutAlignment.CENTER);
pageTv.setLayoutConfig(new StackLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT));
pageTv.setText(itemPage.getPageName());
pageTv.setTextSize(20);
ShapeElement shapeElement = new ShapeElement();
shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.getIntColor("#AFEEEE")));
pageTv.setBackground(shapeElement);
componentContainer.addComponent(pageTv);
return pageTv;
}
@Override
public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) {
componentContainer.removeComponent((Component) o);
}
@Override
public boolean isPageMatchToObject(Component component, Object o) {
return true;
}
}
- 添加测试数据
ArrayList<PageSlideEntity> pageList = new ArrayList<>();
pageList.add(new PageSlideEntity("页面一",1));
pageList.add(new PageSlideEntity("页面二",2));
pageList.add(new PageSlideEntity("页面三",3));
return pageList;
- 通过set方法设置provider
PageSlider pageSlider = (PageSlider) findComponentById(ResourceTable.Id_page_slider);
pageSlider.setProvider(new DataPagerSlideProvider(getDataPageSlider()));
DatePicker
顾名思义日期选择器。
属性如下:
- date_order
取值:
0 表示日期以日-月-年的格式显示。
1 表示日期以月-日-年的格式显示。
2 表示日期以年-月-日的格式显示。
3 表示日期以年-日-月的格式显示。
4 表示日期以日-月的格式显示。
5 表示日期以月-日的格式显示。
6 表示日期以年-月的格式显示。
7 表示日期以月-年的格式显示。
8 表示只显示年份。
9 表示只显示月份。
10 表示只显示日期。 - day_fixed 设置日期固定
- month_fixed 设置月份固定
- year_fixed 设置年份固定
- max_date 设置最大日期
- min_date 设置最小日期
- text_size 设置文本大小
更多属性查阅DatePicker官方文档
使用:
1.布局添加DatePicker组件
<DatePicker
ohos:id="$+id:date_pick"
ohos:height="match_content"
ohos:width="300vp">
</DatePicker>
2.java代码获取DatePicker 实例
DatePicker datePicker = (DatePicker) findComponentById(ResourceTable.Id_date_pick);
int day = datePicker.getDayOfMonth();
int month = datePicker.getMonth();
int year = datePicker.getYear();
3.设置当前日期
datePicker.updateDate(2021, 8, 8);
4.设置最小和最大日期
datePicker.setMinDate(1627747200);//毫秒数
datePicker.setMaxDate(1630339200);
5.通过setValueChangedListener获取选择的时间
datePicker.setValueChangedListener(
new DatePicker.ValueChangedListener() {
@Override
public void onValueChanged(DatePicker datePicker, int year, int monthOfYear, int dayOfMonth) {
//Hilog输出 year年 monthOfYear月 dayOfMonth日
}
}
);
效果图:
TimePicker
时间选择器,通过上面的DatePicker我们能获取到年月日的日期选择,想要获取时分秒的时间选择需要通过TimePicker来进行获取。
属性:
- am_pm_order 上午下午排列顺序
取值空间:
0 表示am/pm列靠时间选择器起始端显示。
1 表示am/pm列靠时间选择器结束端显示。
2 表示am/pm列靠时间选择器左侧显示。
3 表示am/pm列靠时间选择器右侧显示。 - mode_24_hour 是否24小时制显示 Boolean类型
- hour 显示小时 int
- minute 显示分钟 int
- second 显示秒钟 int
更多属性查阅TimePicker官方文档
使用:
1.布局添加TimePicker组件
<TimePicker
ohos:id="$+id:time_picker"
ohos:height="match_content"
ohos:width="match_parent" />
2.获取TimePicker实例
TimePicker timePicker = (TimePicker) findComponentById(ResourceTable.Id_time_picker);
int hour = timePicker.getHour();
int minute = timePicker.getMinute();
int second = timePicker.getSecond();
3.通过set方法设置时分秒
timePicker.setHour(19);
timePicker.setMinute(18);
timePicker.setSecond(12);
4.通过setTimeChangedListener事件监听获取选择的时分秒
timePicker.setTimeChangedListener(new TimePicker.TimeChangedListener() {
@Override
public void onTimeChanged(TimePicker timePicker, int hour, int minute, int second) {
//Hilog输入 hour时 minute分 second秒
}
});
效果图:
RoundProgressBar
RoundProgressBar是继承至ProgressBar,ProgressBar我们都知道进度条组件,而RoundProgressBar则是圆形的进度条组件。
属性:
- min 最小值 int
- max 最大值 int
- progress 当前进度 int
- background_instruct_element 背景颜色 Element类型
- progress_width 进度条宽度 float
- progress_color 进度条颜色 color
- progress_element 进度条背景 Element类型
以上属性是RoundProgressBar继承至ProgressBar的部分共有属性(多的还没列举出来);RoundProgressBar也有属于自己的自由属性:
- start_angle 圆形进度条的起始角度 float类型
- max_angle 圆形进度条的最大角度 float类型
使用:
1.xml添加RoundProgressBar组件
<RoundProgressBar
ohos:id="$+id:round_progress_bar"
ohos:height="200vp"
ohos:width="200vp"
ohos:progress_width="10vp"
ohos:progress="20"
ohos:progress_color="#47CC47"/>
2.设置进度
round_progress_bar.setProgressValue(60);
3.设置最大值最小值
round_progress_bar.setMaxValue(400);
round_progress_bar.setMinValue(0);
4.设置进度颜色和进度条底色
<ProgressBar
ohos:progress_element="#FF9900"
ohos:background_instruct_element="#FFFFFF" />
5.设置提示文字以及文字颜色
<ProgressBar
ohos:progress_hint_text="20%"
ohos:progress_hint_text_color="#FFCC99" />
6.设置监听
AbilitySlice implements Slider.ValueChangedListener
@Override
public void onProgressUpdated(Slider slider, int position, boolean isUpdated) {
switch (slider.getId()) {
case ResourceTable.Id_current_value_slider: {
progressBar.setProgressValue(position);
currentText.setText(String.valueOf(currentSlider.getProgress()));
break;
}
case ResourceTable.Id_max_value_slider: {
maxText.setText(String.valueOf(maxSlider.getProgress()));
progressBar.setMaxValue(position);
break;
}
case ResourceTable.Id_speed_value_slider: {
speedText.setText(String.valueOf(speedSlider.getProgress()));
break;
}
default:
break;
}
}
效果图:
ToastDialog
在Android开发中我们会常用到Toast来提示用户一些信息,在HarmonyOS中通过ToastDialog来完成该工作。
使用:
1.在java中使用ToastDialog需要直接实例化一个ToastDialog对象
- setText 设置显示内容
- show 显示
new ToastDialog(getContext())
.setText("提示值")
.show();
2.设置Toast的显示位置,取值区间是LayoutAlignment
.setAlignment(LayoutAlignment.CENTER)
3.自定义Toast的布局
- 通过LayoutScatter.getInstance(this).parse获取自定义的xml布局
- 通过setContentCustomComponent设置自定义布局
- show显示
DirectionalLayout toastLayout = (DirectionalLayout) LayoutScatter.getInstance(this)
.parse(ResourceTable.Layout_layout_toast, null, false);
new ToastDialog(getContext())
.setContentCustomComponent(toastLayout)
.setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT)
.setAlignment(LayoutAlignment.CENTER)
.show();
更多用法查阅ToastDialog官方文档
布局
每一个组件都是单独的元素,而我们把组件根据一定的层级结构进行组合就行了布局,布局在harmonyOS中同样有一个对应对象ComponentContainer;布局作为容器里面可以包含组件Component也可以包含布局ComponentContainer对象,并对布局里面的元素进行布局,当组件没有添加到布局里面时是无法对该组件进行显示操作以及交互操作的,因此一个用户界面至少包含一个布局。在harmonyOS的Java UI中提供了一些标准的布局功能容器,都继承至ComponentContainer,一般用Layout结尾,如:DependentLayout依赖布局、DirectionalLayout定向布局。
更多布局内容可以查阅官方文档:常用布局开发指导
以上就是HarmonyOS部分常用,但是与Android稍有区别的组件介绍了,一些常用的和Android差异不大的组件这里就不做介绍了,可以查阅相关的官方文档进行了解。
布局和组件的关系
布局里面可以包含组件以及布局,从图中就可以看出来他们的关系,在每一个布局上面可以添加组件和布局:
布局配置LayoutConfig
我们把一个个组件放到布局上面去的时候是没有指定显示位置的,如果是定向布局那么所有组件就会沿着水平或者垂直的方向进行显示,如果是依赖布局就都会显示在左上角,那么这时候我们要设置组件和布局的显示位置,就需要用到LayoutConfig这个属性配置,而不同的布局对应的LayoutConfig也不一样,同样还是刚才的布局图:
从图中我们可以看出,如果是DependentLayout作为布局包裹组件,那么对应的布局配置就是:
DependentLayout.LayoutConfig leftConfig = new DependentLayout.LayoutConfig(80,80);
如果是DirectionalLayout作为布局包裹组件,那么对应的布局配置就是:
DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(MATCH_PARENT,MATCH_PARENT);
不同布局下的LayoutConfig对应的属性能力也不一样。
DirectionalLayout属性和布局内组件属性
DirectionalLayout显示方式沿着某个方向进行排列显示,如下图:
DirectionalLayout自有的属性如下图:
DirectionalLayout布局中的组件组件支持的属性如下:
以上这些属性在java文件中用代码进行编写的时候通过set方法进行设置。
DependentLayout属性和布局内组件属性
DependentLayout显示方式是相对局某个位置,或者某个组件进行显示,如下图:
DependentLayout自有属性:
DependentLayout内包含的组件支持的属性(这些属性相对于做Android开发的来说是很熟悉了):
- left_of 将右边缘与另一个子组件的左边缘对齐
- right_of 将左边缘与另一个子组件的右边缘对齐
- start_of 将结束边与另一个子组件的起始边对齐
- end_of 将起始边与另一个子组件的结束边对齐
- above 将下边缘与另一个子组件的上边缘对齐
- below 将上边缘与另一个子组件的下边缘对齐
- align_baseline 将子组件的基线与另一个子组件的基线对齐
- align_left 将左边缘与另一个子组件的左边缘对齐
- align_top 将上边缘与另一个子组件的上边缘对齐
- align_right 将右边缘与另一个子组件的右边缘对齐
- align_bottom 将底边与另一个子组件的底边对齐
- align_start 将起始边与另一个子组件的起始边对齐
- align_end 将结束边与另一个子组件的结束边对齐
- align_parent_left 将左边缘与父组件的左边缘对齐
- align_parent_top 将上边缘与父组件的上边缘对齐
- align_parent_right 将右边缘与父组件的右边缘对齐
- align_parent_bottom 将底边与父组件的底边对齐
- align_parent_start 将起始边与父组件的起始边对齐
- align_parent_end 将结束边与父组件的结束边对齐
- center_in_parent 将子组件保持在父组件的中心
- horizontal_center 将子组件保持在父组件水平方向的中心
- vertical_center 将子组件保持在父组件垂直方向的中心
以上属性在java文件中设置时通过set方法进行设置。
总结
以上组件和布局相对来说和Android差异不大,作为一个Android开发上手速度还是比较快的;官方文档也写得很详细;这里介绍的是相对于Java UI框架作为介绍,如果是想用js进行开发的可以看一下JS UI框架。