fix(hair): 图片区布局修复——Stack 显式定高 320(额度胶囊 Row height(100%) 在自适应 Stack 里会被 Scroll 视口撑飞,导致图片区下坠出大片空白);裁切回 Cover 居中(人脸通常居中,顶部锚定会只显示天花板);选图/拍照用户取消静默化(13900042 不再误报「读取照片失败」)
真机走查验证:布局紧贴页签、选中描边+「试戴『×××』」按钮、试戴成功自动切效果图页签、额度 3→2 递减
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
import { image } from '@kit.ImageKit'
|
||||
import { util } from '@kit.ArkTS'
|
||||
import { BusinessError } from '@kit.BasicServicesKit'
|
||||
import { photoAccessHelper } from '@kit.MediaLibraryKit'
|
||||
import { cameraPicker } from '@kit.CameraKit'
|
||||
import { camera } from '@kit.CameraKit'
|
||||
@@ -70,6 +71,12 @@ export class ImageCodec {
|
||||
)
|
||||
}
|
||||
|
||||
/** 用户取消判定:多数路径取消返回空数组,但预览态/部分 ROM 会 reject 13900042。 */
|
||||
private static isUserCancel(e: Object): boolean {
|
||||
const code: number | undefined = (e as BusinessError).code
|
||||
return code === 13900042
|
||||
}
|
||||
|
||||
/** 相册选 1 张。用户取消返回 undefined。 */
|
||||
static async pickFromGallery(): Promise<PickedImage | undefined> {
|
||||
const picker = new photoAccessHelper.PhotoViewPicker()
|
||||
@@ -90,6 +97,9 @@ export class ImageCodec {
|
||||
return { uri: res.photoUris[0], width: 0, height: 0 }
|
||||
} catch (e) {
|
||||
hilog.error(IMG_DOMAIN, IMG_TAG, 'gallery: pick failed: %{public}s', String(e))
|
||||
if (ImageCodec.isUserCancel(e)) {
|
||||
return undefined // 取消不报错(页面保持原状,不弹「读取照片失败」)
|
||||
}
|
||||
throw e as Error
|
||||
}
|
||||
}
|
||||
@@ -109,6 +119,9 @@ export class ImageCodec {
|
||||
return { uri: res.resultUri, width: 0, height: 0 }
|
||||
} catch (e) {
|
||||
hilog.error(IMG_DOMAIN, IMG_TAG, 'camera: pick failed: %{public}s', String(e))
|
||||
if (ImageCodec.isUserCancel(e)) {
|
||||
return undefined // 取消不报错
|
||||
}
|
||||
throw e as Error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +303,8 @@ struct HairColorPage {
|
||||
.backgroundColor(COLOR_IMAGE_BG)
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
// 图片区(单区域):无照片=上传入口;生成中=loading;按页签显示原图/效果图
|
||||
// 图片区(单区域,定高 320):无照片=上传入口;生成中=loading;按页签显示原图/效果图。
|
||||
// 注意 Stack 必须显式定高:内部额度胶囊 Row 用 height(100%),不定高会被 Scroll 视口撑飞
|
||||
Stack({ alignContent: Alignment.BottomStart }) {
|
||||
if (this.photoUri.length === 0) {
|
||||
Column({ space: 6 }) {
|
||||
@@ -321,11 +322,9 @@ struct HairColorPage {
|
||||
.width('100%').height(320).justifyContent(FlexAlign.Center)
|
||||
.borderRadius(12).backgroundColor(COLOR_IMAGE_BG)
|
||||
} else if (this.imageTab === 1 && this.resultPm !== undefined) {
|
||||
// 顶部对齐裁切:容器定高 clip,图片只定宽按原比缩放,头顶/发型不被居中裁掉
|
||||
Column() {
|
||||
Image(this.resultPm).width('100%').objectFit(ImageFit.Cover)
|
||||
}
|
||||
.width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG)
|
||||
// Cover 居中裁切:人脸通常在画面中央,头顶/下巴各让一点比只切下巴安全
|
||||
Image(this.resultPm)
|
||||
.width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12)
|
||||
Text('效果图')
|
||||
.fontSize(11).fontColor(Color.White)
|
||||
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
|
||||
@@ -333,11 +332,8 @@ struct HairColorPage {
|
||||
.backgroundColor(COLOR_BADGE_BG)
|
||||
.margin(8)
|
||||
} else {
|
||||
// 顶部对齐裁切:同上
|
||||
Column() {
|
||||
Image(this.photoUri).width('100%').objectFit(ImageFit.Cover)
|
||||
}
|
||||
.width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG)
|
||||
Image(this.photoUri)
|
||||
.width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12)
|
||||
Text('原图')
|
||||
.fontSize(11).fontColor(Color.White)
|
||||
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
|
||||
@@ -363,6 +359,7 @@ struct HairColorPage {
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height(320)
|
||||
|
||||
// 入口文字链:相册/拍照 + 保存(有结果才可点)
|
||||
Row({ space: 16 }) {
|
||||
|
||||
@@ -340,7 +340,8 @@ struct HairDesignPage {
|
||||
.backgroundColor(COLOR_IMAGE_BG)
|
||||
.alignSelf(ItemAlign.Start)
|
||||
|
||||
// 图片区(单区域):无照片=上传入口;生成中=loading;按页签显示原图/效果图
|
||||
// 图片区(单区域,定高 320):无照片=上传入口;生成中=loading;按页签显示原图/效果图。
|
||||
// 注意 Stack 必须显式定高:内部额度胶囊 Row 用 height(100%),不定高会被 Scroll 视口撑飞
|
||||
Stack({ alignContent: Alignment.BottomStart }) {
|
||||
if (this.photoUri.length === 0) {
|
||||
Column({ space: 6 }) {
|
||||
@@ -358,11 +359,9 @@ struct HairDesignPage {
|
||||
.width('100%').height(320).justifyContent(FlexAlign.Center)
|
||||
.borderRadius(12).backgroundColor(COLOR_IMAGE_BG)
|
||||
} else if (this.imageTab === 1 && this.resultPm !== undefined) {
|
||||
// 顶部对齐裁切:容器定高 clip,图片只定宽按原比缩放,头顶/发型不被居中裁掉
|
||||
Column() {
|
||||
Image(this.resultPm).width('100%').objectFit(ImageFit.Cover)
|
||||
}
|
||||
.width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG)
|
||||
// Cover 居中裁切:人脸通常在画面中央,头顶/下巴各让一点比只切下巴安全
|
||||
Image(this.resultPm)
|
||||
.width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12)
|
||||
Text('效果图')
|
||||
.fontSize(11).fontColor(Color.White)
|
||||
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
|
||||
@@ -370,11 +369,8 @@ struct HairDesignPage {
|
||||
.backgroundColor(COLOR_BADGE_BG)
|
||||
.margin(8)
|
||||
} else {
|
||||
// 顶部对齐裁切:同上
|
||||
Column() {
|
||||
Image(this.photoUri).width('100%').objectFit(ImageFit.Cover)
|
||||
}
|
||||
.width('100%').height(320).clip(true).borderRadius(12).backgroundColor(COLOR_IMAGE_BG)
|
||||
Image(this.photoUri)
|
||||
.width('100%').height(320).objectFit(ImageFit.Cover).borderRadius(12)
|
||||
Text('原图')
|
||||
.fontSize(11).fontColor(Color.White)
|
||||
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
|
||||
@@ -400,6 +396,7 @@ struct HairDesignPage {
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height(320)
|
||||
|
||||
// 入口文字链:相册/拍照 + 保存(有结果才可点)
|
||||
Row({ space: 16 }) {
|
||||
|
||||
Reference in New Issue
Block a user