文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

鸿蒙HarmonyOS官方模板学习 之 Grid Ability(Java)

2024-12-03 02:55

关注

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

Grid Ability(Java)

介绍

使用Java语言开发,用于Phone设备的Feature Ability模板,使用XML布局,显示内容为两部分网格表,网格每行显示4个项目,网格内元素可进行拖拽排序。

搭建环境

安装DevEco Studio,详情请参考DevEco Studio下载。

设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

代码结构解读

注意:'#'代表注释

后台功能

  1. gridabilityjava 
  2.      │  MainAbility.java 
  3.      │  MyApplication.java 
  4.      │ 
  5.      ├─component 
  6.      │      DragLayout.java #自定义的拖拽功能组件 
  7.      │      GridView.java #自定义的Grid视图组件,extends TableLayout 
  8.      │ 
  9.      ├─model 
  10.      │      GridItemInfo.java #Grid item 模型 
  11.      │ 
  12.      ├─provider 
  13.      │      GridAdapter.java #给Grid提供实例化好的item 组件列表;提供了计算单个item的宽度的方法 
  14.      │ 
  15.      ├─slice 
  16.      │      MainAbilitySlice.java #主能力页,负责实例化自定义的DragLayout拖拽组件 
  17.      │ 
  18.      └─utils 
  19.              AppUtils.java #工具类,提供了从element资源中中获取value;获取屏幕的坐标的方法 

这是几个java类之间的关系


页面资源

  1. resources 
  2.     ├─base 
  3.     │  ├─element 
  4.     │  │      color.json 
  5.     │  │      float.json 
  6.     │  │      integer.json 
  7.     │  │      string.json 
  8.     │  │ 
  9.     │  ├─graphic 
  10.     │  │      background_bottom_button.xml  #页面底部按钮形状 
  11.     │  │      background_bottom_layout.xml  #页面底部布局形状 
  12.     │  │      background_item_active_button.xml #grid item 激活形状 
  13.     │  │      background_item_button.xml    #grid item 默认形状 
  14.     │  │      background_table_layout_down.xml  #下面的 grid 形状 
  15.     │  │      background_table_layout_up.xml    #上面的 grid 形状 
  16.     │  │ 
  17.     │  ├─layout 
  18.     │  │      ability_main.xml #主显示页面 
  19.     │  │      app_bar_layout.xml #app工具栏布局页面 
  20.     │  │      grid_item.xml #单个grid item布局页面 
  21.     │  │ 
  22.     │  ├─media 
  23.     │  │      5G.png 
  24.     │  │      back.png 
  25.     │  │      back_white.png 

页面布局

ability_main.xml #主显示页

此页面由DirectionalLayout、StackLayout、DependentLayout 布局构成,整体布局是上下布局。

上面时app工具栏,使用了StackLayout布局,通过includ标签引入到主页面。

下面是支持拖拽的GridView,由DependentLayout 和DirectionalLayout布局组成,使用的组件有ScrollView、GridView、Text、Button、Image。


app_bar_layout.xml #app工具栏布局页面


grid_item.xml #单个grid item布局页面


后台逻辑

1.初始化上面的GridView

先构建item模拟数据列表,将构建好的数据传递给GridAdapter 初始化item组件列表,通过GridView.setAdapter方法给每个item组件绑定长按事件,并设置GridView的TAG属性(TAG就是指上面的GridView还是下面的GridView)。

  1.  
  2. private void initUpListItem() { 
  3.     //构建item模拟数据列表 
  4.     List upperItemList = new ArrayList<>(); 
  5.     for (int i = 0; i < UP_ITEM_COUNT; i++) { 
  6.         int iconId = icons[i]; 
  7.         String text = texts[i]; 
  8.         upperItemList.add(new GridItemInfo(text, iconId, UP_GRID_TAG)); 
  9.     } 
  10.  
  11.     GridView gridView = (GridView) slice.findComponentById(ResourceTable.Id_grid_view_up); 
  12.     //将构建好的数据传递给GridAdapter 初始化item组件列表 
  13.     GridAdapter adapter = new GridAdapter(slice.getContext(), upperItemList); 
  14.  
  15.     //通过GridView.setAdapter方法给每个item组件绑定长按事件 
  16.     gridView.setAdapter(adapter, longClickListener); 
  17.     //设置GridView的TAG属性 
  18.     gridView.setTag(UP_GRID_TAG); 

2.初始化下面的GridView

逻辑同上

  1.  
  2. private void initDownListItem() { 
  3.     String itemText = AppUtils.getStringResource(slice.getContext(), ResourceTable.String_grid_item_text); 
  4.     List lowerItemList = new ArrayList<>(); 
  5.     for (int i = 0; i < DOWN_ITEM_COUNT; i++) { 
  6.         //随意取的图标 
  7.         int iconId = icons[i + 5]; 
  8.         String text = texts[i + 5]; 
  9.         lowerItemList.add(new GridItemInfo(text, iconId, DOWN_GRID_TAG)); 
  10.     } 
  11.  
  12.     if (slice.findComponentById(ResourceTable.Id_grid_view_down) instanceof GridView) { 
  13.         GridView gridView = (GridView) slice.findComponentById(ResourceTable.Id_grid_view_down); 
  14.         GridAdapter adapter = new GridAdapter(slice.getContext(), lowerItemList); 
  15.         gridView.setAdapter(adapter, longClickListener); 
  16.         gridView.setTag(DOWN_GRID_TAG); 
  17.     } 

 3.初始化底部的按钮

这个地方做了一个屏幕适配,就是根据屏幕的宽度、边距来设置按钮的宽度,

同时添加了按钮的监听事件,点击按钮 关闭当前Ability。

  1.  
  2. private void initBottomItem() { 
  3.     int screenWidth = AppUtils.getScreenInfo(slice.getContext()).getPointXToInt(); 
  4.     //计算按钮宽度 
  5.     int buttonWidth = (screenWidth - AttrHelper.vp2px(80, slice.getContext())) / 2; 
  6.  
  7.     Component leftButton = slice.findComponentById(ResourceTable.Id_bottom_left_button); 
  8.     leftButton.setWidth(buttonWidth); 
  9.     //关闭Ability 
  10.     leftButton.setClickedListener(component -> slice.terminateAbility()); 
  11.  
  12.     Component rightButton = slice.findComponentById(ResourceTable.Id_bottom_right_button); 
  13.     rightButton.setWidth(buttonWidth); 
  14.     //关闭Ability 
  15.     rightButton.setClickedListener(component -> slice.terminateAbility()); 
  16.  

4.初始化app工具栏

这个没做什么,似乎是想根据本地化信息,设置返回箭头的方向,因为有的语言是从右往左看的。

  1.  
  2. private void initAppBar() { 
  3.     if (TextTool.isLayoutRightToLeft(Locale.getDefault())) { 
  4.         Image appBackImg = (Image) slice.findComponentById(ResourceTable.Id_left_arrow); 
  5.         appBackImg.setRotation(180); 
  6.     } 

5.初始化监听事件

包括返回按钮的返回事件、ScrollView的touch事件。

touch事件包含大量的细节操作,如拖拽时有一个阴影效果,滚动条的处理,拖拽交换结束的处理,过渡效果,上下grid 有效区域的计算,拖拽完成将拖拽的组件添加到对应grid的操作等,参照着拿来用吧。

  1.  
  2. private void initEventListener() { 
  3.  
  4.     //‘返回按钮’的监听事件 
  5.     if (slice.findComponentById(ResourceTable.Id_left_arrow) instanceof Image) { 
  6.         Image backIcon = (Image) slice.findComponentById(ResourceTable.Id_left_arrow); 
  7.         // 
  8.         backIcon.setClickedListener(component -> slice.terminateAbility()); 
  9.     } 
  10.  
  11.     //ScrollView的 Touch事件监听,拿来用就可以了 
  12.     scrollView.setTouchEventListener( 
  13.             (component, touchEvent) -> { 
  14.                 //按下屏幕的位置 
  15.                 MmiPoint downScreenPoint = touchEvent.getPointerScreenPosition(touchEvent.getIndex()); 
  16.  
  17.                 switch (touchEvent.getAction()) { 
  18.                     //表示第一根手指触摸屏幕。这表示交互的开始 
  19.                     case TouchEvent.PRIMARY_POINT_DOWN: 
  20.                         currentDragX = (int) downScreenPoint.getX(); 
  21.                         currentDragY = (int) downScreenPoint.getY(); 
  22.                         //获取指针索引相对于偏移位置的 x 和 y 坐标。 
  23.                         MmiPoint downPoint = touchEvent.getPointerPosition(touchEvent.getIndex()); 
  24.                         scrollViewTop = (int) downScreenPoint.getY() - (int) downPoint.getY(); 
  25.                         scrollViewLeft = (int) downScreenPoint.getX() - (int) downPoint.getX(); 
  26.                         return true
  27.                     //表示最后一个手指从屏幕上抬起。这表示交互结束 
  28.                     case TouchEvent.PRIMARY_POINT_UP: 
  29.                         //恢复下面grid的描述 
  30.                         changeTableLayoutDownDesc(ResourceTable.String_down_grid_layout_desc_text); 
  31.                     case TouchEvent.CANCEL: 
  32.                         if (isViewOnDrag) { 
  33.                             selectedView.setScale(1.0f, 1.0f); 
  34.                             selectedView.setAlpha(1.0f); 
  35.                             selectedView.setVisibility(Component.VISIBLE); 
  36.                             isViewOnDrag = false
  37.                             isScroll = false
  38.                             return true
  39.                         } 
  40.                         break; 
  41.  
  42.                     //表示手指在屏幕上移动 
  43.                     case TouchEvent.POINT_MOVE: 
  44.                         if (!isViewOnDrag) { 
  45.                             break; 
  46.                         } 
  47.                         int pointX = (int) downScreenPoint.getX(); 
  48.                         int pointY = (int) downScreenPoint.getY(); 
  49.  
  50.  
  51.                         this.exchangeItem(pointX, pointY); 
  52.  
  53.                         if (UP_GRID_TAG.equals(selectedView.getTag())) { 
  54.                             this.swapItems(pointX, pointY); 
  55.                         } 
  56.                         this.handleScroll(pointY); 
  57.                         return true
  58.                 } 
  59.                 return false
  60.             } 
  61.     ); 
  62.  

复制归纳总结

1.自定义组件在构造函数中传递slice

这样的目的是便于获取页面的其它组件。

  1. Component itemLayout=LayoutScatter.getInstance(slice.getContext()) 
  2. .parse(ResourceTable.Layout_grid_item, nullfalse); 

需要注意的是slice指代的是页面,但是自定义组件往往是有自己的布局文件的,一般不在slice中,所以不要通过slice获取自定义组件的子组件,获取不到,不过可以通过LayoutScatter获取

  1. //错误的方式 
  2. Component gridItem=  slice.findComponentById(ResourceTable.Layout_grid_item); 
  3. //正确的方式 
  4. Component gridItem = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_grid_item, nullfalse); 

2.单位转换vp2px

java组件对象宽高、边距的单位默认时px,

从element中获取的值需要进行单位转换,可以使用AttrHelper.vp2px 将vp转换为px。

  1. if (gridItem.findComponentById(ResourceTable.Id_grid_item_text) instanceof Text) { 
  2.     Text textItem = (Text) gridItem.findComponentById(ResourceTable.Id_grid_item_text); 
  3.     textItem.setText(item.getItemText()); 
  4.     textItem.setTextSize(AttrHelper.fp2px(10, context)); 

3.子组件的获取

获取一个组件对象后,可以使用该组件对象的findComponentById方法继续获取内部的子组件

  1. Component gridItem = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_grid_item, nullfalse); 
  2. Image imageItem = (Image) gridItem.findComponentById(ResourceTable.Id_grid_item_image); 

4.TableLayout的使用

TableLayout继承自ComponentContainer,提供用于在带有表格的组件中排列组件的布局。

TableLayout 提供了用于对齐和排列组件的接口,以在带有表格的组件中显示组件。 排列方式、行列数、元件位置均可配置。

例如 removeAllComponents();可以用来清除 ComponentContainer 管理的所有组件,addComponent 用来将组件添加到ComponentContainer 容器中。示例中GridView就是继承自TableLayout。

  1.  
  2. void setAdapter(GridAdapter adapter, LongClickedListener longClickedListener) { 
  3.     //清除 ComponentContainer 管理的所有组件 
  4.     removeAllComponents(); 
  5.     //遍历item组件列表 
  6.     for (int i = 0; i < adapter.getComponentList().size(); i++) { 
  7.         //为组件中的长按事件注册一个监听器(组件被点击并按住) 
  8.         adapter.getComponentList().get(i).setLongClickedListener(longClickedListener); 
  9.         //将组件添加到容器中 
  10.         addComponent(adapter.getComponentList().get(i)); 
  11.     } 

效果展示

示例代码模拟了一下手机控制中心,编辑快捷开关的效果

原效果模拟效果

文章相关附件可以点击下面的原文链接前往下载

原文链接:https://harmonyos.51cto.com/posts/4776

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

来源:鸿蒙社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯