跳到主要内容

使用PhotoPicker组件访问图片/视频

当应用需要读取用户图片时,开发者可以在应用界面中嵌入PhotoPicker组件,在用户选择所需要的图片资源后,直接返回该图片资源,而不需要授予应用读取图片文件的权限,即可完成图片或视频文件的访问和读取。

界面效果如图所示。

宫格页大图页

开发步骤

  1. 导入PhotoPicker模块文件。

    import {
    PhotoPickerComponent,
    PickerController,
    PickerOptions,
    DataType,
    BaseItemInfo,
    ItemInfo,
    PhotoBrowserInfo,
    ItemType,
    ClickType,
    MaxCountType,
    PhotoBrowserRange,
    ReminderMode,
    photoAccessHelper
    } from '@kit.MediaLibraryKit';
  2. 创建Picker组件配置选项实例(PickerOptions)和控制实例(PickerController)。

    通过PickerOptions,开发者可配置Picker宫格的样式(如勾选框背景色、文本颜色等)、滑动预览方向、最大选择数量等参数,详见PickerOptions API参考

    通过PickerController,应用可向Picker组件发送数据。

    // 组件初始化时设置参数信息。
    pickerOptions: PickerOptions = new PickerOptions();

    // 组件初始化完成后,可控制组件部分行为。
    @State pickerController: PickerController = new PickerController();

    // 宫格图内已选择的图片uri数组。
    @State selectUris: Array<string> = new Array<string>();

    // 目前选择的图片uri。
    @State currentUri: string = '';

    // 标识当前是否显示大图页面,false表示不显示大图页面,true表示显示大图页面。
    @State isBrowserShow: boolean = false;
  3. 应用界面出现时,初始化组件配置选项实例(PickerOptions)。

    此处仅列举实例用到的参数,当前支持的配置项及其取值范围详见PickerOptions API参考

    // 设置picker宫格页可选择的媒体文件类型,这里设置图片和视频类型。
    this.pickerOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
    // 设置宫格页内资源的最大选择数量,示例设置为5。
    this.pickerOptions.maxSelectNumber = 5;
    // 选择数量达到最大时的提示方式,示例设置为弹窗提示。
    this.pickerOptions.maxSelectedReminderMode = ReminderMode.TOAST;
    // 设置picker页面内是否需要展示搜索框,false为不展示。
    this.pickerOptions.isSearchSupported = true;
    // 将宫格页面内第一个宫格置为拍照按钮,false为不展示拍照按钮。
    this.pickerOptions.isPhotoTakingSupported = true;
  4. 实现回调函数。

    通过实现以下回调事件,可在用户在界面操作时,将相关信息报给应用进行处理。

    • 进退大图、切换大图回调,上报的大图相关信息详见PhotoBrowserInfo

    • 勾选图片/视频,将上报图片URI供应用使用。

      • 回调返回的所有URI均为只读URI,开发者可以根据结果集中的URI读取文件数据。但不能在Picker的回调中直接使用此URI打开文档,需要定义一个全局变量保存URI,样例可参考指定URI读取文件数据指定URI获取图片或视频资源
      • 如需获取元数据,可通过文件管理文件URI接口,根据uri获取部分文件属性信息,比如文件大小、访问时间、修改时间、文件名、文件路径等。
    • 点击图片(缩略图item),将上报图片/视频信息ItemInfo

    • 点击相机item,可默认拉起系统相机或应用自行处理。如何自行拉起相机请参考cameraPicker.pick

    支持的回调事件及其参数请参考PhotoPickerComponent API参考

    // 资源被选中回调,返回资源的信息,以及选中方式。
    // 应用根据自己的业务来决定,资源是否勾选或者是否进入系统相机。
    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) {
    // 如果宫格页面第一个宫格的类型为ItemType.CAMERA,则是相机按钮。
    // 返回true则拉起系统相机;如果返回false应用可以自己拉起相机。
    return true;
    } else {
    // 如果是选中操作。
    if (clickType === ClickType.SELECTED) {
    // 应用做自己的业务处理。
    if (uri) {
    this.selectUris.push(uri);
    this.pickerOptions.preselectedUris = [...this.selectUris];
    }
    // 返回true则该宫格响应勾选,否则不响应勾选。
    return true;
    } else {
    // 如果是取消选中操作。
    // 应用做自己的业务处理。
    if (uri) {
    this.selectUris = this.selectUris.filter((item: string) => {
    return item != uri;
    });
    this.pickerOptions.preselectedUris = [...this.selectUris];
    }
    // 返回true则该宫格响应取消勾选,否则不响应取消勾选。
    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 {
    let elements: number[] = [PhotoBrowserUIElement.BACK_BUTTON];
    this.pickerController.setPhotoBrowserUIElementVisibility(elements, false); // 设置大图页不显示返回按钮。
    }

    // 大图左右滑动的回调。
    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 {
    }
  5. 创建PhotoPickerComponent组件。

    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: this.pickerController,
    })
  6. 通过PickerController向Picker组件发送数据,实现控制PhotoPickerComponent组件行为。

    存在多种用法,详见PickerControllerAPI文档。

完整示例

import {
PhotoPickerComponent,
PickerController,
PickerOptions,
DataType,
BaseItemInfo,
ItemInfo,
PhotoBrowserInfo,
ItemType,
ClickType,
MaxCountType,
PhotoBrowserRange,
ReminderMode,
photoAccessHelper
} from '@kit.MediaLibraryKit';

@Entry
@Component
struct PhotoPickerComponentDemo {
// 组件初始化时设置参数信息。
pickerOptions: PickerOptions = new PickerOptions();

// 组件初始化完成后,可控制组件部分行为。
@State pickerController: PickerController = new PickerController();

// 宫格图内已选择的图片uri数组。
@State selectUris: Array<string> = new Array<string>();

// 目前选择的图片uri。
@State currentUri: string = '';

// 标识当前是否显示大图页面,false表示不显示大图页面,true表示显示大图页面。
@State isBrowserShow: boolean = false;

aboutToAppear() {
// 设置picker宫格页可选择的媒体文件类型,这里设置图片和视频类型。
this.pickerOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
// 设置宫格页内资源的最大选择数量,示例设置为5。
this.pickerOptions.maxSelectNumber = 5;
// 选择数量达到最大时的提示方式,示例设置为弹窗提示。
this.pickerOptions.maxSelectedReminderMode = ReminderMode.TOAST;
// 设置picker页面内是否需要展示搜索框,false为不展示。
this.pickerOptions.isSearchSupported = true;
// 将宫格页面内第一个宫格置为拍照按钮,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) {
// 如果宫格页面第一个宫格的类型为ItemType.CAMERA,则是相机按钮。
// 返回true则拉起系统相机;如果返回false应用可以自己拉起相机。
return true;
} else {
// 如果是选中操作。
if (clickType === ClickType.SELECTED) {
// 应用做自己的业务处理。
if (uri) {
this.selectUris.push(uri);
this.pickerOptions.preselectedUris = [...this.selectUris];
}
// 返回true则该宫格响应勾选,否则不响应勾选。
return true;
} else {
// 如果是取消选中操作。
// 应用做自己的业务处理。
if (uri) {
this.selectUris = this.selectUris.filter((item: string) => {
return item != uri;
});
this.pickerOptions.preselectedUris = [...this.selectUris];
}
// 返回true则该宫格响应取消勾选,否则不响应取消勾选。
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() {
Flex({
direction: FlexDirection.Column,
alignItems: ItemAlign.Start
}) {
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: this.pickerController,
})

// 这里模拟应用侧底部的选择栏。
if (this.isBrowserShow) {
// 已选择的图片缩略图。
Row() {
ForEach(this.selectUris, (uri: string) => {
if (uri === this.currentUri) {
Image(uri).height(50).width(50)
.onClick(() => {
})
.borderWidth(1)
.borderColor('red')
} else {
Image(uri).height(50).width(50).onClick(() => {
this.pickerController.setData(DataType.SET_SELECTED_URIS, this.selectUris);
// 点击底部缩略图,切换大图浏览的照片为点击的缩略图;本示例设置浏览范围为全部,包括图片和视频。
this.pickerController.setPhotoBrowserItem(uri, PhotoBrowserRange.ALL);
})
}
}, (uri: string) => JSON.stringify(uri))
}.alignSelf(ItemAlign.Center).margin(this.selectUris.length ? 10 : 0)
} else {
// 进入大图,预览已选择的图片。
Button('预览').width('33%').alignSelf(ItemAlign.Start).height('5%').margin(10).onClick(() => {
if (this.selectUris.length > 0) {
// 切换picker组件至大图浏览模式浏览图片。
this.pickerController.setPhotoBrowserItem(this.selectUris[0], PhotoBrowserRange.SELECTED_ONLY);
}
})
}
}
}
}