当前位置:   article > 正文

HarmonyOS开发详解(五)——鸿蒙高级组件数据动态绑定案例实践_鸿蒙 findcomponentbyid

鸿蒙 findcomponentbyid

         本文将专门花一篇来讲述ListContainer和PageSlider,ListContainer主要是参考官方例子,PageSlider在原有官方例子上进行了一些升级改造。原有例子添加固定的文字,通过改造动态读取本地json内容和本地图片资源。

        Java UI组件中有些需要动态绑定数据的组件,因为系统不了解你的样式(布局)和行为(方法),这就必须要自己按着规则定义,这就导致组件使用为略显复杂,接下来就只讲一下这些稍微复杂的组件。

        1、 ListContainer(列表容器)

       1、ListContainer实现思路分析

         ListContainer列表容器,用来呈现多行连续的同类数据;导致ListContainer稍嫌复杂有两个原因:

        1)列表中每项布局不确定,需要自定义布局(比如新闻每个列表项可能只有标题,也可能有标题、简介、图片,这会导致每行布局不一样)

        2)内容不确定,动态绑定(新闻条数不确定、内容动态加载)

        以上的不确定导致了每个布局需要自己定义,每个数据类型需要自己定义;

        2、ListContainer实现步骤

        1)定义ListContainer:layout下创建ListContainer组件

        2)定义每项布局:layout下创建ListContainer的内容,即子布局,如果是带标题、简介、图片的新闻列表,就定义两个text和一个image。

        3)定义数据实体类:每一条列表的具体组成java类

        4)定义每条列表项的属性:通过实现BaseItemProvider类;因为每项列表内容不确定,通过重写getComponent方法,返回每项布局内容(第二步中的layerout是自定义且空的,这里定义布局和数据的组合方法)

        5)组装ListContainer:通过BaseItemProvider的实现类将数据和ListContainer组合起来;

        6)注册其他行为:比如定义点击事件、定义更新数据;

        完整代码太长,结合上述步骤贴出核心代码,上部分布局类代码,下部分java类代码:

  1. //第一步创建layerout下ListContainer布局页面
  2. <ListContainer
  3. ohos:id="$+id:list_container"
  4. ohos:height="200vp"
  5. ohos:width="350vp"
  6. ohos:layout_alignment="horizontal_center"/>
  7. //第二步创建子布局,这里用两个字段name和address来展示
  8. <Text
  9. ohos:id="$+id:item_index"
  10. ohos:height="match_content"
  11. ohos:width="match_content"
  12. ohos:padding="4vp"
  13. ohos:text="Item0"
  14. ohos:text_size="20fp"
  15. ohos:layout_alignment="center"/>
  16. <Text
  17. ohos:id="$+id:item_index1"
  18. ohos:height="match_content"
  19. ohos:width="match_content"
  20. ohos:padding="4vp"
  21. ohos:text="Item0"
  22. ohos:text_size="20fp"
  23. ohos:layout_alignment="left"/>
  1. //第三步,创建ItemBean实体类
  2. public class ItemBean {
  3. private String name;
  4. private String address;
  5. public ItemBean(String name,String address) {
  6. this.name = name;
  7. this.address=address;
  8. }
  9. //属性get、set方法省略...
  10. }
  11. //第四步,实现BaseItemProvider类,必须实现以下override方法,这样系统就可以根据这些方法对listContainer内容进行组装,并提供一些行为(比如查询长度、返回ID)
  12. public class ItemProvider extends BaseItemProvider {
  13. private List<ItemBean> list;
  14. private AbilitySlice abilitySlice;
  15. public ItemProvider(List<ItemBean> list, AbilitySlice abilitySlice) {
  16. this.list = list;
  17. this.abilitySlice = abilitySlice;
  18. }
  19. @Override
  20. public int getCount() {
  21. return list.size();
  22. }
  23. @Override
  24. public Object getItem(int i) {
  25. if(list!=null&&list.size()>0){
  26. return list.get(i);
  27. }
  28. return null;
  29. }
  30. @Override
  31. public long getItemId(int i) {
  32. return i;
  33. }
  34. @Override
  35. public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
  36. Component temp;
  37. if(component==null){
  38. temp=LayoutScatter.getInstance(abilitySlice).parse(ResourceTable.Layout_list_container_item,null,false);
  39. }else{
  40. temp=component;
  41. }
  42. ItemBean itemBean= list.get(i);
  43. Text text1=temp.findComponentById(ResourceTable.Id_item_index);
  44. text1.setText(itemBean.getName());
  45. Text text2 =temp.findComponentById(ResourceTable.Id_item_index1);
  46. text2.setText(itemBean.getAddress());
  47. return temp;
  48. }
  49. }
  50. //第五步,在PageSlice里面根据ItemProvider组装ListContainer,构造一个长度20的列表
  51. private void initListContainer() {
  52. ListContainer listCon=findComponentById(ResourceTable.Id_list_container);
  53. List<ItemBean> list=getData();
  54. ItemProvider itemProvider=new ItemProvider(list,this);
  55. listCon.setItemProvider(itemProvider);
  56. }
  57. private List<ItemBean> getData(){
  58. List<ItemBean> list=new ArrayList<>();
  59. for(int i=0;i<20;i++){
  60. ItemBean itembean=new ItemBean("item"+i,"address"+i);
  61. list.add(itembean);
  62. }
  63. return list;
  64. }
  65. //第六步,定义点击事件
  66. listCon.setItemClickedListener((container, component, position, id)->{
  67. ItemBean itemBean=(ItemBean)container.getItemProvider().getItem(position);
  68. new ToastDialog(this)
  69. .setText("你点击了"+itemBean.getName()+"__"+itemBean.getAddress())
  70. .setAlignment(LayoutAlignment.HORIZONTAL_CENTER).show();
  71. });

                以上代码实现效果: 

         2、PageSlider(页面切换组件)

        PageSlider可以通过滚动实现页面间内容切换,每个页面样式内容当然不确定;实现思路和ListContainer一模一样,这里就直接贴出核心代码。

        为了练习,里面添加通过代码创建Text(内容)、image、Text(通过事件获取页码);

  1. //第一步创建PageSlider
  2. <PageSlider
  3. ohos:id="$+id:page_slider"
  4. ohos:height="300vp"
  5. ohos:width="300vp"
  6. ohos:layout_alignment="horizontal_center"/>
  7. <!--页面导航,前期先不用
  8. <PageSliderIndicator
  9. ohos:id="$+id:indicator"
  10. ohos:height="match_content"
  11. ohos:width="match_content"
  12. ohos:padding="8vp"
  13. ohos:layout_alignment="horizontal_center"
  14. ohos:top_margin="16vp"
  15. ohos:background_element="#55FFC0CB"/>
  16. -->
  17. //第二步创建页面的子布局
  18. <Text
  19. ohos:id="$+id:item_title"
  20. ohos:height="match_content"
  21. ohos:width="match_content"
  22. ohos:layout_alignment="top|center"
  23. ohos:padding="4vp"
  24. ohos:text="Item0"
  25. ohos:text_size="20fp"/>
  26. <Image
  27. ohos:id="$+id:imageComponent"
  28. ohos:height="200vp"
  29. ohos:width="match_parent"
  30. />
  31. <Text
  32. ohos:id="$+id:item_page_num"
  33. ohos:height="40vp"
  34. ohos:width="80vp"
  35. ohos:layout_alignment="bottom|center"
  36. ohos:padding="4vp"
  37. ohos:text="Item0"
  38. ohos:text_size="20fp"
  39. />
  1. //第三步,布局数据内容的实体类
  2. public class ItemPageSlider {
  3. private String title;
  4. private String imageUrl;
  5. private String pageNum;
  6. public ItemPageSlider(String title, String imageUrl, String pageNum) {
  7. this.title = title;
  8. this.imageUrl = imageUrl;
  9. this.pageNum = pageNum;
  10. }
  11. public String getTitle() {
  12. return title;
  13. }
  14. public void setTitle(String title) {
  15. this.title = title;
  16. }
  17. public String getPageNum() {
  18. return pageNum;
  19. }
  20. public void setPageNum(String pageNum) {
  21. this.pageNum = pageNum;
  22. }
  23. public String getImageUrl() {
  24. return imageUrl;
  25. }
  26. public void setImageUrl(String imageUrl) {
  27. this.imageUrl = imageUrl;
  28. }
  29. }
  30. //第四步,构建数据提供者
  31. public class ItemPageSliderProvider extends PageSliderProvider {
  32. private List<ItemPageSlider> list;
  33. private Context context;
  34. public ItemPageSliderProvider(List<ItemPageSlider> list, Context context) {
  35. this.list = list;
  36. this.context = context;
  37. }
  38. @Override
  39. public int getCount() {
  40. return list.size();
  41. }
  42. //组装也面内容
  43. @Override
  44. public Object createPageInContainer(ComponentContainer componentContainer, int i) {
  45. Component component = LayoutScatter.getInstance(this.context).parse(ResourceTable.Layout_page_slider_item, null, false);
  46. Text title = component.findComponentById(ResourceTable.Id_item_title);
  47. title.setText(list.get(i).getTitle());
  48. Text pageNum = component.findComponentById(ResourceTable.Id_item_page_num);
  49. pageNum.setText(list.get(i).getPageNum());
  50. Image image = component.findComponentById(ResourceTable.Id_imageComponent);
  51. image.setPixelMap(CommonUtils.getPixelMapFromPath(context, list.get(i).getImageUrl()));
  52. componentContainer.addComponent(component);
  53. return component;
  54. }
  55. //注意必须要实现销毁类,不然内容不断添加,并不会移除
  56. @Override
  57. public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) {
  58. componentContainer.removeComponent((Component)o);
  59. }
  60. @Override
  61. public boolean isPageMatchToObject(Component component, Object o) {
  62. return false;
  63. }
  64. }
  65. //第五步,构建数据提供者
  66. private void initPageSlider() {
  67. PageSlider pageSlider = findComponentById(ResourceTable.Id_page_slider);
  68. ItemPageSliderProvider itemPageSliderProvider=new ItemPageSliderProvider(getData(),this);
  69. pageSlider.setProvider(itemPageSliderProvider);
  70. //监听页面变化
  71. pageSlider.addPageChangedListener(new PageSlider.PageChangedListener() {
  72. @Override
  73. public void onPageSliding(int i, float v, int i1) {
  74. //....
  75. }
  76. @Override
  77. public void onPageSlideStateChanged(int i) {
  78. //....
  79. }
  80. @Override
  81. public void onPageChosen(int i) {
  82. new ToastDialog(getContext()).setText("当前页面索引:"+i++).show();
  83. }
  84. });
  85. //添加页面导航,启用前面的xml布局中PageSliderIndicator,配合此段代码即可实现页面导航
  86. PageSliderIndicator indicator = (PageSliderIndicator)findComponentById(ResourceTable.Id_indicator);
  87. ShapeElement normalElement = new ShapeElement();
  88. normalElement.setRgbColor(RgbColor.fromArgbInt(0xADD8E6));
  89. normalElement.setAlpha(168);
  90. normalElement.setShape(ShapeElement.OVAL);
  91. normalElement.setBounds(0, 0, 32, 32);
  92. ShapeElement selectedElement = new ShapeElement();
  93. selectedElement.setRgbColor(RgbColor.fromArgbInt(0x00BFFF));
  94. selectedElement.setAlpha(168);
  95. selectedElement.setShape(ShapeElement.OVAL);
  96. selectedElement.setBounds(0, 0, 48, 48);
  97. indicator.setItemElement(normalElement, selectedElement);
  98. indicator.setItemOffset(60);
  99. indicator.setPageSlider(pageSlider);
  100. }

辅助类,用于读取页面内容(用本地文件json定义)、图片 (显示图片资源)

  1. public class CommonUtils {
  2. private static final String TAG = "CommonUtils";
  3. //读取资源图片
  4. public static PixelMap getPixelMapFromPath(Context context, String path) {
  5. InputStream inputStream = null;
  6. try {
  7. inputStream = context.getResourceManager().getRawFileEntry(path).openRawFile();
  8. ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
  9. sourceOptions.formatHint = "image/jpg";
  10. ImageSource imageSource = ImageSource.create(inputStream, sourceOptions);
  11. ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
  12. decodingOptions.desiredSize = new Size(0, 0);
  13. decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
  14. decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
  15. return imageSource.createPixelmap(decodingOptions);
  16. } catch (IOException e) {
  17. LogUtil.error(TAG, e.getMessage());
  18. } finally {
  19. try {
  20. if (inputStream != null) {
  21. inputStream.close();
  22. }
  23. } catch (IOException ex) {
  24. LogUtil.error(TAG, ex.getMessage());
  25. }
  26. }
  27. return null;
  28. }
  29. //读取资源文件json内容
  30. public static String getStringFromPath(Context context, String path) {
  31. try {
  32. Resource dataResource = context.getResourceManager().getRawFileEntry(path).openRawFile();
  33. byte[] buffers = new byte[dataResource.available()];
  34. if (dataResource.read(buffers) != -1) {
  35. return new String(buffers, StandardCharsets.UTF_8);
  36. }
  37. } catch (IOException ex) {
  38. LogUtil.error(TAG, ex.getMessage());
  39. }
  40. return Optional.of(path).toString();
  41. }
  42. }
  1. [
  2. {
  3. "title": "向日葵",
  4. "imageUrl": "entry/resources/base/media/xiangrikui.jpg",
  5. "pageNum": "1"
  6. },
  7. {
  8. "title": "海滩",
  9. "imageUrl": "entry/resources/base/media/haitan.jpg",
  10. "pageNum": "2"
  11. },
  12. {
  13. "title": "萧山城市",
  14. "imageUrl": "entry/resources/base/media/xiaoshan.jpg",
  15. "pageNum": "3"
  16. },
  17. {
  18. "title": "郁金香",
  19. "imageUrl": "entry/resources/base/media/yujinxiang.jpg",
  20. "pageNum": ""
  21. },
  22. {
  23. "title": "鸽子",
  24. "imageUrl": "entry/resources/base/media/gezi.jpg",
  25. "pageNum": ""
  26. }
  27. ]

预期效果:

        本文因为涉及到动态读取图片和内容稍微嫌的复杂,虽然例子并不复杂,因为是改造实话说开发过程中也遇到不少问题,而且本文原计划要实现能够在PageSlider的子页面中动态添加当前页码(如右图的1位置),但是因为实在不知道怎么获取当前页面的内容,最后用ToastDialog来实现了(即左侧图片下面页面所以提示),留个尾巴吧未来来实现,先继续往下走!

        改造例子的时候深深的感受到什么叫“眼高手低”,看代码、抄代码感觉一看都懂,一动手要不不知如何下手,要不就是改错,但别灰心,谁让是新手!

        只要不停下来,未来的路会更顺!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/229247?site
推荐阅读
相关标签
  

闽ICP备14008679号