HarmonyOs编写一个案例实现一个照片选择(阶段进阶 四种需求 逐一完善)

需求1. .实现照片选择 并将选择好的照片展示出来

TypeScript 复制代码
import { GoodItem } from '../06/modules';

@Entry
@Component
struct PhotoPage {
  @State message: string = '实现一个相册';
  @State List: GoodItem[] = [{

    goods_name: 'dsfjlsjkfsf',
    goods_price: 100,
    goods_img: 'https://img1.baidu.com/it/u=1535232938,2370569369&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800',
    goods_count: 1,
    id: 1

  },
    {

      goods_name: 'dfhlsdjflkdsjklfs 加速度的佛教山東i附件',
      goods_price: 200,
      goods_img: 'https://img1.baidu.com/it/u=2603934083,3021636721&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 2,
      id: 2

    },
    {

      goods_name: '收到回复技术大会哦恶化日发方大化工iu而韩国佛热',
      goods_price: 300,
      goods_img: 'https://img0.baidu.com/it/u=4289818793,3552718550&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 3,
      id: 3

    }
    , {

      goods_name: '的時間佛薩飛機埃里克森放假哦i二fore多氟多化工i額方法過後i額外人',
      goods_price: 400,
      goods_img: 'https://img0.baidu.com/it/u=2080725050,2021436341&fm=253&fmt=auto&app=138&f=JPEG?w=1200&h=800',
      goods_count: 4,
      id: 4

    }
    , {

      goods_name: '时间佛ID分机构IE',
      goods_price: 500,
      goods_img: 'https://img1.baidu.com/it/u=4202924242,2178453218&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800',
      goods_count: 5,
      id: 5

    }
    , {

      goods_name: '司法鉴定哦is叫哦私人',
      goods_price: 600,
      goods_img: 'https://10wallpaper.com/wallpaper/1680x1050/1405/Lavender_mountain_river-Landscape_HD_Wallpaper_1680x1050.jpg',
      goods_count: 6,
      id: 6

    }
  ]
  @State isShowPhotoCom: boolean = false
  @State maxSelectNum: number = 4
  @State showSelectImgs: GoodItem[] = []

  build() {
    Column() {
      Button('选择图片')
        .onClick(() => {
          this.isShowPhotoCom = true
        })
      Grid() {
        ForEach(this.showSelectImgs, (item: GoodItem, index) => {
          GridItem() {
            Image(item.goods_img)
              .aspectRatio(1)
          }

        })
      }
      .columnsTemplate('1fr 1fr')
      .columnsGap(4)
      .rowsGap(4)

      if (this.isShowPhotoCom) {
        photoCom({
          List: this.List,
          isShowPhotoCom: this.isShowPhotoCom,
          maxSelectNum: this.maxSelectNum,
          showSelectImgs: this.showSelectImgs

        })
      }
    }
    .height('100%')
    .width('100%')
  }
}


@Component
struct photoCom {
  @Prop List: GoodItem[] = []
  @Link isShowPhotoCom: boolean
  @State selectList: GoodItem[] = []
  @Prop maxSelectNum: number
  @Link showSelectImgs: GoodItem[]

  // 选择图片逻辑
  selectFn(item: GoodItem) {

    let Index = this.selectList.findIndex(obj => obj.id == item.id)
    console.log(JSON.stringify(Index))
    if (Index > -1) {
      this.selectList.splice(Index, 1)

    } else {
      this.selectList.push(item)
    }
  }

  build() {
    Column() {
      Grid() {
        ForEach(this.List, (item: GoodItem, index) => {
          GridItem() {
            Stack() {
              Image(item.goods_img)
                .aspectRatio(1)


              if (this.selectList.some(obj => obj.id == item.id)) {
                Image($r('app.media.select'))
                  .width(60)
                  .height(60)
                  .fillColor(Color.Red)
              }
            }
            .onClick(() => {
              this.selectFn(item)
            })

          }
        })
      }
      .columnsTemplate('1fr 1fr')
      .layoutWeight(1)

      // Text(`${}/${}`)

      Row() {
        Button('取消').onClick(() => {
          this.isShowPhotoCom = false
        })
        Text(`已选${this.selectList.length}张/最多选择${this.maxSelectNum}张`)

        Button('确认')
          .onClick(() => {
            this.showSelectImgs = this.selectList
            this.isShowPhotoCom = false

          })
      }
      .width('100%')
      .height(60)

      .justifyContent(FlexAlign.SpaceAround)
    }
    .position({ x: 0, y: 0 })
    .width('100%')
    .height('100%')
    .backgroundColor(Color.White)
    .justifyContent(FlexAlign.SpaceBetween)

  }
}

这个案例用到了父子传参@Prop @Link @State 各种样式交互 有兴趣可敲着玩玩~

我们看下效果

点击按钮

出现这个页面

然后执行选中逻辑

然后点击确认关闭弹窗

需求2. 点击图片实现预览效果(CustomDilog)

TypeScript 复制代码
import { GoodItem } from '../06/modules';

@Entry
@Component
struct PhotoPage {
  @State message: string = '实现一个相册';
  @State List: GoodItem[] = [{

    goods_name: 'dsfjlsjkfsf',
    goods_price: 100,
    goods_img: 'https://img1.baidu.com/it/u=1535232938,2370569369&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800',
    goods_count: 1,
    id: 1

  },
    {

      goods_name: 'dfhlsdjflkdsjklfs 加速度的佛教山東i附件',
      goods_price: 200,
      goods_img: 'https://img1.baidu.com/it/u=2603934083,3021636721&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 2,
      id: 2

    },
    {

      goods_name: '收到回复技术大会哦恶化日发方大化工iu而韩国佛热',
      goods_price: 300,
      goods_img: 'https://img0.baidu.com/it/u=4289818793,3552718550&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 3,
      id: 3

    }
    , {

      goods_name: '的時間佛薩飛機埃里克森放假哦i二fore多氟多化工i額方法過後i額外人',
      goods_price: 400,
      goods_img: 'https://img0.baidu.com/it/u=2080725050,2021436341&fm=253&fmt=auto&app=138&f=JPEG?w=1200&h=800',
      goods_count: 4,
      id: 4

    }
    , {

      goods_name: '时间佛ID分机构IE',
      goods_price: 500,
      goods_img: 'https://img1.baidu.com/it/u=4202924242,2178453218&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800',
      goods_count: 5,
      id: 5

    }
    , {

      goods_name: '司法鉴定哦is叫哦私人',
      goods_price: 600,
      goods_img: 'https://10wallpaper.com/wallpaper/1680x1050/1405/Lavender_mountain_river-Landscape_HD_Wallpaper_1680x1050.jpg',
      goods_count: 6,
      id: 6

    }
  ]
  @State isShowPhotoCom: boolean = false
  @State maxSelectNum: number = 4
  @State showSelectImgs: GoodItem[] = []
  @State selectImage: ResourceStr | string = ''
  previw: CustomDialogController = new CustomDialogController({
    builder: PreviewDilog({ url: this.selectImage }),
    customStyle: true


  })

  build() {
    Column() {
      Button('选择图片')
        .onClick(() => {
          this.isShowPhotoCom = true
        })
      Grid() {
        ForEach(this.showSelectImgs, (item: GoodItem, index) => {
          GridItem() {
            Image(item.goods_img)
              .aspectRatio(1)
              .onClick(() => {
                this.selectImage = item.goods_img
                this.previw.open()
              })
          }

        })
      }
      .columnsTemplate('1fr 1fr')
      .columnsGap(4)
      .rowsGap(4)

      if (this.isShowPhotoCom) {
        photoCom({
          List: this.List,
          isShowPhotoCom: this.isShowPhotoCom,
          maxSelectNum: this.maxSelectNum,
          showSelectImgs: this.showSelectImgs

        })
      }
    }
    .height('100%')
    .width('100%')
  }
}


@Component
struct photoCom {
  @Prop List: GoodItem[] = []
  @Link isShowPhotoCom: boolean
  @State selectList: GoodItem[] = []
  @Prop maxSelectNum: number
  @Link showSelectImgs: GoodItem[]

  // 选择图片逻辑
  selectFn(item: GoodItem) {

    let Index = this.selectList.findIndex(obj => obj.id == item.id)
    console.log(JSON.stringify(Index))
    if (Index > -1) {
      this.selectList.splice(Index, 1)

    } else {
      this.selectList.push(item)
    }
  }

  build() {
    Column() {
      Grid() {
        ForEach(this.List, (item: GoodItem, index) => {
          GridItem() {
            Stack() {
              Image(item.goods_img)
                .aspectRatio(1)


              if (this.selectList.some(obj => obj.id == item.id)) {
                Image($r('app.media.select'))
                  .width(60)
                  .height(60)
                  .fillColor(Color.Red)
              }
            }
            .onClick(() => {
              this.selectFn(item)
            })

          }
        })
      }
      .columnsTemplate('1fr 1fr')
      .layoutWeight(1)

      // Text(`${}/${}`)

      Row() {
        Button('取消').onClick(() => {
          this.isShowPhotoCom = false
        })
        Text(`已选${this.selectList.length}张/最多选择${this.maxSelectNum}张`)

        Button('确认')
          .onClick(() => {
            this.showSelectImgs = this.selectList
            this.isShowPhotoCom = false

          })
      }
      .width('100%')
      .height(60)

      .justifyContent(FlexAlign.SpaceAround)
    }
    .position({ x: 0, y: 0 })
    .width('100%')
    .height('100%')
    .backgroundColor(Color.White)
    .justifyContent(FlexAlign.SpaceBetween)

  }
}


@CustomDialog
struct PreviewDilog {
  controller: CustomDialogController = new CustomDialogController({ builder: CustomDialogController })
  url: ResourceStr | string = ''

  build() {
    Column() {
      Image(this.url)
        .width('100%')

    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Black)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.controller.close()
    })

  }
}

圈下重点代码部分

子组件的

父组件的

需求3.HarmonyOs半模态bindsheet编写一个案例实现一个照片选择

TypeScript 复制代码
import { GoodItem } from '../06/modules';
 
@Entry
@Component
struct PhotoCasePage {
  @State message: string = '实现一个相册';
  @State List: GoodItem[] = [{
 
    goods_name: 'dsfjlsjkfsf',
    goods_price: 100,
    goods_img: 'https://img1.baidu.com/it/u=1535232938,2370569369&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800',
    goods_count: 1,
    id: 1
 
  },
    {
 
      goods_name: 'dfhlsdjflkdsjklfs 加速度的佛教山東i附件',
      goods_price: 200,
      goods_img: 'https://img1.baidu.com/it/u=2603934083,3021636721&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 2,
      id: 2
 
    },
    {
 
      goods_name: '收到回复技术大会哦恶化日发方大化工iu而韩国佛热',
      goods_price: 300,
      goods_img: 'https://img0.baidu.com/it/u=4289818793,3552718550&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 3,
      id: 3
 
    }
    , {
 
      goods_name: '的時間佛薩飛機埃里克森放假哦i二fore多氟多化工i額方法過後i額外人',
      goods_price: 400,
      goods_img: 'https://img0.baidu.com/it/u=2080725050,2021436341&fm=253&fmt=auto&app=138&f=JPEG?w=1200&h=800',
      goods_count: 4,
      id: 4
 
    }
    , {
 
      goods_name: '时间佛ID分机构IE',
      goods_price: 500,
      goods_img: 'https://img1.baidu.com/it/u=4202924242,2178453218&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800',
      goods_count: 5,
      id: 5
 
    }
    , {
 
      goods_name: '司法鉴定哦is叫哦私人',
      goods_price: 600,
      goods_img: 'https://10wallpaper.com/wallpaper/1680x1050/1405/Lavender_mountain_river-Landscape_HD_Wallpaper_1680x1050.jpg',
      goods_count: 6,
      id: 6
 
    }
  ]
  @State isShowPhotoCom: boolean = false
  @State maxSelectNum: number = 4
  @State showSelectImgs: GoodItem[] = []
  @State selectImage: ResourceStr | string = ''
  previw: CustomDialogController = new CustomDialogController({
    builder: PreviewDilog({ url: this.selectImage }),
    customStyle: true
 
 
  })
 
  @Builder
  sheetBuilder() {
    Column() {
      photoCom({
        List: this.List,
        isShowPhotoCom: this.isShowPhotoCom,
        maxSelectNum: this.maxSelectNum,
        showSelectImgs: this.showSelectImgs
 
      })
 
    }
  }
 
  build() {
    Column() {
      Button('选择图片')
        .onClick(() => {
          this.isShowPhotoCom = true
        })
      Grid() {
        ForEach(this.showSelectImgs, (item: GoodItem, index) => {
          GridItem() {
            Image(item.goods_img)
              .aspectRatio(1)
              .onClick(() => {
                this.selectImage = item.goods_img
                this.previw.open()
              })
          }
 
        })
      }
      .columnsTemplate('1fr 1fr')
      .columnsGap(4)
      .rowsGap(4)
 
    }
    .height('100%')
    .width('100%')
    .bindSheet(this.isShowPhotoCom, this.sheetBuilder, {
      showClose: false
    })
  }
}
 
// 选择图片组件
@Component
struct photoCom {
  @Prop List: GoodItem[] = []
  @Link isShowPhotoCom: boolean
  @State selectList: GoodItem[] = []
  @Prop maxSelectNum: number
  @Link showSelectImgs: GoodItem[]
 
  // 选择图片逻辑
  selectFn(item: GoodItem) {
 
    let Index = this.selectList.findIndex(obj => obj.id == item.id)
    console.log(JSON.stringify(Index))
    if (Index > -1) {
      this.selectList.splice(Index, 1)
 
    } else {
      this.selectList.push(item)
    }
  }
 
  build() {
    Column() {
      Grid() {
        ForEach(this.List, (item: GoodItem, index) => {
          GridItem() {
            Stack() {
              Image(item.goods_img)
                .aspectRatio(1)
 
 
              if (this.selectList.some(obj => obj.id == item.id)) {
                Image($r('app.media.select'))
                  .width(60)
                  .height(60)
                  .fillColor(Color.Red)
              }
            }
            .onClick(() => {
              this.selectFn(item)
            })
 
          }
        })
      }
      .columnsTemplate('1fr 1fr')
      .layoutWeight(1)
 
      // Text(`${}/${}`)
 
      Row() {
        Button('取消').onClick(() => {
          this.isShowPhotoCom = false
        })
        Text(`已选${this.selectList.length}张/最多选择${this.maxSelectNum}张`)
 
        Button('确认')
          .onClick(() => {
            this.showSelectImgs = this.selectList
            this.isShowPhotoCom = false
 
          })
      }
      .width('100%')
      .height(60)
 
      .justifyContent(FlexAlign.SpaceAround)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.White)
    .justifyContent(FlexAlign.SpaceBetween)
 
  }
}
 
// 查看图片的组件
@CustomDialog
struct PreviewDilog {
  controller: CustomDialogController = new CustomDialogController({ builder: CustomDialogController })
  url: ResourceStr | string = ''
 
  build() {
    Column() {
      Image(this.url)
        .width('100%')
 
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Black)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.controller.close()
    })
 
  }
}

与上一篇的不同之处就在于 这篇代码使用了半模态弹层 就是点击选择图片之后 弹窗是从底部弹起的 类似于ios那种效果

重点代码截图

需求4. HarmonyOs半模态bindsheet编写一个案例实现一个照片选择并可swiper滑动 并实现点那张展开就是哪张

TypeScript 复制代码
import { GoodItem } from '../06/modules';
 
@Entry
@Component
struct PhotoCasePage {
  @State message: string = '实现一个半模态相册';
  @State List: GoodItem[] = [{
 
    goods_name: 'dsfjlsjkfsf',
    goods_price: 100,
    goods_img: 'https://img1.baidu.com/it/u=1535232938,2370569369&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800',
    goods_count: 1,
    id: 1
 
  },
    {
 
      goods_name: 'dfhlsdjflkdsjklfs 加速度的佛教山東i附件',
      goods_price: 200,
      goods_img: 'https://img1.baidu.com/it/u=2603934083,3021636721&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 2,
      id: 2
 
    },
    {
 
      goods_name: '收到回复技术大会哦恶化日发方大化工iu而韩国佛热',
      goods_price: 300,
      goods_img: 'https://img0.baidu.com/it/u=4289818793,3552718550&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
      goods_count: 3,
      id: 3
 
    }
    , {
 
      goods_name: '的時間佛薩飛機埃里克森放假哦i二fore多氟多化工i額方法過後i額外人',
      goods_price: 400,
      goods_img: 'https://img0.baidu.com/it/u=2080725050,2021436341&fm=253&fmt=auto&app=138&f=JPEG?w=1200&h=800',
      goods_count: 4,
      id: 4
 
    }
    , {
 
      goods_name: '时间佛ID分机构IE',
      goods_price: 500,
      goods_img: 'https://img1.baidu.com/it/u=4202924242,2178453218&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800',
      goods_count: 5,
      id: 5
 
    }
    , {
 
      goods_name: '司法鉴定哦is叫哦私人',
      goods_price: 600,
      goods_img: 'https://10wallpaper.com/wallpaper/1680x1050/1405/Lavender_mountain_river-Landscape_HD_Wallpaper_1680x1050.jpg',
      goods_count: 6,
      id: 6
 
    }
  ]
  @State isShowPhotoCom: boolean = false
  @State maxSelectNum: number = 4
  @State showSelectImgs: GoodItem[] = []
  @State selectImage: ResourceStr | string = ''
  @State setlectIndex: number = 0
  previw: CustomDialogController = new CustomDialogController({
    builder: PreviewDilog({ url: this.showSelectImgs, setlectIndex: this.setlectIndex, }),
    customStyle: true
 
 
  })
 
  @Builder
  sheetBuilder() {
    Column() {
 
 
      photoCom({
        List: this.List,
        isShowPhotoCom: this.isShowPhotoCom,
        maxSelectNum: this.maxSelectNum,
        showSelectImgs: this.showSelectImgs
 
      })
 
 
    }
  }
 
  build() {
    Column() {
      Button('选择图片')
        .onClick(() => {
          this.isShowPhotoCom = true
        })
      Grid() {
        ForEach(this.showSelectImgs, (item: GoodItem, index: number) => {
          GridItem() {
            Image(item.goods_img)
              .aspectRatio(1)
              .onClick(() => {
                this.setlectIndex = index
                this.previw.open()
              })
          }
 
        })
      }
      .columnsTemplate('1fr 1fr')
      .columnsGap(4)
      .rowsGap(4)
 
    }
    .height('100%')
    .width('100%')
    .bindSheet($$this.isShowPhotoCom, this.sheetBuilder, {
      showClose: false
    })
  }
}
 
// 选择图片组件
@Component
struct photoCom {
  @Prop List: GoodItem[] = []
  @Link isShowPhotoCom: boolean
  @State selectList: GoodItem[] = []
  @Prop maxSelectNum: number
  @Link showSelectImgs: GoodItem[]
 
  // 选择图片逻辑
  selectFn(item: GoodItem) {
 
    let Index = this.selectList.findIndex(obj => obj.id == item.id)
    console.log(JSON.stringify(Index))
    if (Index > -1) {
      this.selectList.splice(Index, 1)
 
    } else {
      this.selectList.push(item)
    }
  }
 
  build() {
    Column() {
      Grid() {
        ForEach(this.List, (item: GoodItem, index) => {
          GridItem() {
            Stack() {
              Image(item.goods_img)
                .aspectRatio(1)
 
 
              if (this.selectList.some(obj => obj.id == item.id)) {
                Image($r('app.media.select'))
                  .width(60)
                  .height(60)
                  .fillColor(Color.Red)
              }
            }
            .onClick(() => {
              this.selectFn(item)
            })
 
          }
        })
      }
      .columnsTemplate('1fr 1fr')
      .layoutWeight(1)
 
      // Text(`${}/${}`)
 
      Row() {
        Button('取消').onClick(() => {
          this.isShowPhotoCom = false
        })
        Text(`已选${this.selectList.length}张/最多选择${this.maxSelectNum}张`)
 
        Button('确认')
          .onClick(() => {
            this.showSelectImgs = this.selectList
            this.isShowPhotoCom = false
 
          })
      }
      .width('100%')
      .height(60)
 
      .justifyContent(FlexAlign.SpaceAround)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.White)
    .justifyContent(FlexAlign.SpaceBetween)
 
  }
}
 
// 查看图片的组件
@CustomDialog
struct PreviewDilog {
  controller: CustomDialogController = new CustomDialogController({ builder: CustomDialogController })
  url: GoodItem[] = []
  @Link setlectIndex: number
 
  build() {
    Column() {
      Swiper() {
        ForEach(this.url, (item: GoodItem) => {
 
          Image(item.goods_img)
            .width('100%')
 
        })
      }.loop(true)
      .index($$this.setlectIndex)
 
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Black)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.controller.close()
    })
 
  }
}

重点代码部分

注:传值发生了改变 在之前传值是传一张 然后再半模态显示出来 现在是传选中的那个数组 然后记录下点击的那个index 里边用swiper组件就可以了

相关推荐
草字9 分钟前
uniapp input限制输入负数,以及保留小数点两位.
java·前端·uni-app
MapleLea1f22 分钟前
26届JAVA 学习日记——Day14
java·开发语言·学习·tcp/ip·程序人生·学习方法
小汤猿人类23 分钟前
SpringTask
开发语言·python
没有黑科技28 分钟前
基于web的音乐网站(Java+SpringBoot+Mysql)
java·前端·spring boot
爪哇学长30 分钟前
解锁API的无限潜力:RESTful、SOAP、GraphQL和Webhooks的应用前景
java·开发语言·后端·restful·graphql
老赵的博客37 分钟前
QT 自定义界面布局要诀
开发语言·qt
前端初见37 分钟前
彻底搞懂前端环境变量使用和原理
前端
小王码农记1 小时前
vue中路由缓存
前端·vue.js·缓存·typescript·anti-design-vue
p-knowledge1 小时前
建造者模式(Builder Pattern)
java·开发语言·建造者模式
大G哥1 小时前
我用豆包MarsCode IDE 做了一个 CSS 权重小组件
前端·css