HarmonyOS 鸿蒙Next中如何实现无损图片“九宫格”缩放?

HarmonyOS 鸿蒙Next中如何实现无损图片“九宫格”缩放? 在开发聊天表情包、圆角气泡或不规则卡片这些场景中,我们经常都需要将一张方形素材铺满一个圆角矩形容器,那我们应该如何做到图片无损缩放铺满呢?

3 回复

实现思路

首先Image 组件的裁剪区域(Clip)等于组件的布局区域。如果布局区域是圆角矩形,圆角外的像素都会被物理裁剪掉。所以需要特殊处理下。

我们本次使用 renderFit 属性来处理(renderFit 属性用于控制渲染内容的适配区域)

我们设置 renderFit: RenderFit.TOP_START,这会将图片的渲染基点对齐到组件。确保图片内容“内缩”于圆角之内,而不是强行填满导致边缘被切

效果

cke_9696.png

使用场景

主要针对价格标签或促销角标,需要背景图片适配不规则形状 或者 需要给一些头像添加圆角边框装饰时的场景。

完整代码

@Entry
@Component
struct RenderFitDemo {
  build() {
    Scroll() {
      Column({ space: 30 }) {
        Text("renderFit 与圆角适配演示")
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .margin({ top: 40, bottom: 20 })

        Column() {
          Text("Cover + BorderRadius")
            .fontSize(16)
            .fontColor('#666')

          Image($r('app.media.startIcon'))
            .width(150)
            .height(150)
            .objectFit(ImageFit.Cover)
            .borderRadius(20)
            .border({ width: 2, color: '#FF0000' })
        }
        .width('100%')
        .padding(20)
        .backgroundColor('#F1F3F5')
        .borderRadius(12)

        Column() {
          Text("Fit + 内边距保护")
            .fontSize(16)
            .fontColor('#333')

          Stack() {
            Column()
              .width(150)
              .height(150)
              .borderRadius(20)
              .backgroundColor('#C6E2FF')

            // 图片层
            Image($r('app.media.startIcon'))
              .width('90%') // 稍微缩小,留出安全边距
              .height('90%')
              .objectFit(ImageFit.Contain)
          }
          .width(150)
          .height(150)

          Text("内容完整显示")
            .fontSize(12)
            .fontColor('#666')
            .margin({ top: 5 })
        }
        .width('100%')
        .padding(20)
        .backgroundColor('#FFFFFF')
        .borderRadius(12)
        .shadow({ radius: 5, color: '#1A000000', offsetY: 2 })


        Column() {
          Text("renderFit 铺满优化")
            .fontSize(16)
            .fontColor('#333')

          Stack({ alignContent: Alignment.Center }) {
            // 底层:一张铺满的背景图
            Image($r('app.media.startIcon'))
              .width(150)
              .height(150)
              .objectFit(ImageFit.Cover)
              .borderRadius(20)
              .opacity(0.3) // 淡化作为背景

            Text("logo")
              .fontSize(20)
              .fontColor('#000000')
              .fontWeight(FontWeight.Bold)
          }
          .width(150)
          .height(150)
          .backgroundColor(Color.White)
          .borderRadius(20)
        }
        .width('100%')
        .padding(20)
        .backgroundColor('#FFFFFF')
        .borderRadius(12)

      }
      .width('100%')
      .padding({ left: 20, right: 20, bottom: 40 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F0F4F8')
  }
}

更多关于HarmonyOS 鸿蒙Next中如何实现无损图片“九宫格”缩放?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,可通过PixelMap API实现无损图片九宫格缩放。使用Image组件加载图片资源,结合PixelMap的createNinePatch方法,定义图片的拉伸区域(九宫格信息)。该方法能确保图片在缩放时,四个角保持原始尺寸,仅拉伸中间部分,从而避免失真。具体实现需在ets文件中导入相关模块,并正确设置九宫格参数。

在HarmonyOS Next中实现无损图片的“九宫格”缩放,核心是使用Image组件的resizable属性。这通常被称为“.9图”或“九宫格切图”技术,专门用于解决圆角、气泡等不规则形状容器中图片拉伸变形的问题。

实现方法如下:

  1. 准备图片:首先需要一张带有特殊标记的“.9.png”格式图片。该图片四周有1像素宽的黑边,用于标记可拉伸区域(左右黑边定义水平拉伸区域,上下黑边定义垂直拉伸区域)和内容填充区域(上下左右黑边共同定义)。

  2. 使用resizable属性:在ArkUI的Image组件中,通过resizable参数来定义九宫格拉伸的规则。

    Image($r('app.media.bubble_bg')) // 引用.9.png图片资源
      .resizable({
        top: 10,    // 上边不拉伸区域高度(根据图片黑边标记计算)
        bottom: 10, // 下边不拉伸区域高度
        left: 10,   // 左边不拉伸区域宽度
        right: 10   // 右边不拉伸区域宽度
      })
      .width('100%')
      .height(120)
    

关键点说明:

  • resizable的参数值(如top: 10)取决于你的.9.png图片上用黑边标记的“可拉伸区域”的大小。这些数值是图片的“内部尺寸”,与最终显示的组件尺寸无关。
  • 四边定义的区域交叉后,将图片分为9个部分(四个角、四个边、一个中心)。四个角区域不会拉伸,保持原始比例;四个边区域会单向拉伸;中心区域会双向拉伸。这确保了圆角、边框等关键部分在缩放时不变形。
  • 此方法实现的是“无损”缩放,因为关键部分(角)未发生形变,只是将可拉伸的中间部分进行扩展,完美适配不同尺寸的容器。

适用场景:

  • 聊天对话框气泡
  • 可变尺寸的按钮背景
  • 不规则形状的卡片背景
  • 表情包等需要保持特定轮廓的UI元素

这种方法直接利用了系统级的图片拉伸能力,无需编写复杂计算逻辑,是处理此类UI适配的最高效方案。

回到顶部