选择图片主要设计到状态管理,鸿蒙中状态管理是比较复杂而且又是必备技能,先看效果图:
首先定义图片数据实体类:
interface ILocalImgData {image: ResourceStr}
class LocalImgData implements ILocalImgData {
image: ResourceStr
constructor(data: ILocalImgData) {
this.image = data.image
}
}
export { LocalImgData, ILocalImgData }
SelectImagePage
@Entry
@Component
struct SelectImagePage {
@State
isShowSelectSheet: boolean = false
@State
selected: ILocalImgData[] = []
maxNum: number = 9
@Builder
ImageSelectBuilder() {
Column() {
SelectImageSheet({
maxSelectNum: this.maxNum - this.selected.length,
selected: this.selected,
isShowSelectSheet: this.isShowSelectSheet
})
}
}
build() {
Grid() {
ForEach(this.selected, (item: ILocalImgData) => {
GridItem() {
Stack({ alignContent: Alignment.TopEnd }) {
Image(item.image)
.width("100%")
.aspectRatio(1)
.borderRadius(6)
Image($r("app.media.delete"))
.width(16)
.aspectRatio(1)
.margin(10)
.onClick(() => {
this.selected = this.selected.filter((fItem) => fItem != item)
})
}.width("100%")
}
})
GridItem() {
Image($r("app.media.add")).width(16).aspectRatio(1)
}.border({ width: 1, color: Color.Gray, radius: 6 })
.aspectRatio(1)
.visibility(this.maxNum - this.selected.length == 0 ? Visibility.None : Visibility.Visible)
.onClick(() => this.isShowSelectSheet = true)
}
.columnsTemplate("1fr 1fr 1fr")
.columnsGap(6)
.rowsGap(6)
.height('100%')
.width('100%')
.padding({
top: 10 + px2vp(AppManager.topSafeHeight),
bottom: px2vp(AppManager.topSafeHeight),
left: 10,
right: 10
})
.bindSheet($$this.isShowSelectSheet,
this.ImageSelectBuilder(), {
height: "80%",
enableOutsideInteractive: true,
showClose: false
})
}
}
SelectImageSheet
@Component
struct SelectImageSheet {
private imageResources: ILocalImgData[] = [................]
@State
selectImages: ILocalImgData[] = []
@Link
selected: ILocalImgData[]
@Link
isShowSelectSheet: boolean
maxSelectNum: number = 9
build() {
Column() {
Row() {
Text("取消")
.fontSize(16)
.onClick(() => this.isShowSelectSheet = false)
Text(`${this.selectImages.length}/${this.maxSelectNum}`)
.fontSize(16)
Text("确定")
.fontSize(16)
.onClick(() => {
this.selected.unshift(...this.selectImages)
this.isShowSelectSheet = false
})
}
.padding(20)
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
Grid() {
ForEach(this.imageResources, (item: ILocalImgData) => {
GridItem() {
Stack({ alignContent: Alignment.BottomEnd }) {
Image(item.image).width("100%").aspectRatio(1)
.borderRadius(6)
Image($r("app.media.select"))
.width(16)
.aspectRatio(1)
.margin(10)
.visibility(this.selectImages.includes(item) ? Visibility.Visible : Visibility.None)
}.width("100%")
}.onClick(() => {
console.log("TAG>>>" + JSON.stringify(this.selectImages))
if (this.selectImages.includes(item)) {
this.selectImages = this.selectImages.filter((fItem) => fItem != item)
return
}
if (this.selectImages.length >= this.maxSelectNum) {
promptAction.showToast({ message: `最多只能选中${this.maxSelectNum}` })
return
}
this.selectImages.unshift(item)
})
})
}
.columnsTemplate("1fr 1fr 1fr")
.columnsGap(6)
.rowsGap(6)
.padding({ left: 20, right: 20 })
.height('100%')
.width('100%')
}
}
}
export default SelectImageSheet
图片预览
@CustomDialog
struct PreviewImageDialog {
controller: CustomDialogController
@Link
currentIndex: number
@Link
previewImages: ILocalImgData[]
build() {
Column() {
Stack({ alignContent: Alignment.Bottom | Alignment.Center }) {
Swiper() {
ForEach(this.previewImages, (item: ILocalImgData) => {
Image(item.image)
.width("100%")
})
}.index($$this.currentIndex)
.autoPlay(true)
.indicator(false)
Text(`${this.currentIndex + 1}/${this.previewImages.length}`)
.margin(10)
.fontColor(Color.White)
.fontSize(16)
}
}
.justifyContent(FlexAlign.Center)
.backdropBlur(30)
.width("100%")
.height("100%")
.onClick(() => {
this.controller.close()
})
}
}
export default PreviewImageDialog