选择并查看文档与媒体文件
介绍
应用使用@ohos.file.picker、@ohos.file.fs等接口,实现了picker拉起文档编辑保存、拉起系统相册图片查看、拉起视频并播放的功能。
效果预览
使用说明:
- 在首页,应用显示查看最近打开文件功能的跳转按钮,点击后进入文件管理页面,可以通过最近页面,查看最近打开的文件。通过点击右上方的三个按钮,可以分别实现新建文档、选择图片或视频并打开预览、选择文档并打开的功能。
- 在查看文档界面,点击右上方左一按钮,可以实现当前文档另存为的功能;点击右上方中间的按钮,开启文档的编辑功能,textArea变成可编辑状态,用户输入数据后点击右上方第三个按钮,可以将当前文档内容进行保存操作(系统文档没有保存权限)。
- 在查看图片界面,picker拉起系统相册的图片,用户至多可选择三张图片查看,点击图片可以切换所显示的图片名及大小信息。
- 在查看视频界面,picker拉起系统相册的视频,用户至多可选择三个视频查看,点击视频播放并且可以显示的视频名及大小信息。
具体实现
- 拉起picker选择文件、拉起picker保存文件、拉起picker选择图片或视频的功能封装在Index.ets,源码参考:[Index.ets]
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { router } from '@kit.ArkUI';
import { picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import Logger from '../common/Logger';
import MediaFileUri from '../media/MediaFileUri';
import { Constants } from '../common/Constants';
const MAX_SELECT_NUM = 3; // 选择媒体文件的最大数目
const TAG = 'pickerIndex';
@Entry
@Component
struct Index {
@State uri: string = 'Hello World';
@State filename: string = '';
@State sizeFile: number = 0;
@State log: string = '';
@State imageFlagCur: number = 0;
@StorageLink('fileSizeList') fileSizeList: Array<number> = [];
@StorageLink('fileNameList') fileNameList: Array<string> = [];
@StorageLink('fileUriList') fileUriList: Array<string> = [];
@StorageLink('imageNames') imageNames: Array<string> = [];
mediaFileUri: MediaFileUri = new MediaFileUri();
scroller: Scroller = new Scroller();
authorizeBundleName: string = 'com.open.file.uri.demo';
// 拉起picker选择文件
async callFilePickerSelectFile(): Promise<void> {
try {
let DocumentSelectOptions = new picker.DocumentSelectOptions();
let documentPicker = new picker.DocumentViewPicker();
documentPicker.select(DocumentSelectOptions).then((DocumentSelectResult) => {
Logger.info(TAG,
'DocumentViewPicker.select successfully, DocumentSelectResult uri: ' + JSON.stringify(DocumentSelectResult));
let editFlag = false;
if (DocumentSelectResult !== null && DocumentSelectResult !== undefined) {
DocumentSelectResult.forEach((value) => {
this.uri = value;
editFlag = true;
Logger.info(TAG, `select file uri: ${this.uri}`);
})
}
if (editFlag) {
this.getFilenameByUri(this.uri);
}
}).catch((err: BusinessError) => {
Logger.error(TAG, 'DocumentViewPicker.select failed with err: ' + JSON.stringify(err));
});
} catch (err) {
Logger.error(TAG, 'DocumentViewPicker failed with err: ' + JSON.stringify(err));
}
}
// 拉起picker保存文件
async callFilePickerSaveFile(): Promise<void> {
try {
let DocumentSaveOptions = new picker.DocumentSaveOptions();
DocumentSaveOptions.newFileNames = ['MyDocument_01.txt'];
let documentPicker = new picker.DocumentViewPicker();
documentPicker.save(DocumentSaveOptions).then((DocumentSaveResult) => {
Logger.info(TAG,
'DocumentViewPicker.save successfully, DocumentSaveResult uri: ' + JSON.stringify(DocumentSaveResult));
if (DocumentSaveResult !== null && DocumentSaveResult !== undefined) {
this.uri = DocumentSaveResult[0];
Logger.info(TAG, `save file uri: ${this.uri}`);
}
this.getFilenameByUri(this.uri);
}).catch((err: BusinessError) => {
Logger.error(TAG, 'DocumentViewPicker.save failed with err: ' + JSON.stringify(err));
});
} catch (err) {
Logger.error(TAG, 'DocumentViewPicker failed with err: ' + err);
}
}
async getFilenameByUriForMedia(myUris: string[]) {
router.pushUrl({
url: 'pages/ViewMedia',
params: {
uris: myUris
}
}, router.RouterMode.Standard);
}
async getFilenameByUri(myUri: string): Promise<void> {
// 获取文件名称
this.filename = (myUri.split('/').pop()) as string;
router.pushUrl({
url: 'pages/EditFile',
params: {
fileName: this.filename,
myUri: myUri
}
}, router.RouterMode.Standard);
}
// 拉起picker选择图片/视频
async callFilePickerSelectImage(): Promise<void> {
let array: string[];
try {
// 设置photoPicker的参数
let PhotoSelectOptions = new picker.PhotoSelectOptions();
// 过滤选择媒体文件类型
PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
// 选择媒体文件的最大数目
PhotoSelectOptions.maxSelectNumber = MAX_SELECT_NUM;
let mediaFlag = false;
// 使用图库选择器对象前,需要先创建PhotoViewPicker实例
let photoPicker = new picker.PhotoViewPicker();
photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
// 日志中记录成功信息
Logger.info(TAG,
'PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));
// 接口采用callback异步返回形式,返回PhotoSelectResult对象,故进行下一步操作前要先判断是否已经成功返回PhotoSelectResult对象了
if (PhotoSelectResult !== null && PhotoSelectResult !== undefined) {
// PhotoSelectResult为返回的结果集。
// 其中包含Array<string>类型的photoUris,为返回图库选择后的媒体文件的uri数组;还包含boolean类型的isOriginalPhoto,指示返回图库选择后的媒体文件是否为原图。
// 声明变量array,其取值为PhotoSelectResult中的数组。
array = PhotoSelectResult['photoUris'];
array.forEach((value) => {
this.uri = value;
mediaFlag = true;
Logger.info(TAG, `select image/video uri: ${this.uri}`);
})
}
if (mediaFlag) {
this.getFilenameByUriForMedia(array);
}
}).catch((err: BusinessError) => {
Logger.error(TAG, 'PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
});
} catch (err) {
Logger.error(TAG, 'PhotoViewPicker failed with err: ' + err);
}
}
aboutToDisappear(): void {
this.fileNameList = [];
this.fileSizeList = [];
this.fileUriList = [];
}
onPageShow(): void {
this.mediaFileUri.getAllFiles();
}
build() {
Scroll(this.scroller) {
Row() {
Column() {
Row() {
Column() {
Text($r('app.string.last_open'))
.fontFamily('HarmonyHeiTi-Bold')
.fontSize($r('app.float.text_font_size_30'))
.fontWeight(Constants.TEXT_FONT_WIGHT)
.textAlign(TextAlign.Start)
.fontColor($r('app.color.text_font_color'))
.lineHeight($r('app.float.first_line_height'))
.width(Constants.SEVENTY_PERCENT)
.height($r('app.float.first_line_height'))
}
.width(Constants.FIFTY_PERCENT)
.margin({ left: Constants.PADDING_LEFT_RIGHT })
.alignItems(HorizontalAlign.Start)
Row() {
Image($r('app.media.ic_saveas'))
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.margin({ right: Constants.IMAGE_MARGIN_RIGHT })
.id('newFile')
.onClick(() => {
this.callFilePickerSaveFile();
})
Image($r('app.media.ic_picture'))
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.id('picture')
.margin({ right: Constants.IMAGE_MARGIN_RIGHT })
.onClick(() => {
this.callFilePickerSelectImage();
})
Image($r('app.media.ic_folder'))
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.id('folder')
.opacity(1)
.margin({ right: Constants.MARGIN_RIGHT })
.onClick(() => {
this.callFilePickerSelectFile();
})
}
.justifyContent(FlexAlign.End)
.padding({ right: Constants.PADDING_RIGHT })
.width(Constants.FIFTY_PERCENT)
}
// 第一行结束
.width(Constants.FULL_PERCENT)
.height($r('app.float.first_line_height'))
.margin({
top: $r('app.float.first_line_margin_top'),
left: $r('app.float.first_line_margin_left'),
right: $r('app.float.first_line_margin_right'),
bottom: $r('app.float.first_line_margin_bottom')
})
Row() {
Text($r('app.string.view_last_open'))
.fontSize($r('app.float.text_area_font_size'))
.textAlign(TextAlign.Start)
.lineHeight($r('app.float.line_height'))
.margin({ left: $r('app.float.image_margin_left') })
Blank()
Image($r('app.media.right_arrow'))
.height($r('app.float.text_height_19'))
.width($r('app.float.image_width'))
.margin({
left: $r('app.float.image_margin_left'),
right: $r('app.float.image_margin_left'),
top: $r('app.float.image_margin_top'),
bottom: $r('app.float.image_margin_top')
})
}
.backgroundColor($r('app.color.start_window_background'))
.width(Constants.FULL_PERCENT)
.height($r('app.float.row_height'))
.padding({
top: $r('app.float.row_padding'),
left: $r('app.float.margin_padding_12'),
right: $r('app.float.margin_padding_12')
})
.onClick(() => {
this.callFilePickerSelectFile();
})
Column() {
List({ space: Constants.LIST_SPACE, initialIndex: 0 }) {
ForEach(this.fileNameList, (item: string, index?: number) => {
ListItem() {
Row() {
Image($r('app.media.ic_docs'))
.width(Constants.IMAGE_WIDTH)
.height($r('app.float.line_height'))
.margin({
left: $r('app.float.margin_left'),
right: $r('app.float.margin_right')
})
Text(item)
.fontSize($r('app.float.text_area_font_size'))
.fontFamily('HarmonyHeiTi-Medium')
.fontColor($r('app.color.text_font_color'))
.lineHeight($r('app.float.line_height'))
.textAlign(TextAlign.Start)
.margin({ right: $r('app.float.padding_left_right') })
.width(Constants.SIXTY_FOUR_PERCENT)
if (index !== undefined) {
Text('Size: ' + JSON.stringify(this.fileSizeList[index]) + 'B')
.fontSize($r('app.float.text_font_size_14'))
.fontFamily('HarmonyHeiTi-Medium')
.lineHeight($r('app.float.text_height_19'))
.fontColor($r('app.color.text_font_color'))
.textAlign(TextAlign.End)
.opacity(Constants.TEXT_OPACITY)
.width(Constants.TEXT_WIDTH)
.margin({ right: $r('app.float.margin_padding_12') })
}
}
.id('fileItem' + (index !== undefined ? index : ""))
.borderRadius(Constants.BORDER_RADIUS)
.width(Constants.FULL_PERCENT)
.height($r('app.float.row_height_64'))
.padding({ right: $r('app.float.margin_padding_12') })
.backgroundColor($r('app.color.start_window_background'))
}
.onClick(() => {
Logger.info(TAG, 'fileAsset.displayName fileName item: ' + item);
if (index !== undefined) {
router.pushUrl({
url: 'pages/EditFile',
params: {
fileName: item,
myUri: this.fileUriList[index]
}
}, router.RouterMode.Standard);
}
})
}, (item: string) => item)
}
.listDirection(Axis.Vertical) // 排列方向
.id('indexList')
.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果
.scrollBar(BarState.Auto)
.alignListItem(ListItemAlign.Center)
.margin({
top: Constants.LIST_MARGIN_TOP,
left: $r('app.float.margin_padding_12'),
right: $r('app.float.margin_padding_12')
})
}
.height(Constants.FULL_PERCENT)
.width(Constants.FULL_PERCENT)
}
.alignItems(HorizontalAlign.Center)
.width(Constants.FULL_PERCENT)
.height(Constants.FULL_PERCENT)
.backgroundColor($r('app.color.common_background'))
}
.height(Constants.FULL_PERCENT)
}
}
}
-
使用new picker.DocumentViewPicker来创建文件picker实例,使用documentPicker.select来拉起picker选择文件,使用documentPicker.save来拉起picker保存文件,接口参考:@ohos.file.picker
-
使用new picker.PhotoViewPicker来创建图库picker实例,使用photoPicker.select来拉起picker选择图片或视频,接口参考:@ohos.file.picker
-
编辑文件并保存的功能封装在EditFile.ets,源码参考:[EditFile.ets]
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { promptAction, router } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';
import { fileIo, picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import MediaFileUri from '../media/MediaFileUri';
import Logger from '../common/Logger';
import { terminateSelf } from '../utils/utils';
import { Constants } from '../common/Constants';
const TAG = 'EditFile: ';
let storage = LocalStorage.getShared();
const OPACITY_VALUE = 0.6; // 透明度
interface myParams extends Object {
myUri: string,
fileName: string
};
@Entry(storage)
@Component
struct EditFile {
@LocalStorageLink('loadFlag') loadFlag: Boolean = false;
@LocalStorageLink('loadFileSize') loadFileSize: number = 0;
@LocalStorageLink('loadFileName') loadFileName: string = '';
@LocalStorageLink('loadFileContent') loadFileContent: string = '';
@LocalStorageLink('loadUri') loadUri: string = '';
@LocalStorageLink('fd') loadFd: number = 0;
@StorageLink('editable') editable: Boolean = false;
@StorageLink('myFileSize') myFileSize: number = 0;
@StorageLink('myFileContent') myFileContent: string = '';
@State myContext: Context = getContext(this) as common.UIAbilityContext;
@State myUri: string = '';
@State opacityValue: number = OPACITY_VALUE;
@State uriSave: string = '';
@State myFileName: string = '';
public fileContentFlag: boolean = false;
newFileContent: string = '';
scroller: Scroller = new Scroller();
controller: TextAreaController = new TextAreaController();
mediaFileUri: MediaFileUri = new MediaFileUri();
getFileInfo(): void {
if (this.loadFlag) {
this.myFileName = this.loadFileName;
this.myFileContent = this.loadFileContent;
this.myFileSize = this.loadFileSize;
this.myUri = this.loadUri;
Logger.info(TAG, 'The count of getFileInfo is myFileContent ' + this.myFileContent);
} else {
this.myUri = (router.getParams() as myParams).myUri;
this.myFileName = (router.getParams() as myParams).fileName;
this.myFileContent = this.mediaFileUri.readFileContent(this.myUri);
this.myFileSize = this.mediaFileUri.myGetFileSize(this.myUri, fileIo.OpenMode.READ_ONLY);
Logger.info(TAG, 'The count of getFileInfo is myFileName is: ' + this.myFileName);
Logger.info(TAG, 'The count of getFileInfo is myFileContent ' + this.myFileContent);
Logger.info(TAG, 'The count of getFileInfo is myFileSize ' + this.myFileSize);
}
AppStorage.setOrCreate('myFileContent', this.myFileContent);
AppStorage.setOrCreate('myFileSize', this.myFileSize);
}
async writeContentForSaveAsFile(myUri: string, wrFlag: Boolean = false): Promise<void> {
if (wrFlag) {
Logger.info(TAG, 'fileAsset.displayName wrFlag is true');
Logger.info(TAG, 'fileAsset.displayName wrFlag myFileContent :' + this.myFileContent);
this.mediaFileUri.writeFileContent(myUri, this.myFileContent);
}
}
// 拉起picker保存文件
async callFilePickerSaveFile(): Promise<void> {
try {
let DocumentSaveOptions = new picker.DocumentSaveOptions();
DocumentSaveOptions.newFileNames = ['MyDocument_01.txt'];
let documentPicker = new picker.DocumentViewPicker();
documentPicker.save(DocumentSaveOptions).then((DocumentSaveResult) => {
Logger.info(TAG,
'DocumentViewPicker.save successfully, DocumentSaveResult uri: ' + JSON.stringify(DocumentSaveResult));
if (DocumentSaveResult !== null && DocumentSaveResult !== undefined) {
this.uriSave = DocumentSaveResult[0];
Logger.info(TAG, `save callFilePickerSaveFile file this.uriSave: ${this.uriSave}`);
}
Logger.info(TAG, 'fileAsset.displayName wrFlag myFileContent :' + this.myFileContent);
// 用 medialibrary 重新获取uri,进行写入操作
this.writeContentForSaveAsFile(this.uriSave, true);
}).catch((err: BusinessError) => {
Logger.error(TAG, 'DocumentViewPicker.save failed with err: ' + JSON.stringify(err));
});
} catch (err) {
Logger.error(TAG, 'DocumentViewPicker failed with err: ' + err);
}
}
onPageShow(): void {
this.getFileInfo();
this.editable = false;
}
build() {
Column() {
// 顶部的行容器
Row() {
// 后退箭头
Row() {
Image($r('app.media.ic_back'))
.focusable(true)
.focusOnTouch(true)
.id('backIndex')
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.align(Alignment.Start)
.onClick(() => {
if (this.loadFlag) {
Logger.info(TAG, 'end page');
let context = getContext(this);
terminateSelf(context);
} else {
router.back();
}
})
}
.margin({ left: Constants.MARGIN_LEFT })
// 文件名及信息
Column() {
Row() {
Text(this.myFileName)
.focusable(true)
.focusOnTouch(true)
.fontSize($r('app.float.text_font_size'))
.fontFamily('HarmonyHeiTi-Bold')
.fontColor($r('app.color.text_font_color'))
.textAlign(TextAlign.Start)
.fontWeight(Constants.TEXT_FONT_WIGHT)
.lineHeight(Constants.TEXT_LINE_HEIGHT)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width(Constants.FULL_PERCENT)
.align(Alignment.Start)
.margin({
left: Constants.MARGIN_LEFT,
top: Constants.MARGIN_TOP,
bottom: Constants.MARGIN_ZERO_POINT_THREE_PERCENT
})
Row() {
Text('size: ' + JSON.stringify(this.myFileSize) + 'B')
.focusable(true)
.focusOnTouch(true)
.opacity(Constants.TEXT_OPACITY)
.fontFamily('HarmonyHeiTi')
.fontSize($r('app.float.text_font_size_14'))
.fontColor($r('app.color.text_font_color'))
.textAlign(TextAlign.Start)
.lineHeight(Constants.TEXT_LINE_HEIGHT_19)
.fontWeight(Constants.TEXT_FONT_WIGHT_400)
}
.width(Constants.FULL_PERCENT)
.margin({
left: Constants.MARGIN_LEFT,
top: Constants.MARGIN_ZERO_POINT_THREE_PERCENT,
bottom: Constants.MARGIN_ZERO_POINT_FIVE_PERCENT
})
.align(Alignment.Start)
}
.width(Constants.FORTY_FIVE_PERCENT)
.margin({ left: Constants.MARGIN_LEFT })
// 右边三个图标
Row() {
Image($r('app.media.ic_saveas'))
.focusable(true)
.focusOnTouch(true)
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.id('saveAs')
.margin({ right: Constants.IMAGE_MARGIN_RIGHT })
.onClick(() => {
this.callFilePickerSaveFile();
})
.visibility(this.loadFlag ? Visibility.Hidden : Visibility.Visible)
Image($r('app.media.ic_writting'))
.focusable(true)
.focusOnTouch(true)
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.id('editable')
.margin({ right: Constants.IMAGE_MARGIN_RIGHT })
.onClick(() => {
this.editable = true;
AppStorage.setOrCreate('editable', this.editable);
Logger.info(TAG, 'EditFile caretPosition length = ' + this.myFileContent.length);
this.controller.caretPosition(this.myFileContent.length);
promptAction.showToast({ message: $r('app.string.editable') });
})
Image($r('app.media.ic_save'))
.focusable(true)
.focusOnTouch(true)
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.id('save')
.margin({ right: Constants.MARGIN_LEFT })
.onClick(() => {
if (this.fileContentFlag) {
let flage: boolean = true;
this.myFileContent = this.newFileContent;
AppStorage.setOrCreate('myFileContent', this.myFileContent);
Logger.info(TAG, 'save onClick myFileContent is: ' + this.myFileContent);
Logger.info(TAG, 'save onClick this.loadUri: ' + this.loadUri);
if (this.loadFlag) {
let file = fileIo.openSync(this.loadUri,
fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.TRUNC);
Logger.info(TAG, 'save onClick file.fd is: ' + file.fd);
fileIo.write(file.fd, this.myFileContent).then((writeLen) => {
Logger.info(TAG, 'write data to file succeed and size is:' + writeLen);
this.myFileSize = fileIo.statSync(file.fd).size;
AppStorage.setOrCreate('myFileSize', this.myFileSize);
Logger.info(TAG, 'save onClick this.myFileSize ' + this.myFileSize);
}).catch((err: BusinessError) => {
Logger.info(TAG, 'write data to file failed with error:' + JSON.stringify(err));
});
fileIo.closeSync(file);
} else {
try {
let file = fileIo.openSync(this.myUri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.TRUNC);
let writeLen = fileIo.writeSync(file.fd, this.myFileContent);
this.myFileSize = fileIo.statSync(file.fd).size;
AppStorage.setOrCreate('myFileSize', this.myFileSize);
Logger.info(TAG, 'write data to file succeed and size is:' + writeLen);
fileIo.closeSync(file);
} catch (err) {
flage = false;
Logger.info(`save data to file failed with error:
${JSON.stringify(err)}: ${JSON.stringify(err?.message)}`);
promptAction.showToast({
message: Constants.SHOW_TOAST_MESSAGE,
duration: 6500
})
}
}
if (flage) {
this.editable = false;
AppStorage.setOrCreate('editable', this.editable);
promptAction.showToast({ message: $r('app.string.saved') });
}
}
})
}
.height(Constants.FIFTY_PERCENT)
.width(Constants.THIRTY_SEVEN_POINT_TWO)
.padding({ right: Constants.MARGIN_ZERO_POINT_FIVE_PERCENT })
.justifyContent(FlexAlign.End)
}
.height(Constants.SEVEN_POINT_FOUR)
.width(Constants.FULL_PERCENT)
Scroll(this.scroller) {
// TextArea的行容器
Row() {
TextArea({
text: this.newFileContent ? this.newFileContent : this.myFileContent,
placeholder: Constants.TEXT_AREA_PLACEHOLDER,
controller: this.controller
})
.id('textArea')
.fontSize($r('app.float.text_area_font_size'))
.fontColor($r('app.color.text_font_color'))
.opacity(this.opacityValue)
.fontWeight(Constants.TEXT_FONT_WIGHT_400)
.align(Alignment.TopStart)
.textAlign(TextAlign.Start)
.backgroundColor($r('app.color.common_background'))
.fontFamily('HarmonyHeiTi')
.padding({
top: $r('app.float.padding_top_bottom'),
right: $r('app.float.padding_left_right'),
left: $r('app.float.padding_left_right'),
bottom: $r('app.float.padding_top_bottom')
})
.focusable(this.editable ? true : false)
.focusOnTouch(true)
.defaultFocus(false)
.onFocus(() => {
this.opacityValue = 1;
})
.onBlur(() => {
this.opacityValue = OPACITY_VALUE;
})
.onChange((value: string) => {
this.newFileContent = value;
this.fileContentFlag = true;
})
}
.padding({
top: Constants.PADDING_TOP,
left: Constants.PADDING_LEFT_RIGHT,
right: Constants.PADDING_LEFT_RIGHT
})
}
}
.backgroundColor($r('app.color.common_background'))
.height(Constants.FULL_PERCENT)
}
}
-
使用fs.openSync、fs.writeSync、fs.readSync、fs.closeSync分别用来打开文件、写文件、读文件、关闭文件,接口参考:@ohos.file.fs
-
拉起图片或视频并查看的功能封装在ViewMedia.ets,源码参考:[ViewMedia.ets]
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { router } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';
import { fileIo, picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import MediaFileUri from '../media/MediaFileUri';
import Logger from '../common/Logger';
import { Constants } from '../common/Constants';
const TAG = 'ViewMedia';
interface myParams extends Object {
uris: string[]
};
@Entry
@Component
struct ViewMedia {
@State myContext: Context = getContext(this) as common.UIAbilityContext;
@State myFileSizes: number[] = [];
@State myFileNames: string[] = [];
@State myFileTypes: number[] = [];
@StorageLink('myFileName') myFileName: string = '';
@StorageLink('myFileSize') myFileSize: number = 0;
@State myUris: string[] = (router.getParams() as myParams).uris;
@State uri: string = 'Hello World';
@StorageLink('showPauses') showPauses: Array<number> = [];
mediaFileUri: MediaFileUri = new MediaFileUri();
scroller: Scroller = new Scroller();
currentUri: string = '';
controllers: Array<VideoController> = [];
// 拉起picker保存图片/视频
async callFilePickerSaveImageVideo(): Promise<void> {
try {
let PhotoSaveOptions = new picker.PhotoSaveOptions();
PhotoSaveOptions.newFileNames = ['PhotoViewPicker01.jpg', 'PhotoViewPicker01.mp4'];
let photoPicker = new picker.PhotoViewPicker();
photoPicker.save(PhotoSaveOptions).then((PhotoSaveResult) => {
Logger.info(TAG, 'PhotoViewPicker.save successfully, PhotoSaveResult uri: ' + JSON.stringify(PhotoSaveResult));
if (PhotoSaveResult !== null && PhotoSaveResult !== undefined) {
PhotoSaveResult.forEach((value: string) => {
this.uri = value
Logger.info(TAG, `save image/video uri: ${this.uri}`);
})
}
}).catch((err: BusinessError) => {
Logger.error(TAG, 'PhotoViewPicker.save failed with err: ' + JSON.stringify(err));
});
} catch (err) {
Logger.error(TAG, 'PhotoViewPicker failed with err: ' + err);
}
}
onPageShow() {
this.getImagesInfo();
this.myFileName = this.myFileNames[0];
this.myFileSize = this.myFileSizes[0];
Logger.info(TAG, 'onPageShow getFilenameByUriForMedia this.myFileName ' + this.myFileName);
Logger.info(TAG, 'onPageShow getFilenameByUriForMedia begin ' + this.myFileSize);
AppStorage.setOrCreate('myFileName', this.myFileName);
AppStorage.setOrCreate('myFileSize', this.myFileSize);
}
async getMediaNameByUri(myUri: string, index: number) {
Logger.info(TAG, 'getMediaNameByUri getFilenameByUriForMedia begin');
this.myFileName = (myUri.split('/').pop()) as string;
this.myFileNames[index] = this.myFileName;
}
getImagesInfo() {
for (let index = 0; index < this.myUris.length; index++) {
Logger.info(TAG, 'getFilenameByUriForMedia getImagesInfo index: ' + index);
this.controllers[index] = new VideoController();
this.getMediaNameByUri(this.myUris[index], index);
this.myFileSizes[index] = this.mediaFileUri.myGetFileSize(this.myUris[index], fileIo.OpenMode.READ_ONLY);
Logger.info(TAG, 'getFilenameByUriForMedia getVideosInfo this.myFileNames[index]: '
+ this.myFileNames[index] + ' index ' + index);
Logger.info(TAG, 'getFilenameByUriForMedia getVideosInfo this.myFileSizes[index]' + this.myFileSizes[index]);
Logger.info(TAG, 'getFilenameByUriForMedia getVideosInfo this.myFileTypes[index] cc' + this.myFileTypes[index]);
}
}
build() {
Column() {
// 顶部的行容器
Row() {
// 后退箭头
Row() {
Image($r('app.media.ic_back'))
.focusable(true)
.focusOnTouch(true)
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.align(Alignment.Start)
.id('back2Index')
.onClick(() => {
router.back();
})
}
.width(Constants.BACK_WIDTH)
.padding({ left: Constants.BACK_PADDING_LEFT })
// 文件名及信息
Column() {
Row() {
Text(this.myFileName)
.focusable(true)
.focusOnTouch(true)
.fontSize($r('app.float.text_font_size'))
.fontFamily('HarmonyHeiTi-Bold')
.fontColor($r('app.color.text_font_color'))
.textAlign(TextAlign.Start)
.fontWeight(Constants.TEXT_FONT_WIGHT)
.lineHeight($r('app.float.text_height'))
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width(Constants.FULL_PERCENT)
.align(Alignment.Start)
.margin({
top: Constants.MARGIN_TOP,
bottom: Constants.MARGIN_ZERO_POINT_THREE_PERCENT
})
Row() {
Text('size: ' + JSON.stringify(this.myFileSize) + 'B')
.focusable(true)
.focusOnTouch(true)
.opacity(Constants.TEXT_OPACITY)
.fontFamily('HarmonyHeiTi')
.fontSize($r('app.float.text_font_size_14'))
.fontColor($r('app.color.text_font_color'))
.textAlign(TextAlign.Start)
.lineHeight($r('app.float.text_height_19'))
.fontWeight(Constants.TEXT_FONT_WIGHT_400)
}
.width(Constants.FULL_PERCENT)
.margin({
top: Constants.MARGIN_ZERO_POINT_THREE_PERCENT,
bottom: Constants.MARGIN_ZERO_POINT_FIVE_PERCENT
})
.align(Alignment.Start)
}
.width(Constants.FORTY_FIVE_PERCENT)
.margin({ left: Constants.MARGIN_LEFT })
// 右边一个图标,另存为
Row() {
Image($r('app.media.ic_saveas'))
.focusable(true)
.focusOnTouch(true)
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.visibility(Visibility.Hidden)
}
.height(Constants.FULL_PERCENT)
.width(Constants.THIRTY_SEVEN_POINT_TWO)
.padding({ right: Constants.BACK_PADDING_LEFT })
.justifyContent(FlexAlign.End)
}
.height(Constants.SEVEN_POINT_FOUR)
.width(Constants.FULL_PERCENT)
Scroll(this.scroller) {
// 显示媒体文件的容器
Column() {
List({ space: Constants.LIST_SPACE_20, initialIndex: 0 }) {
ForEach(this.myUris, (uri: string, index?: number) => {
ListItem() {
Column() {
Image(uri)
.borderRadius(Constants.BORDER_RADIUS)
.onClick(() => {
if (index !== undefined) {
this.myFileSize = this.myFileSizes[index];
this.myFileName = this.myFileNames[index];
}
AppStorage.setOrCreate('myFileName', this.myFileName);
AppStorage.setOrCreate('myFileSize', this.myFileSize);
Logger.info(TAG, 'Image onClick myFileName is ' + this.myFileName);
Logger.info(TAG, 'Image onClick myFileName is ' + this.myFileSize);
})
if (index !== undefined) {
Stack({ alignContent: Alignment.Center }) {
Video({
src: uri,
controller: this.controllers[index]
})
.autoPlay(false)
.controls(true)
.borderRadius(Constants.BORDER_RADIUS)
Image($r('app.media.ic_PAUSE'))
.width($r('app.float.image_size'))
.height($r('app.float.image_size'))
.onClick(() => {
this.controllers[index].start();
this.showPauses[index] = 0;
})
}
.onClick(() => {
this.myFileSize = this.myFileSizes[index];
this.myFileName = this.myFileNames[index];
AppStorage.setOrCreate('myFileName', this.myFileName);
AppStorage.setOrCreate('myFileSize', this.myFileSize);
})
}
}
.height(Constants.FULL_PERCENT)
}
.height(Constants.TWENTY_FIVE_PERCENT)
}, (item: string) => item)
}
.id('picScroller')
.scrollBar(BarState.Auto)
}
}
.padding({
top: Constants.ONE_POINT_FIVE_PERCENT,
left: Constants.PADDING_LEFT_RIGHT,
right: Constants.PADDING_LEFT_RIGHT
})
}
.backgroundColor($r('app.color.common_background'))
.height(Constants.FULL_PERCENT)
}
}
以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下:
内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!