布局概述:
每种布局都根据自身特点提供LayoutConfig供子Component设定布局属性和参数,通过指定布局属性可以对子 Component在布局中的显示效果进行约束。例如:“width”、“height”是最基本的布局属性,它们指定了组件的大小。
组件和布局的包含关系:
布局可以理解为是一个容器,可以容纳组件和其他布局,并规定他们如何进行显示。组件在未被添加到布局中时,既无法显示也无法交互,因此一个用户界面至少包含一个布局。
Java UI框架提供了一些标准布局功能的容器,它们继承自ComponentContainer,一般以“Layout”结尾,如 DirectionalLayout、DependentLayout等。
组件树:
在一个界面中,最外层是一定是布局,在布局里面可以有组件,也可以有其他布局。所以布局可以理解为是多个组件形成的那个整体。
线性布局:DirectionalLayout
权重
也是一种百分比布局。
先计算父布局中,可利用空间之和:
父布局可分配区域=父布局长度或者宽度-所有固定长度或者宽度大小;
再计算百分比。
代码
<?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">
<Button
ohos:height="0vp"
ohos:width="100vp"
ohos:text="点我1"
ohos:text_size="35fp"
ohos:text_color="#FFFFFF"
ohos:text_alignment="center"
ohos:background_element="#21A8FD"
ohos:weight="2"/>
<Button
ohos:height="0vp"
ohos:width="100vp"
ohos:text="点我2"
ohos:text_size="35fp"
ohos:text_color="#FFFFFF"
ohos:text_alignment="center"
ohos:background_element="#FF0000"
ohos:weight="1"/>
<Image
ohos:height="match_content"
ohos:width="match_content"
ohos:image_src="$media:girl"/>
</DirectionalLayout>
相对布局:DependentLayout
核心:
找基准位置(和属性alignment相关,center,horizontal_center,vertical_center等)
在相对布局中,组件的位置是相对其他组件而言的
代码:
<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="left">
<Text
ohos:id="$+id:text1"
ohos:height="100vp"
ohos:width="100vp"
ohos:background_element="#21A8FD"
ohos:text="text1"
ohos:text_size="20fp"/>
<Text
ohos:id="$+id:text2"
ohos:height="100vp"
ohos:width="100vp"
ohos:background_element="#FF0000"
ohos:right_of="$id:text1"
ohos:text="text2"
ohos:text_size="20fp"/>
<Text
ohos:height="100vp"
ohos:width="100vp"
ohos:background_element="#00ff00"
ohos:below="$id:text2"
ohos:left_margin="100vp"
ohos:text="text3"
ohos:text_size="20fp"/>
</DependentLayout>
格子布局:TableLayout
说明:
行数和列数两个属性。
如果塞入元素过多,行数自动失效,再加一行。
对齐方式:alignment_type
值:align_contents(页边距对齐)(Margin alignment)
align_edges(边界对齐)(boundary alignment)
页边距对齐,是按照上一个组件的相对边界
边界对齐,是跟上一个组件对齐
其他布局:StackLayout(堆叠布局)、 AdaptiveBoxLayout(自适应盒子布局)
代码:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:row_count="3"
ohos:column_count="3"
ohos:alignment_type="align_edges">
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#FF0000"
ohos:text="1"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:left_margin="50vp"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#00FF00"
ohos:text="2"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#0000FF"
ohos:text="3"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#FFFF00"
ohos:text="4"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#FF00FF"
ohos:text="5"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#FF0000"
ohos:text="6"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#00FF00"
ohos:text="7"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#0000FF"
ohos:text="8"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#FFFF00"
ohos:text="9"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos:height="50vp"
ohos:width="50vp"
ohos:background_element="#FF0000"
ohos:text="10"
ohos:text_size="35fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
</TableLayout>
列表容器组件:ListContainer
ListContainer是一个列表容器类组件。在这里的每一行,我们都可以看做是一个item。如下图所示,包裹了所有 item的红色的容器,就是ListContainer。
注意细节:
1 每一行其实就是一个独立的item。
2 在屏幕的上面和下面,还有很多没有展示出来的item。 当我们用手指往上滑动的时候,就可以到下面的item。 当我们用手指往下滑动的时候,就可以到上面的item。 只不过划出屏幕的item会被销毁,而没有划入屏幕的item 还没有创建出来。
3 如果item过多,在内存会有垃圾。
实现步骤:
1. 给item去指定一个布局xml文件
2. 书写一个javabean类表示item
3. 写一个适配器类去管理item
4. 将适配器交给ListContainer
代码:
ability_main.xml
<?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"
ohos:alignment="center">
<ListContainer
ohos:id="$+id:listcontainer"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="horizontal_center"/>
</DirectionalLayout>
itemview.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_content"
ohos:orientation="horizontal">
<Text
ohos:id="$+id:text"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="00:00"
ohos:text_size="20fp"/>
</DirectionalLayout>
Item.java
package com.example.myapplication.domain;
public class Item {
//记录的值就是赋值给item里的text
private String text;
public Item() {
}
public Item(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
ItemProvider.java
public class ItemProvider extends BaseItemProvider {
//集合
//集合中就装了所有的item的对象
private ArrayList<Item> list;
private AbilitySlice as;
public ItemProvider(ArrayList<Item> list, AbilitySlice as) {
this.list = list;
this.as = as;
}
public ArrayList<Item> getList() {
return list;
}
public void setList(ArrayList<Item> list) {
this.list = list;
}
public AbilitySlice getAs() {
return as;
}
public void setAs(AbilitySlice as) {
this.as = as;
}
//总数据的个数
//多少个item
@Override
public int getCount() {
return list.size();
}
//i表示索引
//根据索引返回数据
@Override
public Object getItem(int i) {
if (list != null && i >= 0 && i < list.size()){
return list.get(i);
}
return null;
}
//返回某一项的ID
@Override
public long getItemId(int i) {
return i;
}
//返回item中要加载的布局对象
//参数一:当前要加载哪一行的的item(item的索引)
@Override
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
//获取每一个item里面的布局对象
DirectionalLayout dl = (DirectionalLayout) LayoutScatter.getInstance(as).parse(ResourceTable.Layout_itemview, null, false);
//获取每一个item里的数据
Item item = list.get(i);
//把数据加载到布局里的text中
Text text = (Text) dl.findComponentById(ResourceTable.Id_text);
text.setText(item.getText());
//当上面的代码执行完毕时就会获取到一个有数据的布局对象
//这时,只要把布局对象dl返回出去就可以了
//在item中,最外层的就是这个dl布局对象
return dl;
}
}
MainAbilitySlice.java
public class MainAbilitySlice extends AbilitySlice {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
//找到ListContainer
ListContainer listcontainer = (ListContainer) findComponentById(ResourceTable.Id_listcontainer);
//创建集合并给集合添加数据
ArrayList<Item> datasList = getData();
//创建一个item的管理员对象(适配器对象)
//并把要展示的所有数据和要加载的页面传递过去
ItemProvider itemprovider = new ItemProvider(datasList,this);
//把适配器交给列表容器中
listcontainer.setItemProvider(itemprovider);
}
public ArrayList<Item> getData(){
ArrayList<Item> list = new ArrayList<>();
for (int i = 0;i < 100;i++){
list.add(new Item("item"+i));
}
return list;
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
}
内存优化:
-
加载一个item,getComponent方法就要被调用一次。
-
假设屏幕中最多显示12个item,此时第13个item还没有在界面中显示出来。但是,ListContainer也会进行预加载。 预加载的好处:避免卡顿。
-
当item划出屏幕的时候,就会被销毁。当页面再次往下滑动的时候,会再次调用getComponent方法,加载本地xml文件,创建一个新的item布局对象。当item加载过多,内存中的垃圾就会过多,所以我们要优化。
-
优化的核心:让划出屏幕的item不销毁,而是继续复用
其它布局
绝对布局(PositionLayout)
可以指定组件的具体位置。
自适应布局(AdaptiveBoxLayout)
指定一行的范围。
屏幕范围小,每行就展示一个,屏幕范围大,就展示多个
底层还不是太稳定。