文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

HarmonyOS自定义组件之仿微信朋友圈主页

2024-12-02 18:25

关注

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

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

https://harmonyos.51cto.com

前言

在实际开发过程中,我们经常会遇到一些系统原有组件无法满足的情况,而HarmonyOS提供了自定义组件的方式,我们使用自定义组件来满足项目需求。自定义组件是由开发者定义的具有一定特性的组件,通过扩展 Component 或其子类实现,可以精确控制屏幕元素的外观,实现开发者想要达到的效果,也可响应用户的点击、触摸、长按等操作。下面通过自定义一个仿微信朋友圈主页的组件来了解一下自定义组件的过程。

简述

首先关于自定义组件,一般遵循以下几个方式

首先,创建一个继承 Component 或其子类的自定义组件类,并添加构造方法,如 MyComponent 。

实现 Component.EstimateSizeListener 接口,在 onEstimateSize 方法中进行组件测量,并通过 setEstimatedSize 方法通知组件。

自定义组件测量出的大小需通过 setEstimatedSize 通知组件,并且必须返回true使测量值生效。setEstimatedSize 方法的入参携带模式信息,可使用 Component.EstimateSpec.getChildSizeWithMode 方法进行拼接。

测量模式

自定义xml属性,通过构造方法中携带的参数 attrSet,可以获取到在 xml 中配置的属性值,并应用在该自定义组件中。

实现 Component.DrawTask 接口,在 onDraw 方法中执行绘制任务,该方法提供的画布 Canvas,可以精确控制屏幕元素的外观。在执行绘制任务之前,需要定义画笔 Paint。

实现 Component.TouchEventListener 或其他事件的接口,使组件可响应用户输入。

在 xml 文件中创建并配置自定义组件。

在 HarmonyOS 中 Component 是视图的父类,既然组件都是继承 Component 来实现的,那么我们也可以继承它来实现我们想要的视图了,根据具体流程,我们按照示例代码来了解一下大致流程:

创建自定义布局

  1. ... 
  2. public class MyComponent extends Component implements Component.DrawTask,Component.EstimateSizeListener { 
  3.     private Paint paint; 
  4.     private Paint paintText; 
  5.  
  6.     private PixelMap bigImage; 
  7.  
  8.     private PixelMap smallImage; 
  9.  
  10.     public MyComponent(Context context) { 
  11.         this(context, null); 
  12.     } 
  13.  
  14.     public MyComponent(Context context, AttrSet attrSet) { 
  15.         this(context, attrSet,""); 
  16.     } 
  17.  
  18.     public MyComponent(Context context, AttrSet attrSet, String styleName) { 
  19.         super(context, attrSet, styleName); 
  20.         init(context); 
  21.     } 
  22.  
  23.     public void init(Context context) { 
  24.         // 设置测量组件的侦听器 
  25.         setEstimateSizeListener(this); 
  26.         // 初始化画笔 
  27.         initPaint(); 
  28.         // 添加绘制任务 
  29.         addDrawTask(this); 
  30.     } 
  31.  
  32.     private void initPaint() { 
  33.         paint = new Paint(); 
  34.         paint.setAntiAlias(true); 
  35.         paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP); 
  36.         paint.setStyle(Paint.Style.STROKE_STYLE); 
  37.  
  38.         paintText = new Paint(); 
  39.         paintText.setStrokeCap(Paint.StrokeCap.ROUND_CAP); 
  40.         paintText.setStyle(Paint.Style.FILL_STYLE); 
  41.         paintText.setColor(Color.WHITE); 
  42.         paintText.setTextSize(50); 
  43.         paintText.setAntiAlias(true); 
  44.  
  45.         bigImage = PixelMapUtils.createPixelMapByResId(ResourceTable.Media_imageDev, getContext()).get(); 
  46.         smallImage = PixelMapUtils.createPixelMapByResId(ResourceTable.Media_icon, getContext()).get(); 
  47.  
  48.     } 
  49.  
  50.     @Override 
  51.     public void addDrawTask(Component.DrawTask task) { 
  52.         super.addDrawTask(task); 
  53.         task.onDraw(this, mCanvasForTaskOverContent); 
  54.     } 
  55.  
  56.     @Override 
  57.     public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) { 
  58.         int width = Component.EstimateSpec.getSize(widthEstimateConfig); 
  59.         int height = Component.EstimateSpec.getSize(heightEstimateConfig); 
  60.         setEstimatedSize( 
  61.                 Component.EstimateSpec.getChildSizeWithMode(width, width, Component.EstimateSpec.NOT_EXCEED), 
  62.                 Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.NOT_EXCEED)); 
  63.         return true
  64.     } 
  65.  
  66.     @Override 
  67.     public void onDraw(Component component, Canvas canvas) { 
  68.         int width = getWidth(); 
  69.         int center = width / 2; 
  70.  
  71.         float length = (float) (center - Math.sqrt(2) * 1.0f / 2 * center); 
  72.  
  73.         // 获取大图片的大小 
  74.  
  75.         Size bigImageSize = bigImage.getImageInfo().size
  76.         RectFloat bigImageRect = new RectFloat(0, 0, width,  bigImageSize.height); 
  77.  
  78.         // 获取小图片的大小 
  79.         Size smallImageSize = smallImage.getImageInfo().size
  80.         RectFloat smallImageRect = new RectFloat(length * 5, length * 5 - 50, 1100, 1030); 
  81.  
  82.         canvas.drawPixelMapHolderRect(new PixelMapHolder(bigImage), bigImageRect, paint); 
  83.         canvas.drawPixelMapHolderRect(new PixelMapHolder(smallImage), smallImageRect, paint); 
  84.         canvas.drawText(paintText,"ABCDEFG",width - length * 3.3f, bigImageSize.height - length * 0.2f); 
  85.  
  86.     } 
  87.  

如上代码,我们创建一个 MyComponent 继承 Component ,并且在构造方法中,初始化一些画笔属性,传入默认的图片,当然也可以通过调用接口的方式在引用的地方传入图片。然后在 ondraw 方法中做具体的画笔操作。通过 canvas.drawPixelMapHolderRect 方法画出一大一小两张可堆叠的图片,并调整好位置参数。

在 Ability 中引用

实现组件之后,我们就可以在我们需要展示的 Ability 去调用这个自定义组件了。

  1. ... 
  2. public class ImageAbilitySlice extends AbilitySlice { 
  3.  
  4.     @Override 
  5.     protected void onStart(Intent intent) { 
  6.         super.onStart(intent); 
  7. //        super.setUIContent(ResourceTable.Layout_ability_image_main); 
  8.         drawMyComponent(); 
  9.     } 
  10.  
  11.     private void drawMyComponent() { 
  12.         // 声明布局 
  13.         ScrollView myLayout = new ScrollView(this); 
  14.         DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig( 
  15.                 DirectionalLayout.LayoutConfig.MATCH_PARENT, DirectionalLayout.LayoutConfig.MATCH_PARENT); 
  16.         myLayout.setLayoutConfig(config); 
  17.         myLayout.setReboundEffect(true); 
  18.         MyComponent customComponent = new MyComponent(this); 
  19.         myLayout.addComponent(customComponent); 
  20.         super.setUIContent(myLayout); 
  21.     } 
  22.  

在XML文件中引用

  1. "1.0" encoding="utf-8"?> 
  2.     ohos:id="$+id:dl" 
  3.     xmlns:ohos="http://schemas.huawei.com/res/ohos" 
  4.     ohos:height="match_parent" 
  5.     ohos:width="match_parent" 
  6.     ohos:alignment="center" 
  7.     ohos:rebound_effect="true" 
  8.     ohos:orientation="vertical"
  9.  
  10.     
  11.         ohos:id="$+id:myComponent" 
  12.         ohos:height="match_parent" 
  13.         ohos:width="match_parent"/> 
  14.  
  15.  

需要注意的是,微信朋友圈主页的滑动有下拉回弹效果,所以我们需要设置 ScrollView 的布局属性。通过在代码中调用 setReboundEffect(true) 或者 xml 中设置 ohos:rebound_effect=“true” 来实现。

效果展示

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

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