#星光计划1.0#HarmonyOS 自定义View之图文标题 原创 精华

中软HOS小鸿
发布于 2021-10-22 10:17
浏览
7收藏

作者:彭为杰

简介

​ 日常项目中,我们可能会碰到一些标题加特效或多行内容+查看更多的需求,如果使用Text+Image这样去拼接的话,在复杂多“标签”场景就实现起来比较呆板,于是根据现有的HarmonyOS Text提供了一种思路实现了图文标题,我们需要在Text中进行图文混排。

效果演示

#星光计划1.0#HarmonyOS 自定义View之图文标题-鸿蒙开发者社区

TextImageTitle介绍

TextImageTitle是用来显示字符串+图片(或任意Component)的自定义控件,目前只支持头部或者尾部。

private int textSize = 45;
private Color textColor = new Color(0xff000000);
private int lineHeight = 60;
private int maxTextLines = DEFAULT_LINES;
private int imageLayout;
private int imageResId;
private int imageWidth;
private int imageHeight;
private int imageMarginLeft;
private int imageMarginRight;
private Component imageComponent;

TextImageTitle常用属性

属性名称 中文描述 取值 取值说明
textSize 文字大小 int 同Text
textColor 文字颜色 Color 同Text
lineHeight 行高 int >0
maxTextLines 最大显示行数int int -1,认为显示最大行
imageLayout 图片位置 int 0:前面; 1:尾部;
imageResId 图片资源 int R 下资源
imageWidth 图片宽度 int >=0
imageHeight 图片高度 int >=0
imageMarginLeft 图片left距离 int >=0
imageMarginRight 图片right距离 int >=0

TextImageTitle用法

在layout目录下的xml文件中创建TextImageTitle组件。

<com.pvj.textimagetitlelibrary.TextImageTitle
    ohos:id="$+id:text0"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:padding="10vp"
    />

1、设置图片在头部

示例代码:

TextImageTitle textImageTitle = (TextImageTitle) findComponentById(ResourceTable.Id_text0);
TextImageTitle.Parameter parameter = new TextImageTitle.Parameter().
        setMaxTextLines(1).
        setImageLayout(TextImageTitle.LAYOUT_FRONT).
        setImageResId(ResourceTable.Media_icon_notice).
        setLineHeight(80).
        setTextSize(50).
        setImageWidth(100).setImageHeight(80).
        setImageMarginRight(30).
        setImageMarginLeft(0);
textImageTitle.setParameter(parameter);
textImageTitle.setText("鸿蒙3.0有望在10月22日发布");

示例效果:

#星光计划1.0#HarmonyOS 自定义View之图文标题-鸿蒙开发者社区

2、设置Component在尾部

示例代码:

TextImageTitle textImageTitle = (TextImageTitle) findComponentById(ResourceTable.Id_text1);
Component component = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_icon_tv2, textImageTitle, false);
TextImageTitle.Parameter parameter = new TextImageTitle.Parameter().
        setMaxTextLines(1).
        setImageLayout(TextImageTitle.LAYOUT_TAIL).
        setImageComponent(component).
        setLineHeight(70).
        setTextSize(45).
        setImageWidth(400).setImageHeight(70).
        setImageMarginLeft(30);
textImageTitle.setParameter(parameter);
textImageTitle.setText("HarmonyOS 图文混排标题!");

示例效果:

#星光计划1.0#HarmonyOS 自定义View之图文标题-鸿蒙开发者社区

3、设置多行文字尾部图片

示例代码:

TextImageTitle textImageTitle = (TextImageTitle) findComponentById(ResourceTable.Id_text3);
TextImageTitle.Parameter parameter = new TextImageTitle.Parameter().
        setMaxTextLines(3).
        setImageLayout(TextImageTitle.LAYOUT_TAIL).
        setImageResId(ResourceTable.Media_icon_more).
        setImageWidth(70).setImageHeight(70).
        setLineHeight(70).
        setTextSize(45).
        setImageMarginLeft(0).
        setImageMarginRight(50);
textImageTitle.setParameter(parameter);
textImageTitle.setText("华为开发者大会2021将在东莞松山湖举办,根据官方邀请函上透露出来的信息,鸿蒙HarmonyOS 3.0、HMS Core 6、全屋智能等黑科技也将悉数亮相鸿蒙HarmonyOS 2升级用户数量已经突破了1.3亿大关,并且华为鸿蒙OS系统目前平均每天升级用户数量都超过了100百万,根据华为目前的规划,鸿蒙OS系统的百机升级计划将会在今年12月份前后完成。");

示例效果:
#星光计划1.0#HarmonyOS 自定义View之图文标题-鸿蒙开发者社区

4、图片单击事件

textImageTitle.setImageClickedListener(() -> {
    L.d("TextImageTitle", "image click....");
    // TODO do something....
});

实现思路

  1. 根据遍历字符计算是否换行(细节请查看源代码)
 int titleLength = title.length();
 measurePaint.setTextSize(parameter.textSize);
 int curLines = 1;
 float curWidth = 0.0f;
 int indexEnd = 0;

 //判断图文在前 还是在后
 boolean isFront = parameter.imageLayout == LAYOUT_FRONT;
  // 1,遍历字符串
 for (int index = 0; index < titleLength; index++) {
       String c = String.valueOf(title.charAt(index));
       float vW = measurePaint.measureText(c);
       curWidth += vW;
     
     //  一些行数 或每行宽度判断示例 头尾判断
     if (lineWidth < curWidth) {
         // ..... 省略大量代码
     }
     
     if (lineWidth < curWidth + imageTotalWidth) {
        // ..... 省略大量代码
     }
     
    if (isFront && curLines == 1) {
       // ..... 省略大量代码 
    }
     ...
 }
  1. 绘制文字
 private void createText(String text) {
     // Text内容创建并且加到容器上
     Text titleText = new Text(getContext());
     titleText.setTextSize(parameter.textSize);
     titleText.setTextColor(parameter.textColor);
     addComponent(titleText, ComponentContainer.LayoutConfig.MATCH_PARENT, parameter.lineHeight);
     titleText.setText(text);
}
  1. 绘制图文
    private void createTextAndImage(String text, int maxTextWidth, boolean isFront) {
        //创建一个图片和文字的容器
        DirectionalLayout directionalLayout = new DirectionalLayout(getContext());
        directionalLayout.setOrientation(ComponentContainer.HORIZONTAL);
        directionalLayout.setAlignment(LayoutAlignment.VERTICAL_CENTER);
        Text titleText = new Text(getContext());
        titleText.setTextSize(parameter.textSize);
        titleText.setTextColor(parameter.textColor);
         // 文字的最大长度,决定尾部是否显示...;不限制有情况是Image出边界
        titleText.setMaxTextWidth(maxTextWidth);
        titleText.setMultipleLine(false);
        titleText.setTruncationMode(Text.TruncationMode.ELLIPSIS_AT_END);
        titleText.setText(text);

        Component component = getImage(text);
        // 点击事件
        component.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (listener != null) {
                    listener.onClick();
                }
            }
        });

        //判断图片在前还是在后
        if (isFront) {
            if (component != null) {
                directionalLayout.addComponent(component);
            }
            directionalLayout.addComponent(titleText, ComponentContainer.LayoutConfig.MATCH_CONTENT,                                                           ComponentContainer.LayoutConfig.MATCH_PARENT);
        } else {
            directionalLayout.addComponent(titleText, ComponentContainer.LayoutConfig.MATCH_CONTENT,                                                           ComponentContainer.LayoutConfig.MATCH_PARENT);
            if (component != null) {
                directionalLayout.addComponent(component);
            }
        }
        addComponent(directionalLayout, ComponentContainer.LayoutConfig.MATCH_PARENT, parameter.lineHeight);
    }
	
    private Component getImage(String text) {
         // 自定义Component优先
        if (parameter.imageComponent != null) {
            parameter.imageComponent.setComponentSize(parameter.imageWidth, parameter.imageHeight);
            parameter.imageComponent.setMarginLeft(parameter.imageMarginLeft);
            parameter.imageComponent.setMarginRight(parameter.imageMarginRight);
            return parameter.imageComponent;
        } else if (parameter.imageResId != 0) {  
           //图文
            Image image = new Image(getContext());
            image.setComponentSize(parameter.imageWidth, parameter.imageHeight);
            if (!TextTool.isNullOrEmpty(text)) {
                image.setMarginLeft(parameter.imageMarginLeft);
                image.setMarginRight(parameter.imageMarginRight);
            }
            image.setScaleMode(Image.ScaleMode.STRETCH);
            image.setPixelMap(parameter.imageResId);
            return image;
        }
        return null;
    }

代码地址

https://gitee.com/guangdong-wangduoyu/ohos-text-image

更多原创内容请关注:开鸿 HarmonyOS 学院

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

【本文正在参与51CTO HarmonyOS技术社区创作者激励-星光计划1.0】

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
13
收藏 7
回复
举报
2条回复
按时间正序
/
按时间倒序
深开鸿
深开鸿

实用的知识,又增加了一点

回复
2021-10-22 15:09:14
爱吃土豆丝的打工人
爱吃土豆丝的打工人

学习一下

回复
2021-10-25 15:42:33
回复
    相关推荐