https://harmonyos.51cto.com/#zz
- 在一个文件夹里会罗列出很多个子文件夹或者文件,包含文件名、文件大小、文件修改日期、文件类型等;
- 在一个内容网站里会罗列出很多条内容,或许还要翻页,包含文章标题、文章作者、发表时间、浏览量等;
- 在一个图册网站,里面会罗列出很多图集或者图片,包含图集名称、图集作者等;
- 在一个音乐播放器的具体某类歌曲中,会罗列出很多歌曲,包含歌名、作者、所属歌集、时长等;
还有很多想类似的情况,这里就不一一列举了。通过上面四个场景,我们可以发现一个共同的特点,它们都有很多条数据,每个场景中数据的属性是相同的。这就让我想起了在学习Java 的数组时,对于一维数组,其元素的类型是相同的,你不可能定义了一个整形的数组,向里面添加了字符串类型的元素,这是不行的。假如我们需要做一个新闻类的展示界面,那么我们的数据中,每个元素中的属性必须是一样的。比如我们的元素属性包含标题、作者、内容摘要、封面图、发布时间、浏览记录、点赞量、评论量,但是在这个列表中存在一个特殊的元素,它的属性为歌曲名称、作者、歌集、时长,那么我们在展示这个数据集的时候,会出现什么问题呢(这里不做详细说明了,也许你已经知道答案是什么了)?
对于ListContainer组件的理论不在这里做赘述了,官文已经说得很明白了,本节将结合OkHttp插件,来使用ListContainer组件做一个简单的新闻展示Demo。
在开始复杂的列表展示页之前,我们先来做一个简单的列表展示,在学习Android的时候,列表有个展示水果的示例,我将在HarmonyOS智慧屏上实现这个小示例。
一、单一的列表
1、在layout目录下新建fruit_layout.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:orientation="vertical">
- <ListContainer
- ohos:id="$+id:fruit_list"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:layout_alignment="horizontal_center"/>
- </DirectionalLayout>
2、接着在layout目录新建element_layout.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:background_element="$graphic:background_element"
- ohos:bottom_margin="4vp"
- ohos:orientation="vertical">
- <Text
- ohos:id="$+id:element_index"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:padding="4vp"
- ohos:text_size="30fp"
- ohos:layout_alignment="center"/>
- </DirectionalLayout>
3、组建一个类型为String的List列表,最终呈现在UI界面上。
- List<String> 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<String> list;
- private AbilitySlice slice;
- public FruitElementProvider(List<String> 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<String> 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
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"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:bottom_margin="4vp"
- ohos:orientation="vertical">
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:background_element="$graphic:background_element"
- ohos:orientation="horizontal">
- <Image
- ohos:id="$+id:news_imgsrc"
- ohos:image_src="$media:icon"
- ohos:height="100vp"
- ohos:width="100vp"/>
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_parent">
- <Text
- ohos:id="$+id:news_title"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:weight="1"
- ohos:text="我是标题"
- ohos:text_size="20fp"/>
- <Text
- 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"/>
- <DependentLayout
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:weight="1">
- <Text
- 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"/>
- <Text
- 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"/>
- </DependentLayout>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
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<News> 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();
- }
我的HarmonyOS GitHub库
©著作权归作者和HarmonyOS技术社区共同所有,如需转载,请注明出处,否则将追究法律责任
https://harmonyos.51cto.com/#zz