- 在一个文件夹里会罗列出很多个子文件夹或者文件,包含文件名、文件大小、文件修改日期、文件类型等;
- 在一个内容网站里会罗列出很多条内容,或许还要翻页,包含文章标题、文章作者、发表时间、浏览量等;
- 在一个图册网站,里面会罗列出很多图集或者图片,包含图集名称、图集作者等;
- 在一个音乐播放器的具体某类歌曲中,会罗列出很多歌曲,包含歌名、作者、所属歌集、时长等;
<?xml version="1.0" encoding="utf-8"?>
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
ohos:id="$+id:fruit_list"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:layout_alignment="horizontal_center"/>
2、接着在layout目录新建element_layout.xml文件,作为ListContainer组件的子布局,代码如下:
<?xml version="1.0" encoding="utf-8"?>
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_parent"
ohos:background_element="$graphic:background_element"
ohos:bottom_margin="4vp"
ohos:orientation="vertical">
ohos:id="$+id:element_index"
ohos:height="match_content"
ohos:width="match_content"
ohos:padding="4vp"
ohos:text_size="30fp"
ohos:layout_alignment="center"/>
3、组建一个类型为String的List列表,最终呈现在UI界面上。
List fruits = new ArrayList<>();
fruits.add("苹果");
fruits.add("橘子");
fruits.add("橙子");
fruits.add("香蕉");
fruits.add("梨");
fruits.add("桃子");
fruits.add("苹果梨");
fruits.add("香蕉梨");
fruits.add("冬桃");
fruits.add("红葡萄");
fruits.add("紫葡萄");
fruits.add("黑葡萄");
4、ListContainer组件的每一行元素可以是不相同的数据,因此需要适配不同的数据结构,使其能够添加到ListContainer组件中,并以列表的形式呈现在UI界面上。ListContainer组件提供了setItemProvider(BaseItemProvider itemProvider)方法,用于设置要显示的ListContainer组件对象。创建FruitElementProvider类,并继承BaseItemProvider,重写其中的方法。
package com.ming.harmonyos.newsapp.domain;
import com.ming.harmonyos.newsapp.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.components.*;
import java.util.List;
public class FruitElementProvider extends BaseItemProvider {
private List list;
private AbilitySlice slice;
public FruitElementProvider(List fruits, AbilitySlice slice) {
this.list = fruits;
this.slice = slice;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
Component cpt = component;
if (cpt == null) {
cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_element_layout, null, false);
}
String fruit = list.get(i);
Text text = (Text) cpt.findComponentById(ResourceTable.Id_element_index);
text.setText(fruit);
return cpt;
}
}
5、在MainAbility中适配ListContainer的数据结构,并添加点击事件。
ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_fruit_list);
List fruits = new ArrayList<>();
fruits.add("苹果");
fruits.add("橘子");
fruits.add("橙子");
fruits.add("香蕉");
fruits.add("梨");
fruits.add("桃子");
fruits.add("苹果梨");
fruits.add("香蕉梨");
fruits.add("冬桃");
fruits.add("红葡萄");
fruits.add("紫葡萄");
fruits.add("黑葡萄");
FruitElementProvider fruitElementProvider = new FruitElementProvider(fruits, this);
listContainer.setItemProvider(fruitElementProvider);
listContainer.setItemClickedListener((listContainer1, component, position, id) -> {
String item = (String) listContainer1.getItemProvider().getItem(position);
new ToastDialog(getContext())
.setText("点击了:" + item)
// Toast显示在界面中间
.setAlignment(LayoutAlignment.CENTER)
.show();
});
6、运行查看效果。
二、组合复杂的列表
1、和单一列表不同之处在于元素的显示和元素的属性。单一列表中我使用了一个List,复杂的列表中,我将根据请求API接口返回的数据类型进行数据结构的组装。在这之前我先要说说OkHttp如何引入,以及需要授予那些权限。
1)首先我们在build.gradle中引入OkHttp(本节并不是对OkHttp做详细讲解,这里只是简单的使用)的版本,并点击窗口上的Sync Now进行同步下载。
implementation("com.squareup.okhttp3:okhttp:4.9.0")
2)在config.json中配置INTENT权限。
"reqPermissions": [
{
"name": "ohos.permission.INTERNET",
"usedScene": {
"ability": [
"com.ming.harmonyos.newsapp.MainAbility"
],
"when": "always"
}
}
]
3)在MainAbilitySlice中实例化OkHttpClient对象,并封装它的GET调用方法。
private OkHttpClient client = new OkHttpClient();
private String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
2、做好上面的准备之后,我使用天行数据的每日简报API接口。先看一下调用接口返回的参数:
3、我们根据返回的参数来构建我们的列表元素类。
public class News {
//新闻标题
private String title;
//简报内容
private String digest;
//简报封面
private String imgsrc;
//简报链接
private String url;
//简报来源
private String source;
//新闻时间
private String mtime;
//getter & setter
}
4、在layout目录新建news_element_layout.xml文件,作为ListContainer组件的子布局,代码如下:
<?xml version="1.0" encoding="utf-8"?>
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_content"
ohos:width="match_parent"
ohos:bottom_margin="4vp"
ohos:orientation="vertical">
ohos:height="match_parent"
ohos:width="match_parent"
ohos:background_element="$graphic:background_element"
ohos:orientation="horizontal">
ohos:id="$+id:news_imgsrc"
ohos:image_src="$media:icon"
ohos:height="100vp"
ohos:width="100vp"/>
ohos:height="match_parent"
ohos:width="match_parent">
ohos:id="$+id:news_title"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:weight="1"
ohos:text="我是标题"
ohos:text_size="20fp"/>
ohos:id="$+id:news_remark"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:weight="1"
ohos:text="我是摘要"
ohos:text_size="14fp"
ohos:multiple_lines="true"
ohos:max_text_lines="2"
ohos:text_color="#888888"/>
ohos:height="match_parent"
ohos:width="match_parent"
ohos:weight="1">
ohos:id="$+id:news_source"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="来源"
ohos:text_size="12fp"
ohos:text_color="#CCCCCC"
ohos:align_parent_left="true"/>
ohos:id="$+id:news_time"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="时间"
ohos:text_size="12fp"
ohos:text_color="#CCCCCC"
ohos:right_padding="20vp"
ohos:align_parent_right="true"/>
5、创建NewsItemProvider类,并继承BaseItemProvider,重写其中的方法。
@Override
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
Component cpt = component;
if (cpt == null) {
cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_news_element_layout, null, false);
}
News news = list.get(i);
//封面图
Image image = (Image) cpt.findComponentById(ResourceTable.Id_news_imgsrc);
//标题
Text title = (Text) cpt.findComponentById(ResourceTable.Id_news_title);
title.setText(news.getTitle());
//摘要
Text remark = (Text) cpt.findComponentById(ResourceTable.Id_news_remark);
remark.setText(news.getDigest());
//来源
Text source = (Text) cpt.findComponentById(ResourceTable.Id_news_source);
source.setText(news.getSource());
//日期
Text time = (Text) cpt.findComponentById(ResourceTable.Id_news_time);
time.setText(news.getMtime());
return cpt;
}
6、在MainAbility中使用OkHttp获取数据并适配ListContainer的数据结构,最后查看运行效果。
/**
* 复杂数据结构
*/
private void initNewsListContainer() {
//在子线程中获取数据
new Thread(new Runnable() {
@Override
public void run() {
try {
String response = MainAbilitySlice.this.run("https://api.tianapi.com/bulletin/index?key=您自己的KEY");
System.out.println(response);
JSONObject jsonObject = JSONObject.parseObject(response);
int code = Integer.valueOf(String.valueOf(jsonObject.get("code")));
String message = String.valueOf(jsonObject.get("msg"));
String data = String.valueOf(jsonObject.get("newslist"));
if (code == 200) {
List list = JSONArray.parseArray(data, News.class);
ListContainer news = (ListContainer) findComponentById(ResourceTable.Id_news_list);
NewsItemProvider nip = new NewsItemProvider(list, MainAbilitySlice.this);
news.setItemProvider(nip);
} else {
new ToastDialog(getContext())
.setText("抛出异常信息: " + message)
.setAlignment(LayoutAlignment.CENTER)
.show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}