HarmonyOS鸿蒙Next中resizable中的lattice如何使用,感觉文档太难理解了,图中的坐标和demo中的都对不上

HarmonyOS鸿蒙Next中resizable中的lattice如何使用,感觉文档太难理解了,图中的坐标和demo中的都对不上 https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-implementing-image-resizable#section0797147172420

目标效果

test.png

我下面的代码怎么调整都无法实现图片只拉伸水平中间那段区域,高度和两边不需要拉伸

@Entry
@Component
struct ArkTsDemoPage {

  private xDivs: Array<number> = [20,100]; // 水平方向关键坐标点
  private yDivs: Array<number> = [];// 纵向不分割(保持高度不变)
  private drawingLattice: DrawingLattice =
    drawing.Lattice.createImageLattice(this.xDivs, this.yDivs, this.xDivs.length, this.yDivs.length);

  build() {
  Stack(){
    Stack() {
      Stack() {
        Image('test.png')
          .width(60)
          .height(16)
          .resizable({
            lattice: this.drawingLattice // 应用网格规则
          })

        Text('粉丝团')
          .fontSize(9)
          .offset({ x: 5 })
          .fontColor(Color.White)
      }
    }
    .width(80)
    .height(40)
    .backgroundColor('#F7F6F9')
    .borderRadius(8)
  }
    .height('100%')
  }
}

更多关于HarmonyOS鸿蒙Next中resizable中的lattice如何使用,感觉文档太难理解了,图中的坐标和demo中的都对不上的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

【解决方案】

开发者你好,可以参考下以下Demo,要实现开发者的图片原图(宽87px,高37px)只水平拉伸需要将无需发生形变的区域处于矩形网格的偶数行偶数列,以X轴[38, 66],Y轴不划分,可分割为3*1的网格,即可实现原图心形形状、左右两边及Y轴方向不拉伸的效果:

@Entry
@Component
struct ArkTsDemoPage {

  private xDivs: Array<number> = [38,66]; // 水平方向关键坐标点
  private yDivs: Array<number> = [];// 纵向不分割(保持高度不变)
  private drawingLattice: DrawingLattice =
    drawing.Lattice.createImageLattice(this.xDivs, this.yDivs, this.xDivs.length, 0);

  build() {
    Stack(){
      Stack() {
        Stack() {
          Image('图片')
            .width(60)
            .height(16)
            .resizable({
              lattice: this.drawingLattice // 应用网格规则
            })

          Text('粉丝团')
            .fontSize(9)
            .offset({ x: 3 })
            .fontColor(Color.White)
        }
      }
      .width(80)
      .height(40)
      .backgroundColor('#F7F6F9')
      .borderRadius(8)
    }
    .height('100%')
  }
}
  • 矩形网格对象通过createImageLattice方法创建,使用屏幕物理像素单位px。可以将图像划分为矩形网格,同时处于偶数列和偶数行上的网格是固定的。如果目标网格足够大,则这些固定网格以其原始大小进行绘制;如果目标网格太小,无法容纳这些固定网格,则所有固定网格都会按比例缩小以适应目标网格。其余网格将进行缩放,来适应剩余的空间。

更多关于HarmonyOS鸿蒙Next中resizable中的lattice如何使用,感觉文档太难理解了,图中的坐标和demo中的都对不上的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


使用slice试试
cke_131.png

slice适合简单的图片,只能设置上下左右的区域,无法设置图片中间的区域不拉伸,

在HarmonyOS Next中,resizable的lattice属性用于定义窗口可调整区域。它是一个4x4的网格,每个格子用0或1表示是否可调整。坐标原点在左上角,行和列索引从0开始。例如,lattice="0010 0100 1000 0001"表示第三行第一列等位置可调整。确保字符串格式正确,每行4个字符,共4行,用空格分隔。

理解你的困惑。文档中的坐标描述和实际应用确实容易混淆,关键在于理解 xDivsyDivs 数组定义的是分割线位置,而不是“要拉伸的区域”。

根据你的目标(只水平拉伸中间区域,高度和两边不变),结合你提供的 test.png 图片(一个带圆角的水平长条背景,文字在左侧),正确的配置思路如下:

  1. 核心逻辑xDivs 数组中的值,将图片在水平方向上划分为多个“固定”和“拉伸”区域。数组中的每个值代表一条分割线的X坐标(相对于原始图片尺寸)。分割线之间的区域,其拉伸行为由 srcRectsdstRects 决定(createImageLattice 方法内部处理了默认映射)。

  2. 你的图片与坐标分析

    • 你的 test.png 原始宽度为 60vp
    • 要实现“两边不拉伸,只拉伸中间”,需要三条垂直分割线,将图片分为左、中、右三部分。
    • 假设你希望:
      • 左侧固定区域:包含左边的圆角和“粉丝团”文字背景,假设原始宽度为 20vp
      • 中间拉伸区域:纯色部分,假设从 20vp40vp
      • 右侧固定区域:包含右边的圆角,假设从 40vp60vp
  3. 代码修正

    • xDivs 应设置为 [20, 40]。这表示在原始图片的 20vp40vp 位置画两条分割线,从而得到三个垂直区域:[0, 20], [20, 40], [40, 60]
    • 默认情况下,createImageLattice 会创建1:1的源到目标矩形映射。当目标 Image 组件宽度(你代码中是 80vp)大于原始图片宽度(60vp)时,只有 xDivs 定义的、不在数组首尾的中间区域(即 [20,40] 这个区间)会被拉伸,以填充新的宽度。首尾区域([0,20][40,60])保持原始比例。
    • yDivs 设为空数组 [] 是正确的,表示在垂直方向不进行分割,整个高度方向的行为一致(你希望高度不变)。

修改后的关键代码部分:

private xDivs: Array<number> = [20, 40]; // 在原始图片宽度60vp上,于20vp和40vp处设置分割线
private yDivs: Array<number> = []; // 垂直方向不分割
private drawingLattice: DrawingLattice =
  drawing.Lattice.createImageLattice(this.xDivs, this.yDivs, this.xDivs.length, this.yDivs.length);

总结与验证

  • 坐标原点xDivsyDivs 的坐标值都是相对于你通过 .width().height() 设置的图片原始显示尺寸(在你的代码中是 .width(60).height(16)),而不是图片的物理像素尺寸。
  • 效果:设置 xDivs: [20, 40] 后,当外部容器宽度变为 80vp 时,图片会:
    1. 保持左侧 [0,20] 区域(左圆角及部分背景)的原始宽度。
    2. 拉伸中间 [20,40] 区域(纯色背景)以适应新的总宽度。
    3. 保持右侧 [40,60] 区域(右圆角)的原始宽度。
    4. 整个图片高度保持不变。

请根据你的 test.png 实际设计,调整 2040 这两个分割线位置值,它们决定了固定部分和拉伸部分的精确比例。如果文字“粉丝团”完全位于左侧固定区域内,那么拉伸时文字部分就不会变形。

回到顶部