【鸿蒙开发】滑动菜单

ZJKJTL ZJKJTL 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

 先看下效果

 

目录

前言

UI布局部分

背景资源布局

Ability UI

Java 部分


前言

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

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

UI布局部分

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

背景资源布局

bg_contacts_component.xml 背景

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle">

    <solid ohos:color="#FF8C8C8C"/>

    <corners ohos:radius="12vp"/>
</shape>

bg_contacts_cancel.xml 背景

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="oval">

    <solid ohos:color="#FFEFBD03"/>
</shape>

bg_contacts_deldete.xml 背景

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="oval">

    <solid ohos:color="#FFE20101"/>
</shape>

Ability UI

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

效果 

 layout 布局

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:id="$+id:dl_contacts_main"
    ohos:orientation="horizontal"
    ohos:width="match_parent">

    <DependentLayout
        ohos:height="80vp"
        ohos:id="$+id:dl_contacts"
        ohos:width="200vp">

        <Component
            ohos:background_element="$graphic:bg_contacts_component"
            ohos:bottom_margin="12vp"
            ohos:end_margin="12vp"
            ohos:height="match_parent"
            ohos:id="$+id:c_contacts"
            ohos:start_margin="12vp"
            ohos:top_margin="12vp"
            ohos:width="match_parent"/>

    </DependentLayout>

    <DirectionalLayout
        ohos:height="80vp"
        ohos:id="$+id:dtrl_contacts"
        ohos:orientation="horizontal"
        ohos:right_of="$id:dl_contacts"
        ohos:total_weight="2"
        ohos:width="160vp">

        <Text
            ohos:background_element="$graphic:bg_contacts_cancel"
            ohos:bottom_margin="12vp"
            ohos:end_margin="12vp"
            ohos:height="match_parent"
            ohos:id="$+id:t_contacts_cancel"
            ohos:start_margin="12vp"
            ohos:text="取消"
            ohos:text_alignment="center"
            ohos:text_color="#FFFFFF"
            ohos:text_size="18fp"
            ohos:top_margin="12vp"
            ohos:weight="1"
            ohos:width="0"/>

        <Text
            ohos:background_element="$graphic:bg_contacts_deldete"
            ohos:bottom_margin="12vp"
            ohos:end_margin="12vp"
            ohos:height="match_parent"
            ohos:id="$+id:t_contacts_delete"
            ohos:start_margin="12vp"
            ohos:text="删除"
            ohos:text_alignment="center"
            ohos:text_color="#FFFFFF"
            ohos:text_size="18fp"
            ohos:top_margin="12vp"
            ohos:weight="1"
            ohos:width="0"/>
    </DirectionalLayout>

</DirectionalLayout>

Java 部分

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

在 onStart() 中初始化布局

private DirectionalLayout dependentLayoutMain;
private DependentLayout dependentLayout;
private DirectionalLayout directionalLayout;

@Override
protected void onStart(Intent intent) {
    ......
    int widthPx = (int) (getContext().getResourceManager().getDeviceCapability().width * AttrHelper.getDensity(this));

    // 前景布局
    dependentLayout = (DependentLayout) findComponentById(ResourceTable.Id_dl_contacts);
    dependentLayout.setWidth(widthPx);

    // 菜单
    directionalLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_dtrl_contacts);

    // 主容器
    dependentLayoutMain = (DirectionalLayout) findComponentById(ResourceTable.Id_dl_contacts_main);
    dependentLayoutMain.setWidth(widthPx + directionalLayout.getWidth());

    ......
}

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

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

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

具体代码如下:

    @Override
    protected void onActive() {
        ......

        // 设置水平拖动监听
        dependentLayout.setDraggedListener(Component.DRAG_HORIZONTAL, new Component.DraggedListener() {
            // 拖动动作开始X坐标
            private int startX = 0;
            // 拖动动作开始时的前景坐标,确定移动方向
            private float dependentLayoutStartX = 0;
            // 背景组件长度
            private int directionalLayoutWidth = 0;
            // 背景移动最远位置
            private int distance = 0;

            @Override
            public void onDragDown(Component component, DragInfo dragInfo) {

            }

            @Override
            public void onDragStart(Component component, DragInfo dragInfo) {
                
                startX = dragInfo.startPoint.getPointXToInt();
                
                dependentLayoutStartX = dependentLayoutMain.getContentPositionX();
                
                directionalLayoutWidth = directionalLayout.getWidth();

                
                distance = -directionalLayoutWidth;

                HiLog.error(LABEL_LOG, "前景X坐标:" + dependentLayoutStartX +
                        ";背景长度:" + directionalLayoutWidth +
                        ";拖动开始位置:" + startX +
                        ";背景移动最远位置:" + distance);
            }

            @Override
            public void onDragUpdate(Component component, DragInfo dragInfo) {
                // 拖动动作当前X坐标
                int upX = dragInfo.updatePoint.getPointXToInt();
                // 拖动距离
                int upDataX = upX - startX;
                HiLog.error(LABEL_LOG, "拖动距离:" + upDataX);
                // 前景子组件当时的位置
                float dependentLayoutX = dependentLayoutMain.getContentPositionX();

                // 预定位置
                float position = dependentLayoutX + upDataX;

                if (position < distance) {
                    position = distance;
                }

                if (position > 0) {
                    position = 0;
                }

                dependentLayoutMain.setContentPositionX(position);
            }

            @Override
            public void onDragEnd(Component component, DragInfo dragInfo) {
                HiLog.error(LABEL_LOG, "拖动结束");
                float nowX = dependentLayoutMain.getContentPositionX();

                // 由于不是拖动,添加动画使移动流畅
                AnimatorProperty animatorProperty = new AnimatorProperty();
                animatorProperty
                        .setTarget(dependentLayoutMain)
                        .setLoopedCount(0)
                        .setDuration(200)
                        .setCurveType(Animator.CurveType.LINEAR);


                // 设定以2/5为分界点
                int divide = directionalLayoutWidth / 3;
                if (dependentLayoutStartX == 0) {
                    // 从原点出发
                    if (nowX < -divide) {
                        animatorProperty.moveFromX(nowX).moveToX(distance);
                    } else {
                        animatorProperty.moveFromX(nowX).moveToX(0);
                    }
                } else if (dependentLayoutStartX == distance) {
                    // 从隐藏点出发
                    if (distance - nowX > -divide) {
                        animatorProperty.moveFromX(nowX).moveToX(distance);
                    } else {
                        animatorProperty.moveFromX(nowX).moveToX(0);
                    }
                }

                animatorProperty.start();
            }

            @Override
            public void onDragCancel(Component component, DragInfo dragInfo) {
                //HiLog.error(LABEL_LOG, "拖动取消");
            }
        });

        ......
    }

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

...全文

相关推荐

android studio开发app项目:鸿蒙滑动菜单,鸿蒙的第三方组件适配移植

项目介绍 编程语言:Java SlidingMenu是一个滑动菜单组件,当用户使用时,菜单栏隐藏在手机屏幕的左侧或右侧, 通过左滑或者右滑出现导航菜单栏,既节省了主屏幕的空间,也方便用户操作,在很多主流APP中都有广泛的应用。 安装教程 下载har包library-debug.har。 启动 DevEco Studio,将下载的har包,导入工程目录“entry->libs”下。 在moudle级别下的build.gradle文件中添加依赖,在dependences标签中增加对libs目录下jar包的引用。 dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) …… } 在sdk5,DevEco Studio2.1 beta3下项目可直接运行 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下 使用说明 新建一个项目,在entry下的MainAbilitySlice中通过import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu即可对滑动菜单进行设置和使用。 使用样例如下: public class MainAbilitySlice extends AbilitySlice { @Override protected void onStart(Intent intent) { super.onStart(intent); //初始化一个directionalLayout(后面attachToAbility会用到,用来获取页面展示的根节点) Direc

程序员老冯头

鸿蒙版瑞幸咖啡开发日记[源码]

本文详细介绍了鸿蒙版瑞幸咖啡APP的首页布局设计过程,包括整体布局思路和三大模块的开发。首先,整体布局采用DependentLayout,分为顶部的信息栏、中间的菜单栏和底部的导航栏。信息栏和导航栏固定不动,菜单栏可滑动。接着,文章详细讲解了头部信息栏的开发,包括地址信息、位置信息和自提选项的布局设计。中间菜单栏分为左右两部分,左侧为一级分类菜单,右侧为二级分类菜单,均采用ScrollView组件实现滑动效果。文章还提供了多个布局文件的代码示例,如一级分类菜单模板、右侧大分类模板和咖啡模板。最后,作者记录了开发过程中遇到的Bug,并提醒开发者注意ScrollView的宽高设置问题。

7h6j5k4l3

华为鸿蒙HarmonyOS开发者资料大全.7z

鸿蒙开发者小白必看,华为鸿蒙HarmonyOS开发者资料大全

Jason–json

华为鸿蒙系统HarmonyOS学习之鸿蒙开发环境搭建

鸿蒙操作系统,华为鸿蒙系统HarmonyOS学习之鸿蒙开发环境搭建

zz_ll9023

HarmonyOS开发文档(一)_鸿蒙学堂.pdf

华为鸿蒙操作系统学习资料,文章介绍了HarmonyOS的开发的知识,适合深入了解、学习鸿蒙系统开发者参考使用。

客啦啦智鉴
评论 1
收藏 已收藏
分享
返回顶部