鸿蒙实现仿微信朋友圈发布九宫格选择图片效果

前言:

DevEco Studio版本:4.0.0.600

API:10

在安卓中实现仿微信朋友圈这样的效果是通过RecyclerView+自定义ItemTouchHelper来实现,下面文章就介绍如何通过鸿蒙的方式实现这样的效果

效果:

     

实现原理分析

1、实现3x3九宫格布局:

        可以通过Arkts中的Grid/GridItem组件来实现,设置Grid().columnsTemplate('1fr 1fr 1fr')

2、实现拖拽效果

        通过查看Grid/GridItem组件相关api文档,发现存在editMode属性方法设置为true可以拖动内部GridItem子控件。并且通过onItemDragStart、onItemDragMove、onItemDrop等事件方法监听拖动的过程。

参考链接:OpenHarmony Grid

3、拖动后将数组内数据对换

        新建一个temp用于数组元素实现数据对换

4、监听拖动事件,实现底部删除效果

        通过onItemDragStart、onItemDrop拖动开始和拖动结束事件监听方法来控制底部删除效果的显示和隐藏

代码实现:

1、实现九宫格布局

Grid() {
   ForEach(this.numbers, (imageBean: ImageSelectBean) => {
      GridItem() {
         this.pixelMapBuilder(imageBean)
      }
   })
}
.columnsTemplate('1fr 1fr 1fr')//三等分
.columnsGap(10) //列之间间距
.rowsGap(10) //行之间间距
.supportAnimation(true)
.width('90%')
.height(450)
.margin({ top: 20 })
.backgroundColor(0xFAEEE0)

pixelMapBuilder实现

@Builder
pixelMapBuilder(image: ImageSelectBean) { //拖拽过程样式
   Image(image.imageUrl)
      .width(130)
      .height(130)
      .onClick(() => {
         if (image.isAdd) {
            this.getFileAssetsFromType()
         }
      })
}

2、实现拖拽效果,并设置监听

Grid() {
   //...省略的代码
}
.editMode(true) //设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => { //第一次拖拽此事件绑定的组件时,触发回调。
   if (!this.numbers[itemIndex].isAdd) {
      animateTo({ duration: 600 }, () => {
         this.offsetY = 0
      })
      return this.pixelMapBuilder(this.numbers[itemIndex]) //设置拖拽过程中显示的组件。
   }
})
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { //绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调。
   // isSuccess=false时,说明drop的位置在grid外部;insertIndex > length时,说明有新增元素的事件发生,this.numbers[insertIndex].isAdd==true,说明是添加按钮
   console.info('1111111111  onItemDrop ' + itemIndex + '  insertIndex:', insertIndex + '  isSuccess: ' + isSuccess + "  event  x: " + event.x + " y: " + event.y) //itemIndex拖拽起始位置,insertIndex拖拽插入位置
   
   if (!isSuccess || insertIndex >= this.numbers.length || this.numbers[insertIndex].isAdd) {
      return
   }
})

3、在拖拽结束,对换数组内元素

.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
   this.changeIndex(itemIndex, insertIndex)
})


changeIndex(index1: number, index2: number) { //交换数组位置
    let temp: ImageSelectBean;
    temp = this.numbers[index1];
    this.numbers[index1] = this.numbers[index2];
    this.numbers[index2] = temp;
}

4、实现底部删除效果

给底部删除布局设置偏移量(offset方法),来动态控制隐藏和显示效果

UI布局

Stack() {
   Text('拖到此处删除')
      .fontSize(15)
      .fontColor(Color.White)
}
.width('100%')
.height(60)
.flexShrink(1)
.backgroundColor(Color.Pink)
.offset({ x: 0, y: this.offsetY })

动态设置偏移量

//拖拽开始,显示删除布局
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => { 
   if (!this.numbers[itemIndex].isAdd) {
      animateTo({ duration: 600 }, () => {
         this.offsetY = 0
      })
      return this.pixelMapBuilder(this.numbers[itemIndex]) //设置拖拽过程中显示的图片。
   }
})


//拖拽结束,隐藏删除布局
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
   animateTo({ duration: 600 }, () => {
      this.offsetY = 60
   })
   if (!isSuccess || insertIndex >= this.numbers.length || this.numbers[insertIndex].isAdd) {
      return
   }
   this.changeIndex(itemIndex, insertIndex)
})

5、选择图片方法实现

//选择图片
getFileAssetsFromType() {
   let selectNumber = this.maxSelectNumber - this.numbers.length + 1

   let photoViewPicker = new picker.PhotoViewPicker();
   const photoSelectOptions = new picker.PhotoSelectOptions(); // 创建图库对象实例
   photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 选择媒体文件类型为Image
   photoSelectOptions.maxSelectNumber = selectNumber < 0 ? 0 : selectNumber; // 选择媒体文件的最大数目
   photoViewPicker.select(photoSelectOptions)
      .then((photoSelectResult) => {
         this.imgDatas = photoSelectResult.photoUris; // select返回的uri权限是只读权限,需要将uri写入全局变量@State中即可根据结果集中的uri进行读取文件数据操作。
         console.info('1111111111  选择图片: ' + JSON.stringify(this.imgDatas));
         for (let i = this.imgDatas.length - 1; i >= 0; i--) {
            console.info('1111111111  forEach 选择图片: ' + this.imgDatas[i]);
            let imageBean = new ImageSelectBean(this.imgDatas[i], false)
            let unShiftLength = this.numbers.unshift(imageBean)
            if (unShiftLength > 9) {
               this.numbers.pop()
            }
         }
      })
      .catch((err: BusinessError) => {
         console.info('1111111111  选择图片出错: ' + err.message);
      })
}

因为图片选择涉及到'ohos.permission.READ_MEDIA', 'ohos.permission.WRITE_MEDIA'两个权限,需要在module.json5文件中配置。另外这两个权限是隐私权限需要通过requestPermissionsFromUser方法动态申请权限。

动态申请权限参考链接:OpenHarmony 权限申请介绍

在aboutToAppear初始化方法中申请权限

ImageSelectBean类

export class ImageSelectBean {
   imageUrl: string//图片地址
   isAdd: boolean//是否是添加按钮

   constructor(imageUrl: string, isAdd: boolean) {
      this.imageUrl = imageUrl
      this.isAdd = isAdd
   }
}

6、实现数据删除

1、给删除布局设置onAreaChange监听获取Y轴坐标位置。

2、给最外层父控件设置触摸监听,在手指滑动到删除区域时,改变文字为:‘松手即可删除’,手指抬起时执行数据元素删除,并判断是否添加按钮是否显示,未显示显示添加按钮。

onAreaChange监听:

Stack()
.onAreaChange((oldValue: Area, newValue: Area) => {
   console.info("1111111111   oldValue----height: " + oldValue.height + "   oldValue:  y:" + oldValue.position.y
      + "   newValue  y:" + newValue.position.y)
   this.stackY = newValue.position.y as number
})

父控件设置onTouch触摸监听

父控件().onTouch((event) => this.touchEvent(event))


touchEvent(event: TouchEvent) {
   switch (event.type) {
      case TouchType.Move: // 手指移动
         console.info('1111111111   手指移动: ' + event.touches[0].y)
         if (event.touches[0].y + 65 > this.stackY) {
            this.stackContent = '松手即可删除'
         } else {
            this.stackContent = '拖到此处删除'
         }
         break
      case TouchType.Up: // 手指抬起
      case TouchType.Cancel: // 触摸意外中断
         console.info('1111111111   手指抬起: ' + event.touches[0].y)
         if (event.touches[0].y + 65 > this.stackY) {
            this.numbers.splice(this.startIndex, 1)
            if (!this.showAdd && this.numbers.length < 9) {
               let imageSelectBean = new ImageSelectBean('images/add.png', true)
               this.numbers.push(imageSelectBean)
               this.showAdd = true
            }
         }
         break
   }
}

  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现仿微信朋友圈九宫格相册,你可以使用Android实现的一个开源项目,该项目提供了九宫格图片的预览、拖动、放大、左右滑动和长按保存到手机的功能。你可以在GitHub上找到该项目的源码,点击链接\[1\]即可下载。此外,还有一篇教程介绍了如何使用Django来实现仿微信朋友圈九宫格相册,该教程会分成两部分发布,你可以持续关注\[2\]。在该教程中,你需要对Python、Django、HTML、CSS和Javascript有一定的了解。如果你对RecyclerView的适配器RvAdapter.java感兴趣,可以参考其中的代码实现\[3\]。 #### 引用[.reference_title] - *1* *3* [Android 实现仿微信朋友圈九宫格图片+NineGridView+ImageWatcher(图片查看:1.预览,2.拖动,3.放大,4.左右...](https://blog.csdn.net/qq_35091074/article/details/123085791)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [世界那么大,我想去看看。Django仿微信朋友圈九宫格相册(1)](https://blog.csdn.net/weixin_42134789/article/details/80656306)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等风起了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值