0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

HarmonyOS 中的几个自定义控件介绍

OpenHarmony技术社区 来源:HarmonyOS技术社区 作者:HarmonyOS技术社区 2022-01-04 13:49 次阅读

HarmonyOS 开发自定义组件目前还不是很丰富,在开发过程中常常会有一些特殊效果的组件,这就需要我们额外花一些时间实现。

这里给大家提供了一个 BottomSheet 上拉抽屉的组件,同时通过这个组件示例讲解一下 HarmonyOS 中的几个自定义控件用到的知识,分享一下自己自定义组件的思路。

效果演示如下图:

实现思路

①布局设计

选择的是相对布局,蒙层区来改变内容区随着抽屉的位置调节透明度。如图 1:

②手势判断

先得出 Component 在屏幕的上下左右的坐标,然后手指的坐标是否在 Component 内。

/**
*(x,y)是否在view的区域内
*
*@paramcomponent
*@paramx
*@paramy
*@return
*/
privatebooleanisTouchPointInComponent(Componentcomponent,floatx,floaty){
int[]locationOnScreen=component.getLocationOnScreen();
intleft=locationOnScreen[0];
inttop=locationOnScreen[1];
intright=left+component.getEstimatedWidth();
intbottom=top+component.getEstimatedHeight();
booleaninY=y>=top&&y<= bottom;
    boolean inX = x >=left&&x<= right;
    return inY && inX;
}

③抽屉偏移

步骤如下:

这里采用的是整个 component 对 Touch 事件的监听。

手指按下的判断是否在抽屉上,然后记录当前触摸 y 坐标。

移动是算出偏移量 offY。

setTouchEventListener(newTouchEventListener(){
@Override
publicbooleanonTouchEvent(Componentcomponent,TouchEventtouchEvent){
HiLog.info(logLabel,"onTouchEventaction:"+touchEvent.getAction());
switch(touchEvent.getAction()){
caseTouchEvent.PRIMARY_POINT_DOWN:
marginBottom=directionalLayout.getMarginBottom();
MmiPointposition=touchEvent.getPointerScreenPosition(0);
if(isTouchPointInComponent(directionalLayout,position.getX(),position.getY())){
dragStartPointY=touchEvent.getPointerPosition(0).getY();
returntrue;
}
break;
caseTouchEvent.PRIMARY_POINT_UP:
onTouchUp();
break;
caseTouchEvent.POINT_MOVE:
floaty=touchEvent.getPointerPosition(0).getY();
floatoffY=dragStartPointY-y;
setDrawerMarginBottom((int)offY);
break;
}
returnfalse;
}
});

根据偏移量改变抽屉的位置:

privatevoidsetDrawerMarginBottom(intoffY){
intbottom=marginBottom+offY;
if(bottom>0){
bottom=0;
listContainer.setEnabled(true);
}

if(bottom< -H / 2) {
        bottom = -H / 2;
    }
    HiLog.info(logLabel, "setDrawerMarginBottom bottom:" + bottom);

    float alpha = (0.5f - Math.abs((float) bottom / (float) H)) * 0.5f;
    HiLog.info(logLabel, "setDrawerMarginBottom alpha:" + alpha);
    bgComponent.setAlpha(alpha);
    directionalLayout.setMarginBottom(bottom);
}

④事件冲突解决

首先发现不能按安卓的思想去处理:

HarmonyOS 中是没有事件分发这概念的,只有事件消费,ListContainer 先拿到事件,然后是抽屉布局。

根据抽屉在完全展开的位置,在 ListContainer 收到触摸事件时,把 ListContainer 事件静止掉,不让其消费。

待抽屉完全展开时,解开 ListContainer 的事件。

listContainer.setTouchEventListener(newTouchEventListener(){
@Override
publicbooleanonTouchEvent(Componentcomponent,TouchEventtouchEvent){
marginBottom=directionalLayout.getMarginBottom();
booleandrag_down=listContainer.canScroll(DRAG_DOWN);
booleandrag_UP=listContainer.canScroll(DRAG_UP);
if(marginBottom==0&&drag_down){
component.setEnabled(true);
returntrue;
}
component.setEnabled(false);
returnfalse;
}
});

这里是抽屉容器定位抽屉时,判断是否打开 ListContainer 事件。

privatevoidsetDrawerMarginBottom(intoffY){
intbottom=marginBottom+offY;
if(bottom>0){
bottom=0;
listContainer.setEnabled(true);
}
.......
}

⑤背景亮暗变化

首先我们 XML 布局参照上述布局设计—如图 1。背景亮暗的改变根据抽屉位置按比例设置蒙层的透明度。

floatalpha=(0.5f-Math.abs((float)bottom/(float)H))*0.5f;
bgComponent.setAlpha(alpha);

⑥回弹效果

运用到了数值动画,在手势抬起时,判断上下临界点决定动画的上下。

privatevoidonTouchUp(){
HiLog.info(logLabel,"onTouchUp");
createAnimator();
}

privatevoidcreateAnimator(){
marginBottom=directionalLayout.getMarginBottom();
HiLog.info(logLabel,"createAnimatormarginBottom:"+marginBottom);
//创建数值动画对象
AnimatorValueanimatorValue=newAnimatorValue();
//动画时长
animatorValue.setDuration(300);
//播放前的延迟时间
animatorValue.setDelay(0);
//循环次数
animatorValue.setLoopedCount(0);
//动画的播放类型
animatorValue.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
//设置动画过程
animatorValue.setValueUpdateListener(newAnimatorValue.ValueUpdateListener(){
@Override
publicvoidonUpdate(AnimatorValueanimatorValue,floatvalue){
HiLog.info(logLabel,"createAnimatorvalue:"+value);
if(marginBottom>-H/4){//top
HiLog.info(logLabel,"createAnimatortop:"+value);
setDrawerBottomOrToP((int)(marginBottom-value*marginBottom));
}else{//bottom
HiLog.info(logLabel,"createAnimatorbottom:"+value);
inttop=H/2+marginBottom;
setDrawerBottomOrToP((int)(marginBottom-value*top));
}
}
});
//开始启动动画
animatorValue.start();
}

privatevoidsetDrawerBottomOrToP(intbottom){
if(bottom>0){
bottom=0;
listContainer.setEnabled(true);
}

if(bottom< -H / 2) {
        bottom = -H / 2;
    }

    float alpha = (0.5f - Math.abs((float) bottom / (float) H)) * 0.5f;

    bgComponent.setAlpha(alpha);
    directionalLayout.setMarginBottom(bottom);
}

总结

自定义组件步骤及思考方向:

明确父容器和子 view 的关系。

如何绘制一般采用以下三个方向:已有控件组合;采用画布绘制等;继承控件扩展功能。

若涉及到触摸事件,需要考虑如何处理事件分发与消费。

动画选择,可根据需求选择合适动画(本文采用属性动画)。

计算问题,复杂的需要丰富的数学知识。

性能问题(过度计算,重复绘制,对象重复创建)。

代码地址:

https://gitee.com/guangdong-wangduoyu/touch-event-demo

原文标题:HarmonyOS“上拉抽屉”效果实现!

文章出处:【微信公众号:HarmonyOS技术社区】欢迎添加关注!文章转载请注明出处。

审核编辑:彭菁

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 安卓
    +关注

    关注

    5

    文章

    2120

    浏览量

    56990
  • HarmonyOS
    +关注

    关注

    79

    文章

    1967

    浏览量

    29997

原文标题:HarmonyOS“上拉抽屉”效果实现!

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    LabVIEW如何制作漂亮的自定义控件(按钮)

    :使用LabVIEW制作自定义控件1、打开LabVIEW8.6,新建【自定义控件】,如图:2、在前面板添加
    发表于 01-06 11:22

    LabVIEW自定义控件

    首先看下面的 这个例 子:这个程序可以做出一些 动画的 效果,其实实现起来是十分简单的。主要的工作就是将布尔控件和滑动杆控件做了自定义 的处理 。我们在具体的程序,也可以使用
    发表于 01-07 10:57

    LabVIEW自定义控件的好处是什么?

    如上图是一个状态机的获取队列引用。最左边是枚举的自定义类型控件。如果不用自定义枚举控件只用枚举应该也是同样的效果。那为什么要用自定义枚举
    发表于 05-13 07:57

    2.1 sc界面-自定义控件

    自定义控件很多时候在前面板上都需要自定义控件,我们介绍下操作步骤:第一步:新建一个自定义
    发表于 08-29 06:45

    LabVIEW制作的漂亮自定义控件

    LabVIEW制作的漂亮自定义控件文档介绍
    发表于 07-29 16:25

    讲解一下HarmonyOS几个自定义组件用到的知识

    开发自定义组件目前还不是很丰富,在开发过程中常常会有一些特殊效果的组件,这就需要我们额外花一些时间实现,这里给大家提供了一个 BottomSheet 上拉抽屉的组件,同时通过这个组件示例讲解一下 HarmonyOS
    发表于 03-16 16:05

    HarmonyOS实现自定义控件的过程分享

    ,100圆的绘图,为设置的笔画}4.在xml布局引用自定义控件:<?xml 版本="1.0" 编码="utf-8"
    发表于 05-07 11:48

    C#教程之自定义水晶按钮控件

    C#教程之自定义水晶按钮控件,很好的C#资料,快来学习吧。
    发表于 04-20 10:50 5次下载

    如何在LabVIEW实现自定义控件

    本文档的主要内容详细介绍的是如何在LabVIEW实现自定义控件
    发表于 01-14 17:17 48次下载
    如何在LabVIEW<b class='flag-5'>中</b>实现<b class='flag-5'>自定义</b><b class='flag-5'>控件</b>

    鸿蒙系统如何设置自定义下拉刷新控件

    Ohos-MaterialRefreshLayout 是一个自定义 Material 风格下拉刷新控件,支持设置水波纹效果,支持下拉刷新侵入式和非侵入式,初始化自动刷新及上滑加载更多,支持刷新头部
    的头像 发表于 09-13 09:24 3297次阅读

    C#自定义开关按钮控件(WINFORM)

    C#自定义开关按钮控件(WINFORM)转载于:https://www.cnblogs.com/macT/p/10212711.html
    发表于 10-21 18:36 17次下载
    C#<b class='flag-5'>自定义</b>开关按钮<b class='flag-5'>控件</b>(WINFORM)

    精美的TF自定义控件源文件合集

    精美的自定义控件源文件100+,满足优秀界面的需求,分享给大家。
    发表于 01-13 14:13 31次下载

    自定义屏幕图案解锁控件教程案例

    一个自定义屏幕图案解锁控件,该库使您可以轻松,快速地在应用程序实现模式锁定机制。它非常易于使用,并且提供了许多自定义选项,可以更改此视图的功能和外观以满足您的需求。它还支持RxJav
    发表于 04-11 09:40 1次下载

    labview自定义控件

    labview自定义精美控件
    发表于 05-15 16:46 17次下载

    labview超快自定义控件制作和普通自定义控件制作

    labview超快自定义控件制作和普通自定义控件制作
    发表于 08-21 10:32 12次下载