当前位置:   article > 正文

【鸿蒙HarmonyOS开发】滑动菜单_ondragend animator

ondragend animator

先看下效果

目录

前言

UI布局部分

背景资源布局

Ability UI

Java 部分


前言

       实现滑动菜单我的想法是,菜单隐藏在屏幕之外。当监听到滑动事件时,判断滑动的方向与距离,根据滑动的速度改变前景组件的位置。当滑动结束时,要判断滑动停止的位置,如果停留的位置不在预期的原点或边缘要将前景的组件恢复到指定位置(这里需要运用简单的动画)。

        本来想写一个关于动画的文章,发现鸿蒙官方的文档就很简单易懂还有示例。大家可以先看一下官方的动画文档,动画开发指导

UI布局部分

        由于鸿蒙暂时没有圆角的布局,UI中的圆角和圆形都是通过graphic中的shape实现的,利用shape可以快速的实现圆角矩形、圆形和弧的几何图形,当然shape的用法不止这些。

背景资源布局

bg_contacts_component.xml 背景

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape
  3. xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4. ohos:shape="rectangle">
  5. <solid ohos:color="#FF8C8C8C"/>
  6. <corners ohos:radius="12vp"/>
  7. </shape>

bg_contacts_cancel.xml 背景

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape
  3. xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4. ohos:shape="oval">
  5. <solid ohos:color="#FFEFBD03"/>
  6. </shape>

bg_contacts_deldete.xml 背景

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape
  3. xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4. ohos:shape="oval">
  5. <solid ohos:color="#FFE20101"/>
  6. </shape>

Ability UI

       由于是横向滑动,菜单布局在前景布局的后面我们选用DirectionalLayout为主要布局,前景布局和菜单都放在其中。菜单的布局也选用DirectionalLayout布局,选择按钮在其中DirectionalLayout还有一点就是可以利用权重来指定其中组件的占比,特别适合做菜单等单元等分的布局。前景布局现实中可能要复杂很多,我们采用DependentLayout布局。

效果 

 layout 布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DirectionalLayout
  3. xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4. ohos:height="match_parent"
  5. ohos:id="$+id:dl_contacts_main"
  6. ohos:orientation="horizontal"
  7. ohos:width="match_parent">
  8. <DependentLayout
  9. ohos:height="80vp"
  10. ohos:id="$+id:dl_contacts"
  11. ohos:width="200vp">
  12. <Component
  13. ohos:background_element="$graphic:bg_contacts_component"
  14. ohos:bottom_margin="12vp"
  15. ohos:end_margin="12vp"
  16. ohos:height="match_parent"
  17. ohos:id="$+id:c_contacts"
  18. ohos:start_margin="12vp"
  19. ohos:top_margin="12vp"
  20. ohos:width="match_parent"/>
  21. </DependentLayout>
  22. <DirectionalLayout
  23. ohos:height="80vp"
  24. ohos:id="$+id:dtrl_contacts"
  25. ohos:orientation="horizontal"
  26. ohos:right_of="$id:dl_contacts"
  27. ohos:total_weight="2"
  28. ohos:width="160vp">
  29. <Text
  30. ohos:background_element="$graphic:bg_contacts_cancel"
  31. ohos:bottom_margin="12vp"
  32. ohos:end_margin="12vp"
  33. ohos:height="match_parent"
  34. ohos:id="$+id:t_contacts_cancel"
  35. ohos:start_margin="12vp"
  36. ohos:text="取消"
  37. ohos:text_alignment="center"
  38. ohos:text_color="#FFFFFF"
  39. ohos:text_size="18fp"
  40. ohos:top_margin="12vp"
  41. ohos:weight="1"
  42. ohos:width="0"/>
  43. <Text
  44. ohos:background_element="$graphic:bg_contacts_deldete"
  45. ohos:bottom_margin="12vp"
  46. ohos:end_margin="12vp"
  47. ohos:height="match_parent"
  48. ohos:id="$+id:t_contacts_delete"
  49. ohos:start_margin="12vp"
  50. ohos:text="删除"
  51. ohos:text_alignment="center"
  52. ohos:text_color="#FFFFFF"
  53. ohos:text_size="18fp"
  54. ohos:top_margin="12vp"
  55. ohos:weight="1"
  56. ohos:width="0"/>
  57. </DirectionalLayout>
  58. </DirectionalLayout>

Java 部分

这里包含三部分布局,最外层包含前景和菜单布局我们要移动的就是它、前景布局对点击拖动事件进行响应和菜单部分。

在 onStart() 中初始化布局

  1. private DirectionalLayout dependentLayoutMain;
  2. private DependentLayout dependentLayout;
  3. private DirectionalLayout directionalLayout;
  4. @Override
  5. protected void onStart(Intent intent) {
  6. ......
  7. int widthPx = (int) (getContext().getResourceManager().getDeviceCapability().width * AttrHelper.getDensity(this));
  8. // 前景布局
  9. dependentLayout = (DependentLayout) findComponentById(ResourceTable.Id_dl_contacts);
  10. dependentLayout.setWidth(widthPx);
  11. // 菜单
  12. directionalLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_dtrl_contacts);
  13. // 主容器
  14. dependentLayoutMain = (DirectionalLayout) findComponentById(ResourceTable.Id_dl_contacts_main);
  15. dependentLayoutMain.setWidth(widthPx + directionalLayout.getWidth());
  16. ......
  17. }

当UI具备交互后初始化点击拖动事件的监听,也就是在 onActive() 中。

实现拖动监听接口DraggedListener类需要重写其中的方法:

方法功能描述
onDragDown () 下拉事件不在我们本次的处理范围内
onDragStart () 拖拽开始我们需要在这里计算起始位置等初始信息
onDragUpdate( )拖动更新我们需要根据拖动的距离实时更改组件位置
onDragEnd () 拖拽结束我们需要在这里计算需要移动到的位置将组件继续移动到指定位置
onDragCancel ()拖动取消暂时不做处理,也可同结束事件

具体代码如下:

  1. @Override
  2. protected void onActive() {
  3. ......
  4. // 设置水平拖动监听
  5. dependentLayout.setDraggedListener(Component.DRAG_HORIZONTAL, new Component.DraggedListener() {
  6. // 拖动动作开始X坐标
  7. private int startX = 0;
  8. // 拖动动作开始时的前景坐标,确定移动方向
  9. private float dependentLayoutStartX = 0;
  10. // 背景组件长度
  11. private int directionalLayoutWidth = 0;
  12. // 背景移动最远位置
  13. private int distance = 0;
  14. @Override
  15. public void onDragDown(Component component, DragInfo dragInfo) {
  16. }
  17. @Override
  18. public void onDragStart(Component component, DragInfo dragInfo) {
  19. startX = dragInfo.startPoint.getPointXToInt();
  20. dependentLayoutStartX = dependentLayoutMain.getContentPositionX();
  21. directionalLayoutWidth = directionalLayout.getWidth();
  22. distance = -directionalLayoutWidth;
  23. HiLog.error(LABEL_LOG, "前景X坐标:" + dependentLayoutStartX +
  24. ";背景长度:" + directionalLayoutWidth +
  25. ";拖动开始位置:" + startX +
  26. ";背景移动最远位置:" + distance);
  27. }
  28. @Override
  29. public void onDragUpdate(Component component, DragInfo dragInfo) {
  30. // 拖动动作当前X坐标
  31. int upX = dragInfo.updatePoint.getPointXToInt();
  32. // 拖动距离
  33. int upDataX = upX - startX;
  34. HiLog.error(LABEL_LOG, "拖动距离:" + upDataX);
  35. // 前景子组件当时的位置
  36. float dependentLayoutX = dependentLayoutMain.getContentPositionX();
  37. // 预定位置
  38. float position = dependentLayoutX + upDataX;
  39. if (position < distance) {
  40. position = distance;
  41. }
  42. if (position > 0) {
  43. position = 0;
  44. }
  45. dependentLayoutMain.setContentPositionX(position);
  46. }
  47. @Override
  48. public void onDragEnd(Component component, DragInfo dragInfo) {
  49. HiLog.error(LABEL_LOG, "拖动结束");
  50. float nowX = dependentLayoutMain.getContentPositionX();
  51. // 由于不是拖动,添加动画使移动流畅
  52. AnimatorProperty animatorProperty = new AnimatorProperty();
  53. animatorProperty
  54. .setTarget(dependentLayoutMain)
  55. .setLoopedCount(0)
  56. .setDuration(200)
  57. .setCurveType(Animator.CurveType.LINEAR);
  58. // 设定以2/5为分界点
  59. int divide = directionalLayoutWidth / 3;
  60. if (dependentLayoutStartX == 0) {
  61. // 从原点出发
  62. if (nowX < -divide) {
  63. animatorProperty.moveFromX(nowX).moveToX(distance);
  64. } else {
  65. animatorProperty.moveFromX(nowX).moveToX(0);
  66. }
  67. } else if (dependentLayoutStartX == distance) {
  68. // 从隐藏点出发
  69. if (distance - nowX > -divide) {
  70. animatorProperty.moveFromX(nowX).moveToX(distance);
  71. } else {
  72. animatorProperty.moveFromX(nowX).moveToX(0);
  73. }
  74. }
  75. animatorProperty.start();
  76. }
  77. @Override
  78. public void onDragCancel(Component component, DragInfo dragInfo) {
  79. //HiLog.error(LABEL_LOG, "拖动取消");
  80. }
  81. });
  82. ......
  83. }

到此拖动菜单就结束了,也可以举一反三下拉刷新之类的处理! 

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

闽ICP备14008679号