写点什么

鸿蒙 Next 仿微信朋友圈图片排序删除

作者:auhgnixgnahz
  • 2025-06-23
    北京
  • 本文字数:5844 字

    阅读完需:约 19 分钟

上一篇介绍了 Grid 的图片拖拽排序,这篇加一下拖拽到底部删除图片的功能,仿微信,但是还不是很完美,以后再完善,看一下成果和代码:


Page 代码:

import { CustomContentDialog, display } from "@kit.ArkUI"import Logger from "../utils/Logger";
let displayWidthVp = px2vp(display.getDefaultDisplaySync().width);let displayHeightVp = px2vp(display.getDefaultDisplaySync().height);
@Builderexport function PublishViewBuilder() { PublishView()}
@Entry@ComponentV2struct PublishView { @Local inputContent: string = '' @Local htmlste: string = '' @Local imgs: string[] = [] @Local showDeleteImg:boolean =false pathStack: NavPathStack = new NavPathStack() inputstr:string='' selectImgWigth :number = Math.ceil((displayWidthVp-20)/3); contentHeight:number=0; @Builder buildContent(): void { Column() { TextInput({placeholder:'输入地址'}).onChange((e)=>{ this.inputstr=e }) }.padding({left:10,right:10}) .width('100%') } dialogController: CustomDialogController = new CustomDialogController({ builder: CustomContentDialog({ primaryTitle: '标题', secondaryTitle: '辅助文本', contentBuilder: () => { this.buildContent(); }, buttons: [ { value: '取消', buttonStyle: ButtonStyleMode.TEXTUAL, action: () => { this.inputstr='' this.dialogController.close() } }, { value: '确定', buttonStyle: ButtonStyleMode.TEXTUAL, action: () => { this.htmlste=this.inputstr this.dialogController.close() } } ], }), }); //拖拽过程样式 @Builder pixelMapBuilder(imgSource:string) { Image(imgSource).objectFit(ImageFit.Cover).width(this.selectImgWigth).height(this.selectImgWigth) .draggable(false) } @Builder gridItem(item:number){ Image(item).objectFit(ImageFit.Cover).width('90%').height('90%') .draggable(false) }
build() { NavDestination() { Column({ space: 5 }) { Row() { Image($r('app.media.ic_about_return')).width(20).height(20).objectFit(ImageFit.Contain) .onClick(() => { this.pathStack.pop() }) Text('发表动态').fontSize(20) Text('发送').fontSize(20)
} .alignItems(VerticalAlign.Bottom) .backgroundColor(Color.White) .height('10%') .width('100%') .justifyContent(FlexAlign.SpaceBetween) .padding({ left: 10, right: 10, bottom: 20 })
TextArea({ placeholder: '欢迎关注HarmonyOS开发者笔记共同学习进步' }).width('100%')//去除默认圆角矩形背景 .backgroundColor(Color.Transparent) .padding(10) .onChange((value: string) => { this.inputContent = value })
Text(this.htmlste) .width('100%') .textOverflow({ overflow: TextOverflow.Ellipsis }) .maxLines(2) .fontColor(Color.Blue) .fontSize(20) .backgroundColor(Color.Gray) Stack(){
} Grid() { ForEach(this.imgs, (item: string,index:number) => { GridItem() { Image(item).objectFit(ImageFit.Cover).width(this.selectImgWigth*0.9).height(this.selectImgWigth*0.9) .draggable(false) } }, (item: string) => item) } .width('100%') .height(Math.ceil(this.imgs.length/3)*this.selectImgWigth) .columnsTemplate('1fr 1fr 1fr') // .maxCount(9) // .layoutDirection(GridDirection.Row) // .columnsGap(10) .rowsGap(10) .padding({ left: 10, right: 10 }) .editMode(true) .supportAnimation(true) //第一次拖拽此事件绑定的组件时,触发回调。 .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { Logger.info('========onItemDragStart','x: '+event.x+'y: '+event.y+'itemIndex:'+itemIndex) //设置拖拽过程中显示的图片。 return this.pixelMapBuilder(this.imgs[itemIndex]); }) .onItemDragMove((event: ItemDragInfo, itemIndex: number, insertIndex: number) => { this.showDeleteImg = false Logger.info('========onItemDragMove','x: '+event.x+'y: '+event.y+'屏幕高:'+displayHeightVp) }) .onItemDragLeave((event: ItemDragInfo, itemIndex: number)=>{ this.showDeleteImg = true Logger.info('========onItemDragLeave','x: '+event.x+'y: '+event.y) }) //当在本组件范围内停止拖拽行为时,触发回调。 .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { Logger.info('========onItemDrop','x: '+event.x+'y: '+event.y+'itemIndex:'+itemIndex)
if (event.y>(this.contentHeight-40)){ this.imgs.splice(itemIndex,1) this.showDeleteImg = false return }
if (!isSuccess || insertIndex >= this.imgs.length) { return; } this.changeIndex(itemIndex, insertIndex); }) Image($r('app.media.icon_add_pic')).width(this.selectImgWigth*0.9).height(this.selectImgWigth*0.9).onClick(() => { this.pathStack.pushPath({ name: 'photoPicker', onPop: (popInfo: PopInfo) => { let selectUris: Array<string> = popInfo.result as Array<string> if (null != selectUris.length) { this.imgs = [] for (let str of selectUris) { this.imgs.push(str) } } } }) }).visibility(this.imgs.length>8?Visibility.None:Visibility.Visible) .draggable(false).margin({left:10})
Divider().width('100%').height(1).color('#ffe9f0f0')
Column(){ Row(){ Text('拖到此处即可删除').fontColor(Color.White) }.backgroundColor(Color.Red).width('100%').height(40).justifyContent(FlexAlign.Center) .visibility(this.showDeleteImg?Visibility.Visible:Visibility.None) }.width('100%').layoutWeight(1).justifyContent(FlexAlign.End)
}.width('100%').height('100%') .alignItems(HorizontalAlign.Start) .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) =>{ this.contentHeight = newValue.height as number }) }.backgroundColor(Color.White).hideTitleBar(true).hideToolBar(true) .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack }) } //拖拽之后改变元素位置 changeIndex(index1: number, index2: number) { //这种方式可以保存移动过程中的其他元素位置变化 let tmp = this.imgs.splice(index1, 1); this.imgs.splice(index2, 0, tmp[0]); }}</string></string>
复制代码

选取照片组件:

import {  PhotoPickerComponent,  PickerController,  PickerOptions,  BaseItemInfo,  ItemInfo,  PhotoBrowserInfo,  ItemType,  ClickType,  MaxCountType,  ReminderMode,} from '@ohos.file.PhotoPickerComponent';import photoAccessHelper from '@ohos.file.photoAccessHelper';

@Builderexport function PhotoPickerBuilder() { PhotoPicker()}@ComponentV2struct PhotoPicker{ pathStack: NavPathStack = new NavPathStack() // 组件初始化时设置参数信息 pickerOptions: PickerOptions = new PickerOptions();
// 已选择的图片 @Local selectUris: Array<string> = new Array<string>();
//目前选择的图片 @Local currentUri: string = '';
//是否显示大图 @Local isBrowserShow: boolean = false;
aboutToAppear() { // 设置picker宫格页数据类型 this.pickerOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE // 图片和照片都显示; // 最大选择数量 this.pickerOptions.maxSelectNumber = 6; // 超出最大选择数量时 this.pickerOptions.maxSelectedReminderMode = ReminderMode.TOAST; // 是否展示搜索框,默认false this.pickerOptions.isSearchSupported = false; // 是否支持拍照,默认false this.pickerOptions.isPhotoTakingSupported = true;
}
// 资源被选中回调,返回资源的信息,以及选中方式 private onItemClicked(itemInfo: ItemInfo, clickType: ClickType): boolean { if (!itemInfo) { return false; } let type: ItemType | undefined = itemInfo.itemType; let uri: string | undefined = itemInfo.uri; if (type === ItemType.CAMERA) { // 点击相机item return true; // 返回true则拉起系统相机,若应用需要自行处理则返回false。 } else { if (clickType === ClickType.SELECTED) { // 应用做自己的业务处理 if (uri) { this.selectUris.push(uri); this.pickerOptions.preselectedUris = [...this.selectUris]; } return true; // 返回true则勾选,否则则不响应勾选。 } else { if (uri) { this.selectUris = this.selectUris.filter((item: string) => { return item != uri; }); this.pickerOptions.preselectedUris = [...this.selectUris]; } } return true; } }
// 进入大图的回调 private onEnterPhotoBrowser(photoBrowserInfo: PhotoBrowserInfo): boolean { this.isBrowserShow = true; return true; }
// 退出大图的回调 private onExitPhotoBrowser(photoBrowserInfo: PhotoBrowserInfo): boolean { this.isBrowserShow = false; return true; }
// 接收到该回调后,便可通过pickerController相关接口向picker发送数据,在此之前不生效。 private onPickerControllerReady(): void { }
// 大图左右滑动的回调 private onPhotoBrowserChanged(browserItemInfo: BaseItemInfo): boolean { this.currentUri = browserItemInfo.uri ?? ''; return true; }
// 已勾选图片被删除时的回调 private onSelectedItemsDeleted(baseItemInfos: Array<baseiteminfo>): void { }
// 超过最大选择数量再次点击时的回调 private onExceedMaxSelected(exceedMaxCountType: MaxCountType): void { }
// 当前相册被删除时的回调 private onCurrentAlbumDeleted(): void { } build() { NavDestination(){ Column(){ Row(){ Button('返回').onClick(()=>{ this.pathStack.pop() }) Button('确定').onClick(()=>{ this.pathStack.pop(this.selectUris) })
}.width('100%').justifyContent(FlexAlign.SpaceBetween)
PhotoPickerComponent({ pickerOptions: this.pickerOptions, onItemClicked: (itemInfo: ItemInfo, clickType: ClickType): boolean => this.onItemClicked(itemInfo, clickType), onEnterPhotoBrowser: (photoBrowserInfo: PhotoBrowserInfo): boolean => this.onEnterPhotoBrowser(photoBrowserInfo), onExitPhotoBrowser: (photoBrowserInfo: PhotoBrowserInfo): boolean => this.onExitPhotoBrowser(photoBrowserInfo), onPickerControllerReady: (): void => this.onPickerControllerReady(), onPhotoBrowserChanged: (browserItemInfo: BaseItemInfo): boolean => this.onPhotoBrowserChanged(browserItemInfo), onSelectedItemsDeleted: (BaseItemInfo: Array<baseiteminfo>) => this.onSelectedItemsDeleted(BaseItemInfo), onExceedMaxSelected: (exceedMaxCountType: MaxCountType) => this.onExceedMaxSelected(exceedMaxCountType), onCurrentAlbumDeleted: () => this.onCurrentAlbumDeleted(), pickerController: new PickerController(), }) } }.backgroundColor(Color.White).hideTitleBar(true).hideToolBar(true) .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack }) }}</baseiteminfo></baseiteminfo></string></string>
复制代码


目前的缺陷:


1.Grid 设置拖动时 onItemDragStart 默认时间是 170 毫秒,因此不能立马响应,官网给出的解决办法测试了,也不是很完美,需要再研究一下


2.添加图片的 icon 没有和 Grid 绑定在一起


3.底部落入区域的图层没有放到图片上层


如果看到的各位大佬有解决办法,欢迎留言,私信,感谢!!!


发布于: 刚刚阅读数: 2
用户头像

auhgnixgnahz

关注

还未添加个人签名 2018-07-10 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙Next仿微信朋友圈图片排序删除_鸿蒙Next_auhgnixgnahz_InfoQ写作社区