ListContainer
ListContainer是用来呈现连续、多行数据的组件,包含一系列相同类型的列表项。
支持的XML属性
ListContainer的共有XML属性继承自:Component
ListContainer的自有XML属性见下表:
属性名称 | 中文描述 | 取值 | 取值说明 | 使用案例 |
---|---|---|---|---|
rebound_effect | 开启/关闭回弹效果 | boolean类型 | 可以直接设置true/false,也可以引用boolean资源。 | ohos:rebound_effect="true"ohos:rebound_effect="$boolean:true" |
shader_color | 着色器颜色 | color类型 | 可以直接设置色值,也可以引用color资源。 | ohos:shader_color="#A8FFFFFF"ohos:shader_color="$color:black" |
orientation | 列表项排列方向 | horizontal | 表示水平方向列表。 | ohos:orientation="horizontal" |
vertical | 表示垂直方向列表。 | ohos:orientation="vertical" |
ListContainer的使用方法
在layout目录下,AbilitySlice对应的布局文件page_listcontainer.xml文件中创建ListContainer。
<ListContainer ohos:id="$+id:list_container" ohos:height="200vp" ohos:width="300vp" ohos:layout_alignment="horizontal_center"/>
在layout目录下新建xml文件(例:item_sample.xml),作为ListContainer的子布局。
<?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:left_margin="16vp" ohos:right_margin="16vp" ohos:orientation="vertical"> <Text ohos:id="$+id:item_index" ohos:height="match_content" ohos:width="match_content" ohos:padding="4vp" ohos:text="Item0" ohos:text_size="20fp" ohos:layout_alignment="center"/></DirectionalLayout>
创建SampleItem.java,作为ListContainer的数据包装类。
public class SampleItem { private String name; public SampleItem(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
ListContainer每一行可以为不同的数据,因此需要适配不同的数据结构,使其都能添加到ListContainer上。
创建SampleItemProvider.java,继承自BaseItemProvider。必须重写的方法如下:
| 方法 | 作用 | | ------------------------------------------------------------ | -------------------------------- | | int getCount() | 返回填充的表项个数。 | | Object getItem(int position) | 根据position返回对应的数据。 | | long getItemId(int position) | 返回某一项的id。 | | Component getComponent(int position, Component covertComponent,ComponentContainer componentContainer) | 根据position返回对应的界面组件。 |
代码示例如下:
import ohos.aafwk.ability.AbilitySlice;import ohos.agp.components.*;import java.util.List;public class SampleItemProvider extends BaseItemProvider { private List<SampleItem> list; private AbilitySlice slice; public SampleItemProvider(List<SampleItem> list, AbilitySlice slice) { this.list = list; this.slice = slice; } @Override public int getCount() { return list == null ? 0 : list.size(); } @Override public Object getItem(int position) { if (list != null && position >= 0 && position < list.size()){ return list.get(position); } return null; } @Override public long getItemId(int position) { return position; } @Override public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { final Component cpt; if (convertComponent == null) { cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_item_sample, null, false); } else { cpt = convertComponent; } SampleItem sampleItem = list.get(position); Text text = (Text) cpt.findComponentById(ResourceTable.Id_item_index); text.setText(sampleItem.getName()); return cpt; }}
在Java代码中添加ListContainer的数据,并适配其数据结构。
@Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_page_listcontainer); initListContainer(); } private void initListContainer() { ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_list_container); List<SampleItem> list = getData(); SampleItemProvider sampleItemProvider = new SampleItemProvider(list, this); listContainer.setItemProvider(sampleItemProvider); } private ArrayList<SampleItem> getData() { ArrayList<SampleItem> list = new ArrayList<>(); for (int i = 0; i <= 8; i++) { list.add(new SampleItem("Item" + i)); } return list; }
图1 ListContainer的界面显示效果
ListContainer的常用接口
设置响应点击事件。
listContainer.setItemClickedListener((container, component, position, id) -> { SampleItem item = (SampleItem) listContainer.getItemProvider().getItem(position); new ToastDialog(this) .setText("you clicked:" + item.getName()) // Toast显示在界面中间 .setAlignment(LayoutAlignment.CENTER) .show();});
图2 响应点击事件效果
设置响应长按事件。
listContainer.setItemLongClickedListener((container, component, position, id) -> { SampleItem item = (SampleItem) listContainer.getItemProvider().getItem(position); new ToastDialog(this) .setText("you long clicked:" + item.getName()) .setAlignment(LayoutAlignment.CENTER) .show(); return false;});
图3 响应长按事件效果
ListContainer的样式设置
ListContainer的样式设置相关的接口如下:
属性 | Java方法 | 作用 |
---|---|---|
orientation | setOrientation(int orientation) | 设置布局方向 |
- | setContentStartOffSet(int startOffset)setContentEndOffSet(int endOffset)setContentOffSet(int startOffset, int endOffset) | 设置列表容器的开始和结束偏移量 |
rebound_effect | setReboundEffect(boolean enabled) | 设置是否启用回弹效果 |
- | setReboundEffectParams(int overscrollPercent, float overscrollRate, int remainVisiblePercent)setReboundEffectParams(ListContainer.ReboundEffectParams reboundEffectParams) | 设置回弹效果参数 |
shader_color | setShaderColor(Color color) | 设置着色器颜色 |
设置ListContainer的布局方向:orientation设置为“horizontal”,表示横向布局;orientation设置为“vertical”,表示纵向布局。默认为纵向布局。
在xml中设置:
<ListContainer ... ohos:orientation="horizontal"/>
在Java代码中设置:
listContainer.setOrientation(Component.HORIZONTAL);
图4 设置布局方向为horizontal的效果
设置ListContainer的开始和结束偏移量。
listContainer.setContentOffSet(32, 16);
为了便于观察,分别在子布局和ListContainer布局中添加背景色:
在item_sample.xml的根布局中添加背景色。
<DirectionalLayout ... ohos:background_element="#FAEBD7"> ...</DirectionalLayout>
在ListContainer布局文件中添加背景色。
<ListContainer ... ohos:background_element="#FFDEAD"/>
图5 设置列表容器的开始偏移量为32,结束偏移量为16效果
设置回弹效果。
在xml中设置:
<ListContainer ... ohos:rebound_effect="true"/>
在Java代码中设置
listContainer.setReboundEffect(true);
图6 回弹效果
在开启回弹效果后,可以调用setReboundEffectParams()方法调整回弹效果。
listContainer.setReboundEffectParams(40, 0.6f, 20);
设置着色器颜色。
在xml中设置:
<ListContainer ... ohos:shader_color="#90EE90"/>
在Java代码中设置:
listContainer.setShaderColor(new Color(Color.getIntColor("#90EE90")));
图7 设置着色器效果
ListContainer性能优化
在适配ListContainer的数据时,无论是新创建的列表项实例,还是从缓存中获取到的,都需要调用方法findComponentById()获取所有子组件并进行数据填充,大量调用该方法,会损耗ListContainer的性能。比较好的解决方案是在创建列表项实例时进行调用,将获取到的所有子组件绑定到列表项的实例中,当从缓存中获取到列表项实例后,直接使用绑定的的子组件填充新数据。完整示例代码如下:
创建数据包装类
public class SettingItem { private int imageId; private String settingName; private boolean isChecked; public SettingItem(int imageId, String settingName, boolean isChecked) { this.imageId = imageId; this.settingName = settingName; this.isChecked = isChecked; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; } public String getSettingName() { return settingName; } public void setSettingName(String settingName) { this.settingName = settingName; } public boolean isChecked() { return isChecked; } public void setChecked(boolean checked) { isChecked = checked; }}
创建列表项布局layout_item_setting.xml
<?xml version="1.0" encoding="utf-8"?><DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="80vp" ohos:width="match_parent" ohos:padding="8vp" ohos:orientation="horizontal"> <Image ohos:id="$+id:ima_setting" ohos:height="match_parent" ohos:width="0" ohos:layout_alignment="vertical_center" ohos:weight="2"> </Image> <Text ohos:id="$+id:text_setting" ohos:height="match_content" ohos:width="0" ohos:padding="4fp" ohos:text_size="20fp" ohos:start_padding="8vp" ohos:end_padding="8vp" ohos:weight="6" ohos:layout_alignment="vertical_center"/> <Switch ohos:id="$+id:switch_setting" ohos:height="20vp" ohos:width="0vp" ohos:weight="1" ohos:layout_alignment="vertical_center"/> </DirectionalLayout>
创建SettingProvider.java
public class SettingProvider extends BaseItemProvider{ // ListContainer的数据集合 private List<SettingItem> settingList; private AbilitySlice slice; public SettingProvider(List<SettingItem> list, AbilitySlice slice) { this.settingList = list; this.slice = slice; } // 用于保存列表项中的子组件信息 public class SettingHolder { Image settingIma; Text settingText; Switch settingSwitch; SettingHolder(Component component) { settingIma = (Image) component.findComponentById(ResourceTable.Id_ima_setting); settingText = (Text) component.findComponentById(ResourceTable.Id_text_setting); settingSwitch = (Switch) component.findComponentById(ResourceTable.Id_switch_setting); settingSwitch.setTrackElement(trackElementInit( new ShapeElement(slice, ResourceTable.Graphic_track_on_element), new ShapeElement(slice, ResourceTable.Graphic_track_off_element))); settingSwitch.setThumbElement(thumbElementInit( new ShapeElement(slice, ResourceTable.Graphic_thumb_on_element), new ShapeElement(slice, ResourceTable.Graphic_thumb_off_element))); } private StateElement trackElementInit(ShapeElement on, ShapeElement off) { StateElement trackElement = new StateElement(); trackElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, on); trackElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, off); return trackElement; } private StateElement thumbElementInit(ShapeElement on, ShapeElement off) { StateElement thumbElement = new StateElement(); thumbElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, on); thumbElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, off); return thumbElement; } } @Override public int getCount() { return settingList == null ? 0 : settingList.size(); } @Override public Object getItem(int position) { if (settingList != null && position >= 0 && position < settingList.size()){ return settingList.get(position); } return null; } @Override public long getItemId(int position) { return position; } @Override public Component getComponent(int position, Component component, ComponentContainer componentContainer) { final Component cpt; SettingHolder holder; SettingItem setting = settingList.get(position); if (component == null) { cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_layout_item_setting, null, false); holder = new SettingHolder(cpt); // 将获取到的子组件信息绑定到列表项的实例中 cpt.setTag(holder); } else { cpt = component; // 从缓存中获取到列表项实例后,直接使用绑定的子组件信息进行数据填充。 holder = (SettingHolder) cpt.getTag(); } holder.settingIma.setPixelMap(setting.getImageId()); holder.settingText.setText(setting.getSettingName()); holder.settingSwitch.setChecked(setting.isChecked()); return cpt; }}
其中使用到的graphic资源文件如下:
thumb_off_element.xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="oval"> <solid ohos:color="#FFFFFF"/> <bounds ohos:top="0" ohos:left="0" ohos:right="20vp" ohos:bottom="20vp"/></shape>
thumb_on_element.xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="oval"> <solid ohos:color="#1E90FF"/> <bounds ohos:top="0" ohos:left="0" ohos:right="20vp" ohos:bottom="20vp"/></shape>
track_off_element.xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="rectangle"> <solid ohos:color="#808080"/> <corners ohos:radius="20vp"/></shape>
track_on_element.xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="rectangle"> <solid ohos:color="#87CEFA"/> <corners ohos:radius="20vp"/></shape>
在layout文件夹下,创建ListContainerSlice对应的布局文件layout_listcontainer.xml,并添加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:padding="8vp" ohos:orientation="vertical"> <ListContainer ohos:id="$+id:list_container" ohos:height="match_parent" ohos:width="match_parent"/></DirectionalLayout>
ListContainer添加数据
public class ListContainerSlice extends AbilitySlice { @Override protected void onStart(Intent intent) { super.onStart(intent); setUIContent(ResourceTable.Layout_layout_listcontainer); ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_list_container); SettingProvider provider = new SettingProvider(getData(), this); listContainer.setItemProvider(provider); } private List<SettingItem> getData() { ArrayList<SettingItem> data = new ArrayList<>(); for (int i = 0; i < 100; i++) { data.add(new SettingItem( ResourceTable.Media_icon, "SettingName" + i, i % 3 == 0 )); } return data; }}
图8 效果如下:
相关实例
针对ListContainer组件开发,有以下示例工程可供参考:
List
本示例以长列表联系人为例,演示ListContainer 组件的基本使用方法。