列表项布局表示问题
使用FileBrowser在目录之间进行切换时,发现了一个问题:本来只应该在出现在返回上级目录列表项上面的<<按钮会按照一定的频率出现在其他列表项上。具体请参见下面的视频:
经过各种尝试之后得到的结论是问题出在下面的代码:
@Override
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
HiLog.info(LABEL, "getComponent, i=%{public}d!", i);
BrowserItem item = list.get(i);
Component cpt = null;
if (component == null) {
cpt = item.createUiComponent();
} else {
cpt = component;
}
Text text = (Text) cpt.findComponentById(ResourceTable.Id_item_name);
text.setText(item.getName());
return cpt;
}
解决方法
这段代码的逻辑很简单:如果某一个列表项对应的组件已经存在就直接使用;否则生成对应的新组件。从结果上看,这个组件并不是系统为每个列表项缓存一个组件,而是为整个ListContainer缓存了若干组件并按照顺序分配给列表项。如果每个组件的表示方式都完全相同,这种做法没有问题;如果像FileBrowser这样,不同列表项的表示方式不同就会出现下面的问题:
解决的办法也很简单:在使用已经存在的组件之前进行检查,看看这个组件是不是该列表项想要的,如果不是就新生成一个:
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
HiLog.info(LABEL, "getComponent, i=%{public}d!", i);
BrowserItem item = list.get(i);
Component cpt = null;
if (component == null) {
cpt = item.createUiComponent();
} else {
if(component.getId() == item.getComponentId()) {
cpt = component;
}
else{
cpt = item.createUiComponent();
}
}
Text text = (Text) cpt.findComponentById(ResourceTable.Id_item_name);
text.setText(item.getName());
return cpt;
}
为了向BowerItemProvider说明自己想要什么,我们为每个组件增加了getComponentId方法。例如ParentItem:
public class ParentItem extends BrowserItem {
static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00106, "ParentItem");
File dir = null;
ItemListener listener = null;
public ParentItem(Context context, File dir, ItemListener listener) {
super(context, dir.toString());
this.dir = dir;
this.listener = listener;
}
@Override
public int getComponentId(){
return ResourceTable.Id_parent_layout;
}
@Override
public Component createUiComponent(){
HiLog.info(LABEL, "ParentItem.createUiComponent of %{public}s", name);
Component comp = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_parent_item, null, false);
Button back = (Button) comp.findComponentById(ResourceTable.Id_extend);
if(listener != null && dir.listFiles() != null){
back.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
listener.changeDir(ParentItem.this.dir);
}
});
}
return comp;
}
代码12行中返回的Id_parentlayout需要在布局文件中分别指定。对于ParentItem的布局文件,它的顶层组件的Id在第4行指定:
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:id="$+id:parent_layout"
ohos:height="match_content"
ohos:width="match_parent"
ohos:left_margin="16vp"
ohos:right_margin="16vp"
ohos:orientation="horizontal">
<Text
ohos:id="$+id:item_name"
ohos:height="match_content"
ohos:width="match_content"
ohos:padding="4vp"
ohos:text="Item0"
ohos:text_size="20fp"
ohos:layout_alignment="left"/>
<Button
ohos:id="$+id:extend"
ohos:height="match_content"
ohos:width="match_content"
ohos:padding="4vp"
ohos:text="$string:BackTo"
ohos:text_size="20fp"
ohos:layout_alignment="center"/>
</DirectionalLayout>
经过这么一番折腾,软件的动作如下:
相关列表项的表示结果也变成了下面的样子:
参考资料
ListContainer
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-java-component-listcontainer-0000001060007847
参考代码
https://github.com/xueweiguo/Harmony/tree/master/FileBrowser
作者著作介绍
《实战Python设计模式》是作者去年3月份出版的技术书籍,该书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。
对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。