HarmonyOS鸿蒙Next中不使用系统自带的图片选择器,如何选择图片,有特定的UI

HarmonyOS鸿蒙Next中不使用系统自带的图片选择器,如何选择图片,有特定的UI 不提供 ohos.permission.READ_IMAGEVIDEO 权限,如何能显示本地图片/视频列表,需要根据日期进行分组显示,图片UI会根据特定的条件有所不同,实现如下图效果

cke_277.png


更多关于HarmonyOS鸿蒙Next中不使用系统自带的图片选择器,如何选择图片,有特定的UI的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

楼主如果要在不申请ohos.permission.READ_IMAGEVIDEO权限且不使用系统图片选择器的情况下实现本地图片/视频列表的展示与分组,那么由于你未申请媒体库权限,应用仅能访问沙箱内文件而无法直接读取系统相册内容。因此要通过文件管理API操作沙箱目录内的媒体文件。然后通过解析文件名或管理自定义元数据实现日期分组逻辑,而不用依赖系统媒体库的元数据。

我觉得下面步骤可行。

遍历文件和获取元数据

import fileio from '@ohos.fileio';
import fileUri from '@ohos.fileuri';

// 获取沙箱路径并转换为URI
let sandboxPath = getContext().filesDir; // 这里以应用私有目录为例
let uri = fileUri.getUriFromPath(sandboxPath);

// 遍历目录并筛选媒体文件
let dir = fileio.opendirSync(uri.path);
let fileList: Array<string> = [];
let entry = fileio.readdirSync(dir);

while (entry !== undefined) {
  if (isMediaFile(entry.name)) { // 自定义函数判断是否为图片/视频
    let filePath = uri.path + '/' + entry.name;
    let stat = fileio.statSync(filePath);
    fileList.push({
      path: 'file://' + filePath,
      modifyTime: stat.mtime // 使用修改时间作为分组依据
    });
  }
  entry = fileio.readdirSync(dir);
}

按日期分组数据结构

// 将文件按日期分组
let groupedFiles: Map<string, Array<FileItem>> = new Map();
fileList.forEach(item => {
  let dateKey = formatDate(item.modifyTime); // 自定义日期格式化函数
  if (!groupedFiles.has(dateKey)) {
    groupedFiles.set(dateKey, []);
  }
  groupedFiles.get(dateKey)?.push(item);
});

实现自定义分组UI

// 使用List组件实现分组布局
List({ space: 10 }) {
  ForEach(Array.from(groupedFiles.keys()), (dateKey: string) => {
    ListItem() {
      Column() {
        // 日期标题
        Text(dateKey)
          .fontSize(18)
          .padding(10)
        
        // 图片/视频缩略图列表
        Grid() {
          ForEach(groupedFiles.get(dateKey), (item: FileItem) => {
              GridItem() {
                Image(item.path)
                  .aspectRatio(1)
                  .borderRadius(8)
                  .overlay(CustomConditionUI(item)) // 根据条件叠加自定义UI
              }
          })
        }
        .columnsTemplate('1fr 1fr 1fr')
      }
    }
  })
}

UI部分楼主可以再按照样式修改。

更多关于HarmonyOS鸿蒙Next中不使用系统自带的图片选择器,如何选择图片,有特定的UI的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


无法直接拿取数据执行做排序,可以提交相关需求,后期官方加入。目前只能改变基础ui使用 使用PhotoPicker组件访问图片/视频

可以使用 ‘@kit.MediaLibraryKit’ 进行获取

import photoAccessHelper from '[@kit](/user/kit).MediaLibraryKit';

// 获取相册助手实例
const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);

// 查询相册中的图片
async function getPhotos() {
  let fetchOptions = {
    selections: `${photoAccessHelper.PhotoKeys.MEDIA_TYPE} = ?`,
    selectionArgs: [photoAccessHelper.PhotoType.IMAGE.toString()]
  };
  let photos = await phAccessHelper.getAssets(fetchOptions);
  return photos; // 返回图片资源集合
}

文档地址

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/component-guidelines-albumpicker

没权限又不用图片选择器肯定拿不到 拿得到还有用户隐私可言么

在HarmonyOS Next中,要自定义图片选择器UI,可以使用PhotoViewPickerPhotoAccessHelper能力。通过PhotoAccessHelper获取设备相册权限和图片列表,然后自定义UI展示图片。关键步骤:

  1. 申请ohos.permission.READ_IMAGEVIDEO权限
  2. 使用PhotoAccessHelper.getPhotoAccessHelper()创建helper实例
  3. 调用getAssets()获取图片资源
  4. 通过fetchResult()遍历图片列表
  5. 自定义UI组件展示图片缩略图(使用Image组件)

选择图片时通过PhotoViewPicker.select()回调返回选中图片的URI。整个过程无需依赖系统默认UI。

在HarmonyOS Next中,如果不使用系统自带的图片选择器,可以通过以下方式实现自定义图片选择功能:

  1. 使用FilePicker API获取媒体文件URI:
import picker from '@ohos.file.picker';

async function selectImages() {
  const photoSelectOptions = new picker.PhotoSelectOptions();
  photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
  
  const photoPicker = new picker.PhotoViewPicker();
  return await photoPicker.select(photoSelectOptions);
}
  1. 自定义UI实现分组显示:
  • 使用媒体库查询API获取图片元数据
  • 按日期分组处理数据
  • 使用List组件实现瀑布流布局
  1. 关键代码示例:
// 获取图片列表
const fetchImages = async () => {
  const result = await mediaLibrary.getMediaAssets({
    selections: mediaLibrary.FileKey.MEDIA_TYPE + '=?',
    selectionArgs: [mediaLibrary.MediaType.IMAGE.toString()],
    order: mediaLibrary.FileKey.DATE_ADDED + ' DESC'
  });
  
  // 按日期分组
  const grouped = groupByDate(result);
  return grouped;
};

// 自定义List组件
@Component
struct ImageGrid {
  @State groupedImages: Map<string, Array<ImageItem>> = new Map()
  
  build() {
    List() {
      ForEach(Array.from(this.groupedImages.keys()), (date) => {
        ListItem() {
          Column() {
            Text(date)
            // 自定义图片显示逻辑
            ImageGridSection({images: this.groupedImages.get(date)})
          }
        }
      })
    }
  }
}
  1. 注意事项:
  • 需要申请ohos.permission.READ_MEDIA权限
  • 对于大图加载建议使用图片缓存机制
  • 日期分组处理建议使用Luxon等日期库

这种方式可以完全自定义UI,同时满足按日期分组显示的需求。

回到顶部