“我”页面功能
原创大约 6 分钟
页面整体布局
修改之前的src/main/ets/pages/Me.ets
页面内容,代码如下。
import { UserVideoDataSource } from "../datasource/UserVideoDataSource";
import { MeClassification } from "../view/MeClassification";
import { MeMenu } from "../view/MeMenu";
import { MeUserInfo } from "../view/MeUserInfo";
/**
* “我”页面
*
*/
@Component
export struct Me {
// 用户上传的视频数据源
@Link
userVideoDataSource: UserVideoDataSource;
build() {
Column() {
// 菜单栏
MeMenu()
.padding({ right: 10, top: 10 })
// 个人信息展示
MeUserInfo()
.padding({ left: 10, top: 60 })
// 作品分类
MeClassification({
userVideoDataSource: this.userVideoDataSource
})
.padding({ left: 10, right: 10, top: 10, bottom: 10 })
}
.width("100%")
.height("100%")
.backgroundImage($rawfile('wallpaper.png'))
.backgroundImageSize({ width: '100%', height: '100%'})
}
}
菜单布局
在src/main/ets/view/
目录中创建MeMenu.ets
文件,代码如下。
/**
* “我”页面的菜单栏
*
*/
@Component
export struct MeMenu {
build() {
Row() {
Flex({ justifyContent: FlexAlign.End }) {
// 搜索
Image($r('app.media.me_search'))
.width(22)
.height(22)
// 利用Column实现间隔
Column().width(22)
// 菜单
Image($r('app.media.me_view_list'))
.width(22)
.height(22)
}
}
.width('100%')
.height(22)
}
}
信息展示布局
在src/main/ets/view/
目录中创建MeUserInfo.ets
文件,代码如下。
/**
* 个人信息展示
*
*/
@Component
export struct MeUserInfo {
build() {
// 展示个人信息
Row() {
// 头像
Image($rawfile(AppStorage.get('UserInfo.profilePath')))
.width(80)
.height(80)
// 圆形头像
.borderRadius(40)
// 账号
Text(AppStorage.get('UserInfo.username'))
.fontSize(25)
.fontColor('#FFFFFF')
.margin({ left: 6 })
}
.width('100%')
.height(80)
}
}
作品分类布局
在src/main/ets/view/
目录中创建MeClassification.ets
文件,代码如下。
import { UserVideoDataSource } from "../datasource/UserVideoDataSource";
import { MeVideoList } from "./MeVideoList";
/**
* “我”作品分类
*
*/
@Component
export struct MeClassification {
// 当前Tabs页签
@State
currentIndex: number = 0;
// 用户上传的视频数据源
@Link
userVideoDataSource: UserVideoDataSource;
build() {
Column() {
// 设置Tabs组件
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
// 作品列表
MeVideoList({
userVideoDataSource: this.userVideoDataSource
})
}.tabBar(this.TabBuilder('作品', 0))
TabContent() {
//
}.tabBar(this.TabBuilder('喜欢', 1))
TabContent() {
//
}.tabBar(this.TabBuilder('收藏', 2))
TabContent() {
//
}.tabBar(this.TabBuilder('关注', 3))
}
.onChange((index: number) => {
this.currentIndex = index;
})
}
.width('100%')
.height('100%')
}
/**
* 自定义导航栏
*/
@Builder
TabBuilder(title: string, index: number) {
Column() {
// 选中和不选中的文本样式
Text(title)
.fontColor(this.currentIndex === index ? '#FFFFFF' : '#F8FAEE')
.fontSize(this.currentIndex === index ? 20 : 18)
// 选中时下划线
Divider()
.strokeWidth(1)
.color('#FFFFFF')
.visibility(this.currentIndex === index ? Visibility.Visible : Visibility.Hidden)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
视频分类列表
在src/main/ets/view/
目录中创建MeVideoList.ets
文件,代码如下。
import { UserVideoDataSource } from "../datasource/UserVideoDataSource";
import { VideoInfoDataSource } from "../datasource/VideoInfoDataSource";
import { VideoInfo } from "../model/VideoInfo";
/**
* “我”页面视频分类列表
*
*/
@Component
export struct MeVideoList {
// 用户上传的视频数据源
@Link
userVideoDataSource: UserVideoDataSource;
// 视频数据源
// 在多个层级之间同步数据
@Consume
videoInfoDataSource: VideoInfoDataSource;
build() {
Column() {
// 列表组件,各列表项之间间隔为5
List({ space: 5 }) {
LazyForEach(this.userVideoDataSource,
// 指定itemGenerator
(videoInfo: VideoInfo) => {
// 列表项
ListItem() {
Row() {
// 视频封面
Image($rawfile(videoInfo.coverPath))
.width(136)
.height(180)
// 视频文本
Text(videoInfo.content)
.width(130)
.fontSize(16)
.fontColor('#FFFFFF')
// 操作按钮
Column() {
Button('编辑', { type: ButtonType.Normal })
.width(100)
.height(24)
.borderRadius(4)
.fontSize(14)
.backgroundColor(Color.Blue)
Column()
.height(10)
Button('删除', { type: ButtonType.Normal })
.width(100)
.height(24)
.borderRadius(4)
.fontSize(14)
.backgroundColor(Color.Red)
.onClick(() => {
// 删除用户视频数据
this.userVideoDataSource.removeById(videoInfo.videoId)
// 删除视频数据源
this.videoInfoDataSource.removeById(videoInfo.videoId)
})
}
.width(100)
}
.width('100%')
.height(180)
}
.width('100%')
},
// 用生成的JSON数据作为keyGenerator
(videoInfo: VideoInfo) => JSON.stringify(videoInfo)
)
}
.width('100%')
// 垂直排列
.listDirection(Axis.Vertical)
// 边缘互动效果
.edgeEffect(EdgeEffect.Spring)
}
.width('100%')
.height('100%')
}
}
/**
* 定义编辑视频信息的CustomDialog弹窗
*/
@CustomDialog
struct VideoEditCustomDialog {
// 视频信息
@Link
selectedVideoInfo: VideoInfo
private controller: CustomDialogController;
// 同步父组件的数据源
@Link
userVideoDataSource: UserVideoDataSource;
// 消费祖先节点上的数据源
@Consume
videoInfoDataSource: VideoInfoDataSource;
build() {
Column() {
// 编辑视频内容
TextArea({
placeholder: '请输入视频内容',
text: this.selectedVideoInfo.content
})
.width(320)
.height(100)
.borderRadius(8)
.backgroundColor('#F8F8F8')
.margin({ top: 10 })
.fontSize(20)
.onChange((value: string) => {
this.selectedVideoInfo.content = value;
})
// 操作按钮
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('取消', { type: ButtonType.Normal })
.backgroundColor(Color.White)
.fontColor(Color.Black)
.onClick(() => {
this.controller.close();
})
Button('确定', { type: ButtonType.Normal })
.backgroundColor(Color.White)
.fontColor(Color.Black)
.onClick(() => {
this.controller.close();
this.onConfirm();
})
}
.margin({ bottom: 10 })
}
}
// 点击确定按钮时
onConfirm(): void {
// 更新数据到用户上传视频数据源
this.userVideoDataSource.updateById(this.selectedVideoInfo.videoId, this.selectedVideoInfo)
// 更新数据到视频数据源
this.videoInfoDataSource.updateById(this.selectedVideoInfo.videoId, this.selectedVideoInfo)
}
}
修改数据源
在src/main/ets/datasource/
目录中创建UserVideoDataSource.ets
文件,代码如下。
import { VideoInfo } from "../model/VideoInfo";
import { BaseDataSource } from "./BaseDataSource";
/**
* 用户上传的视频数据
*
*/
export class UserVideoDataSource extends BaseDataSource<VideoInfo> {
constructor(videoArray: Array<VideoInfo>) {
super(videoArray);
}
/**
* 根据ID删除视频
*/
removeById(id: number): void {
let dataSource: Array<VideoInfo> = this.getDataSource();
// 遍历数据并删除
for (let i: number = 0; i < dataSource.length; i++) {
if (dataSource[i].videoId === id) {
this.remove(i);
break;
}
}
}
/**
* 根据ID更新视频
*/
updateById(id: number, videoInfo: VideoInfo): void {
let dataSource: Array<VideoInfo> = this.getDataSource();
// 遍历数据并更新
for (let i: number = 0; i < dataSource.length; i++) {
if (dataSource[i].videoId === id) {
this.update(i, videoInfo);
break;
}
}
}
}
然后修改之前的VideoInfoDataSource.ets
文件。
import { VideoInfo } from '../model/VideoInfo';
import { BaseDataSource } from './BaseDataSource';
/**
* 视频信息数据源
*
*/
export class VideoInfoDataSource extends BaseDataSource<VideoInfo> {
constructor(videoArray: Array<VideoInfo>) {
super(videoArray);
}
/**
* 根据ID删除
*/
removeById(id: number): void {
let dataSource: Array<VideoInfo> = this.getDataSource();
// 遍历数据并删除
for (let i: number = 0; i < dataSource.length; i++) {
if (dataSource[i].videoId === id) {
this.remove(i);
break;
}
}
}
/**
* 根据ID更新
*/
updateById(id: number, videoInfo: VideoInfo): void {
let dataSource: Array<VideoInfo> = this.getDataSource();
// 遍历数据并更新
for (let i: number = 0; i < dataSource.length; i++) {
if (dataSource[i].videoId === id) {
this.update(i, videoInfo);
break;
}
}
}
}
其他修改内容
修改src/main/ets/common/
目录中的Constant.ets
文件,增加新的常量。
export default class Constant {
......
/**
* 用户上传的视频数据
*/
static USER_VIDEO_INFO_ARRAY: Array<VideoInfo> = [];
}
修改src/main/ets/pages/
目录中的Index.ets
文件,代码如下。
import Constant from '../common/Constant';
import { VideoInfoDataSource } from '../datasource/VideoInfoDataSource';
import { Main } from './Main'
import { Me } from './Me'
import router from '@ohos.router';
import { UserInfo } from '../model/UserInfo';
import { VideoInfo } from '../model/VideoInfo';
import { UserVideoDataSource } from '../datasource/UserVideoDataSource';
/**
* 主界面
*
*/
@Entry
@Component
struct Index {
// 是否显示视频界面
@State
isShow: boolean = false;
// 视频信息数据源
// 以@Provide方式提供同步数据
@Provide
videoInfoDataSource: VideoInfoDataSource = new VideoInfoDataSource(Constant.VIDEO_INFO_ARRAY);
// 当前Tabs页面的索引
@State
currentIndex: number = 0;
// TabsController组件
private tabsController: TabsController = new TabsController();
// 用户上传的视频数据源
@State
userVideoDataSource: UserVideoDataSource = new UserVideoDataSource(Constant.USER_VIDEO_INFO_ARRAY);
// 在其他生命周期处理isShow变量
aboutToAppear(): void {
this.isShow = true;
}
aboutToDisappear(): void {
this.isShow = false;
}
onPageShow(): void {
this.isShow = true;
// 从路由参数中获取用户信息
let params = router.getParams();
if (params != null) {
let userInfo: UserInfo = (params as Record<string, UserInfo>)[`${Constant.ROUTER_LOGGED_USER_INFO}`];
if (userInfo != null) {
// 存储在AppStorage中
AppStorage.setOrCreate('UserInfo.username', userInfo.username);
AppStorage.setOrCreate('UserInfo.profilePath', userInfo.profilePath);
}
// 从路由参数中获取视频信息
let selectedVideoInfo: VideoInfo = (params as Record<string, VideoInfo>)[`${Constant.WAIT_PUBLISHED_VIDEO_INFO}`];
if (selectedVideoInfo != null) {
// 存储至视频数据源
this.videoInfoDataSource.push(selectedVideoInfo)
// 存储至用户视频数据源
this.userVideoDataSource.push(selectedVideoInfo)
}
}
}
onPageHide(): void {
this.isShow = false;
}
build() {
// 设置导航栏和Tabs的控制器
Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
// 各个导航的页签
TabContent() {
Main({
isShow: this.isShow,
videoInfoDataSource: this.videoInfoDataSource
})
}.tabBar(this.TabBuilder("首页", 0))
TabContent() {
// VideoPublish()
}.tabBar(this.TabBuilder("发布", 1))
TabContent() {
Me({
userVideoDataSource: this.userVideoDataSource
})
}.tabBar(this.TabBuilder("我", 2))
}
}
/**
* 自定义TabBuilder导航栏组件
*
*/
@Builder
TabBuilder(title: string, index: number) {
Column() {
// 设置选中状态
Text(title)
.fontColor(this.currentIndex === index ? '#FFFFFF' : '#999999')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.Black)
// 设置点击事件
.onClick(() => {
this.currentIndex = index;
// 页面的索引从0开始
if (index === 0) {
this.tabsController.changeIndex(index);
this.isShow = true;
} else {
this.isShow = false;
}
// 如果是点击视频发布
if (index === 1) {
router.pushUrl({
url: 'pages/VideoPublish'
})
}
// 如果是点击“我”
if (index === 2) {
this.tabsController.changeIndex(index);
}
})
}
}
最终的预览效果如下图所示。

感谢支持
更多内容,请移步《超级个体》。