简介
日常项目中,我们可能会碰到一些标题加特效或多行内容+查看更多的需求,如果使用Text+Image这样去拼接的话,在复杂多“标签”场景就实现起来比较呆板,于是根据现有的HarmonyOS Text提供了一种思路实现了图文标题,我们需要在Text中进行图文混排。
效果演示
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常用属性
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日发布");
示例效果:
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 图文混排标题!");
示例效果:
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月份前后完成。");
示例效果:
4、图片单击事件
- textImageTitle.setImageClickedListener(() -> {
- L.d("TextImageTitle", "image click....");
- // TODO do something....
- });
实现思路
根据遍历字符计算是否换行(细节请查看源代码)
- 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) {
- // ..... 省略大量代码
- }
- ...
- }
绘制文字
- 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);
绘制图文
- 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;
- }