栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 前沿技术 > 云计算 > Docker/k8s

DistributedVideoPlayer 分布式视频播放器(一)

Docker/k8s 更新时间:发布时间: 百科书网 趣学号



想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

介绍

本示例是在官方Video Play Ability 模板基础上做了扩展开发,官方模板提供基本的视频播放功能,并允许您在手机和电视之间传输视频.

应用分为手机端(entry)和TV端(entrytv),以及一个依赖模块(commonlib).

在示例的基础之上,手机端增加了视频播放列表功能,以及播放详情页和评论功能;手机端播放的视频可以流转到TV端,并实现远端遥控的功能。

内容比较多,会分两期给大家讲解,本期文章主要讲解的内容是手机端部分:

1.实现一个视频播放器 2.实现一个播放列表 3.实现一个评论功能.

[本文正在参与优质创作者激励]

效果展示

DistributedVideoPlayer 分布式视频播放器(一)-鸿蒙HarmonyOS技术社区

搭建环境

安装DevEco Studio,详情请参考DevEco Studio下载。

设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

下载源码后,使用DevEco 打开项目。

代码结构 Java代码
  1. │  config.json │ 
  2. ├─java │  └─com 
  3. │      └─buty │          └─distributedvideoplayer 
  4. │              │  MainAbility.java                │              │  MyApplication.java 
  5. │              │ │              ├─ability 
  6. │              │      DevicesSelectAbility.java    │              │      MainAbilitySlice.java           #视频播放列表页 
  7. │              │      SyncControlServiceAbility.java   │              │      VideoPlayAbility.java           #视频播放Ability 
  8. │              │      VideoPlayAbilitySlice.java      #视频播放详情和评论页 │              │ 
  9. │              ├─components │              │      EpisodesSelectionDialog.java     
  10. │              │      RemoteController.java │              │      VideoPlayerPlaybackButton.java  #播放按钮组件 
  11. │              │      VideoPlayerSlider.java          #播放时间进度条 │              │ 
  12. │              ├─constant │              │      Constants.java                  #常量 
  13. │              │      ResolutionEnum.java             #分辨率枚举 │              │      RouteRegister.java              #自定义路由 
  14. │              │ │              ├─data 
  15. │              │      VideoInfo.java                  #视频基础信息 │              │      VideoInfoService.java           #视频信息服务,用于模拟数据 
  16. │              │      Videos.java                     #视频列表 │              │  
  17. │              ├─model │              │      CommentModel.java               #评论模型 
  18. │              │      DeviceModel.java                 │              │      ResolutionModel.java            #解析度模型 
  19. │              │      VideoModel.java                 #视频模型 │              │ 
  20. │              ├─provider │              │      CommentItemProvider.java        #评论数据提供程序 
  21. │              │      DeviceItemProvider.java       │              │      ResolutionItemProvider.java     #解析度数据提供程序 
  22. │              │      VideoItemProvider.java          #视频数据提供程序 │              │ 
  23. │              └─utils │                      AppUtil.java                   #工具类 
  24. │                      DateUtils.java 
资源文件
  1. └─resources     ├─base 
  2.     │  ├─element     │  │      color.json 
  3.     │  │      float.json     │  │      strarray.json 
  4.     │  │      string.json     │  │ 
  5.     │  ├─graphic     │  │      background_ability_control_bg.xml           
  6.     │  │      background_ability_control_middle.xml     │  │      background_ability_control_ok.xml 
  7.     │  │      background_ability_devices.xml     │  │      background_ability_episodes.xml 
  8.     │  │      background_button_click.xml     │  │      background_button_clicked.xml 
  9.     │  │      background_episodes_item.xml     │  │      background_episodes_quality.xml 
  10.     │  │      background_episodes_trailer.xml     │  │      background_slide_thumb.xml 
  11.     │  │      background_switch_checked.xml     │  │      background_switch_empty.xml 
  12.     │  │      background_switch_thumb.xml     │  │      background_switch_track.xml 
  13.     │  │      list_divider.xml     │  │      shape_slider_thumb.xml 
  14.     │  │     │  ├─layout 
  15.     │  │      ability_main.xml                                #播放列表布局     │  │      comments_item.xml                               #单条评论布局 
  16.     │  │      dialog_playlist.xml                          │  │      dialog_resolution_list.xml 
  17.     │  │      dialog_table_layout.xml     │  │      hm_sample_ability_video_box.xml                 #视频播放组件页 
  18.     │  │      hm_sample_ability_video_comments.xml            #播放详情布局页     │  │      hm_sample_view_video_box_seek_bar_style1.xml    #播放进度条布局 
  19.     │  │      hm_sample_view_video_box_seek_bar_style2.xml     │  │      remote_ability_control.xml 
  20.     │  │      remote_ability_episodes.xml     │  │      remote_ability_select_devices.xml 
  21.     │  │      remote_ability_sound_equipment.xml     │  │      remote_device_item.xml 
  22.     │  │      remote_episodes_item.xml     │  │      remote_video_quality_item.xml 
  23.     │  │     │  ├─media 
  24.     │  │      comments.png     │  │      great.png 
  25.     │  │      icon.png     │  │      ic_anthology.png 
  26.     │  │     │  └─profile 
  27.     ├─en     │  └─element 
  28.     │          string.json     │ 
  29.     ├─rawfile     │      videos.json                                      #模拟数据JSON文件 
  30.     │     └─zh 
  31.         └─element                 string.json 
实现步骤 1.实现一个视频播放器

引入对commonlib的依赖后,实现一个视频播放器就很容易了.

entry的build.gradle 增加对commonlib的依赖

  1. dependencies {     implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) 
  2.     testImplementation 'junit:junit:4.13'     ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.200' 
  3.     //引用commonlib 依赖     implementation project(path: ':commonlib') 

1.1.页面布局 hm_sample_ability_video_comments.xml

添加一个VideoPlayerView组件

  1.      xmlns:ohos="http://schemas.huawei.com/res/ohos"     ohos:id="$+id:root_layout" 
  2.     ohos:height="match_parent"     ohos:width="match_parent" 
  3.     ohos:background_element="#FFFFFFFF"     ohos:orientation="vertical"> 
  4.              ohos:id="$+id:video_view"         ohos:height="250vp" 
  5.         ohos:width="match_parent"/> ... 
  6.  

1.2.Java代码

获取视频组件对象后,只需要2步就可以了: 1.设置视频资源路径和描述; 2.设置播放器核心组件和自定义组件.几行关键代码 VideoPlayAbilitySlice.java

  1.  private void initPlayer() { 
  2.     HiLog.debug(LABEL, "initPlayer");     //自定义视频播放视图组件 
  3.     player = (VideoPlayerView) findComponentById(ResourceTable.Id_video_view);  
  4.     if (player != null) {         //获取视频信息服务 
  5.         videoService = new VideoInfoService(getContext());         //获取当前播放视频的路径 
  6.         String path = videoService                 .getVideoInfoByIndex(currentPlayingIndex) 
  7.                 .getResolutions()                 .get(currentPlayingResolutionIndex) 
  8.                 .getUrl();         //视频描述 
  9.         String videoDesc = videoService.getVideoInfoByIndex(currentPlayingIndex).getVideoDesc();         HiLog.debug(LABEL, "videoDesc = " + videoDesc + " path = " + path); 
  10.          if (path != null) { 
  11.             //设置路径和描述             player.setVideoPathAndTitle(path, videoDesc); 
  12.             //视频准备完毕就播放并设置播放进度条             player.setPlayeronPreparedListener( 
  13.                     () -> {                         player.start(); 
  14.                         //设置播放位置                         player.seekTo(currentPlayingPosition); 
  15.                     });             //双击播放或暂停 
  16.             player.setDoubleClickedListener(                     component -> { 
  17.                         //是否在控制TV端                         if (remoteController != null && remoteController.isShown()) { 
  18.                             return;                         } 
  19.                         HiLog.debug(LABEL, "VideoPlayView double-click event");                         if (player.isPlaying()) { 
  20.                             player.pause();                         } else { 
  21.                             player.start();                         } 
  22.                     });             //监听播放错误 
  23.             player.setErrorListener(                     (errorType, errorCode) -> { 
  24.                         ToastDialog toast = new ToastDialog(getContext());                         switch (errorType) { 
  25.                             case HmPlayerAdapter.ERROR_LOADING_RESOURCE:                                 toast.setText( 
  26.                                         AppUtil.getStringResource(                                                 getContext(), ResourceTable.String_media_file_loading_error)); 
  27.                                 break;                             case HmPlayerAdapter.ERROR_INVALID_OPERATION: 
  28.                                 toast.setText(                                         AppUtil.getStringResource( 
  29.                                                 getContext(), ResourceTable.String_invalid_operation));                                 break; 
  30.                             default:                                 toast.setText( 
  31.                                         AppUtil.getStringResource(                                                 getContext(), ResourceTable.String_undefined_error_type)); 
  32.                                 break;                         } 
  33.                         getUITaskDispatcher().asyncDispatch(toast::show);                     }); 
  34.         }         //添加核心组件,播放时间进度滑块 
  35.         addCoreComponent();         //添加自定义组件 
  36.         addCustomComponent();         HiLog.debug(LABEL, "initPlayer finish"); 
  37.     } } 
2.实现一个视频播放列表功能

2.1.页面布局 ability_main.xml

使用了DirectionalLayout布局组件,还有ScrollView和ListContainer组件

  1.      xmlns:ohos="http://schemas.huawei.com/res/ohos"     ohos:id="$+id:ability_main_root" 
  2.     ohos:height="match_parent"     ohos:width="match_parent" 
  3.     ohos:orientation="vertical">  
  4.             ohos:height="match_content"         ohos:width="match_parent" 
  5.         ohos:background_element="#B0B0B0"         ohos:orientation="horizontal" 
  6.         ohos:padding="10vp">  
  7.                     ohos:width="match_content"             ohos:weight="1"> 
  8.                              ohos:id="$+id:tag_favorite"                 ohos:height="match_content" 
  9.                 ohos:width="match_parent"                 ohos:text="关注" 
  10.                 ohos:text_size="$float:normal_text_size_15"                 /> 
  11.           
  12.                     ohos:width="match_content"             ohos:weight="1"> 
  13.                              ohos:id="$+id:tag_support"                 ohos:height="match_content" 
  14.                 ohos:width="match_content"                 ohos:text="推荐" 
  15.                 ohos:text_size="$float:normal_text_size_15"                 /> 
  16.           
  17.                     ohos:width="match_content"             ohos:weight="1"> 
  18.                              ohos:id="$+id:tag_movie"                 ohos:height="match_content" 
  19.                 ohos:width="match_content"                 ohos:element_end="$id:favorite" 
  20.                 ohos:text="电影"                 ohos:text_color="#1C6AE9" 
  21.                 ohos:text_size="$float:normal_text_size_15"                 ohos:text_weight="600"/> 
  22.                              ohos:id="$+id:device_item_divider"                 ohos:height="2vp" 
  23.                 ohos:width="30vp"                 ohos:background_element="$graphic:list_divider"/> 
  24.           
  25.                     ohos:width="match_content"             ohos:weight="1"> 
  26.                              ohos:id="$+id:tag_live"                 ohos:height="match_content" 
  27.                 ohos:width="match_parent"                 ohos:text="直播" 
  28.                 ohos:text_size="$float:normal_text_size_15"                 /> 
  29.           
  30.                     ohos:width="match_content"             ohos:weight="1"> 
  31.                              ohos:id="$+id:tag_tv"                 ohos:height="match_content" 
  32.                 ohos:width="match_parent"                 ohos:text="电视" 
  33.                 ohos:text_size="$float:normal_text_size_15"                 /> 
  34.           
  35.       
  36.             ohos:width="match_parent"         ohos:id="$+id:video_list_scroll" > 
  37.                      ohos:id="$+id:videos_container"             ohos:height="match_parent" 
  38.             ohos:width="match_parent">  
  39.               
  40.  

2.2.Java代码

申请用户敏感权限授权 MainAbility.java

  1.  public class MainAbility extends Ability { 
  2.     private static final int REQUEST_CODE = 1;  
  3.     //读写媒体权限     private final String[] permissionLists 
  4.             = new String[]{"ohos.permission.READ_MEDIA", "ohos.permission.WRITE_MEDIA"};  
  5.     @Override     public void onStart(Intent intent) { 
  6.         super.onStart(intent);         super.setUIContent(ResourceTable.Layout_ability_main); 
  7.         super.setMainRoute(MainAbilitySlice.class.getName());  
  8.         //申请授权         verifyPermissions(); 
  9.     }     private void verifyPermissions() { 
  10.         for (String permissionList : permissionLists) {             int result = verifySelfPermission(permissionList); 
  11.             if (result != IBundleManager.PERMISSION_GRANTED) {                 requestPermissionsFromUser(permissionLists, REQUEST_CODE); 
  12.             }         } 
  13.     } ... 

通过VideoInfoService读取videos.json文件初始化视频容器列表MainAbilitySlice.java

  1. public class MainAbilitySlice extends AbilitySlice {     public static final HiLogLabel LABEL = new HiLogLabel(0, 0, "=>MainAbilitySlice"); 
  2.     private VideoInfoService videoService;  
  3.     @Override     protected void onStart(Intent intent) { 
  4.         super.onStart(intent);         //加载视频播放器页面 
  5.         super.setUIContent(ResourceTable.Layout_ability_main);         initVideoContainer(); 
  6.      } 
  7.           private void initVideoContainer() { 
  8.         HiLog.debug(LABEL, "initVideoContainer");         List videos = new ArrayList<>(); 
  9.         //获取视频信息服务         videoService = new VideoInfoService(getContext()); 
  10.          for (int i = 0; i < 7; i++) { 
  11.             VideoModel video = new VideoModel();             video.setComments(new Random().nextInt(1000)); 
  12.             video.setFavorites(new Random().nextInt(1000));             video.setGreats(new Random().nextInt(10000)); 
  13.             VideoInfo videoInfo = videoService.getVideoInfoByIndex(i);             videoInfo.setIndex(i); 
  14.             video.setVideoInfo(videoInfo);             videos.add(video); 
  15.         }  
  16.         ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_videos_container);         //容器绑定数据提供程序 
  17.         VideoItemProvider provider = new VideoItemProvider(this, videos, this);         listContainer.setItemProvider(provider); 
  18.     } } 

 视频容器列表数据提供程序 VideoItemProvider.java

  1. public class VideoItemProvider extends baseItemProvider {     private static final HiLogLabel LABEL = new HiLogLabel(0, 0, "=>VideoItemProvider"); 
  2.     private final Context context;     private final List list; 
  3.     private AbilitySlice abilitySlice;     //当前播放视频分辨率索引 
  4.     private int currentPlayingResolutionIndex = 0;  
  5.          public VideoItemProvider(Context context, List list, AbilitySlice abilitySlice) { 
  6.         HiLog.debug(LABEL, "VideoItemProvider");         this.context = context; 
  7.         this.list = list;         this.abilitySlice = abilitySlice; 
  8.     }  
  9.     public Context getContext() {         return context; 
  10.     }  
  11.     @Override     public int getCount() { 
  12.         return list == null ? 0 : list.size();     } 
  13.      @Override 
  14.     public Object getItem(int position) {         if (list != null && position >= 0 && position < list.size()) { 
  15.             return list.get(position);         } 
  16.         return new VideoModel();     } 
  17.      @Override 
  18.     public long getItemId(int position) {         return position; 
  19.     }  
  20.     @Override     public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { 
  21.         HiLog.debug(LABEL, "getComponent:" + convertComponent + "," + componentContainer);         final Component cpt; 
  22.         final VideoPlayerView player;  
  23.         VideoModel item = list.get(position);  
  24.         //初次获取组件         if (convertComponent == null) { 
  25.             cpt = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_hm_sample_ability_video_box, componentContainer, false);             player = (VideoPlayerView) cpt.findComponentById(ResourceTable.Id_video_view); 
  26.             //初始化播放器组件             initPlayer(player,item.getVideoInfo()); 
  27.         } else {             //ScrollView滑动时也会调用getComponent方法, 
  28.             cpt = convertComponent;             player = (VideoPlayerView) cpt.findComponentById(ResourceTable.Id_video_view); 
  29.         }  
  30.         //设置其他组件的值         Text text_favorites = (Text) cpt.findComponentById(ResourceTable.Id_text_favorites); 
  31.         Text text_comments = (Text) cpt.findComponentById(ResourceTable.Id_text_comments);         Text text_greats = (Text) cpt.findComponentById(ResourceTable.Id_text_greats); 
  32.         //注意setText的参数类型是字符串         text_favorites.setText(item.getFavorites() + ""); 
  33.         text_comments.setText(item.getComments() + "");         text_greats.setText(item.getGreats() + ""); 
  34.         //点击评论图标,停止当前播放器,打开VideoPlayAbility的Slice页面         Image commentImage = (Image) cpt.findComponentById(ResourceTable.Id_image_comment); 
  35.         commentImage.setClickedListener(component -> {             //停止播放,列表页面的播放器 
  36.             player.stopPlayback();             //打开带有评论的播放页面 
  37.             startVideoPlayDetail(item,player);         }); 
  38.         return cpt;     } 
  39.       
  40.     private void initPlayer(VideoPlayerView player, VideoInfo videoInfo) {         HiLog.debug(LABEL, "initPlayer"); 
  41.         if (player != null) {             //视频路径 
  42.             String path = videoInfo                     .getResolutions() 
  43.                     .get(currentPlayingResolutionIndex)                     .getUrl(); 
  44.             HiLog.debug(LABEL, "path:" + path);  
  45.             //视频描述             String videoDesc = videoInfo.getVideoDesc(); 
  46.             HiLog.debug(LABEL, "videoDesc  = " + videoDesc + " path = " + path);  
  47.             if(path!=null) {                 //设置路径和名称 
  48.                 player.setVideoPathAndTitle(path, videoDesc);                 //双击播放或暂停 
  49.                 player.setDoubleClickedListener(                         component -> { 
  50.                             HiLog.debug(LABEL, "VideoPlayView double-click event");                             if (player.isPlaying()) { 
  51.                                 player.pause();                             } else { 
  52.                                 player.start();                             } 
  53.                         });                 //监听播放错误 
  54.                 player.setErrorListener(                         (errorType, errorCode) -> { 
  55.                             ToastDialog toast = new ToastDialog(getContext());                             switch (errorType) { 
  56.                                 case HmPlayerAdapter.ERROR_LOADING_RESOURCE:                                     toast.setText( 
  57.                                             AppUtil.getStringResource(                                                     getContext(), ResourceTable.String_media_file_loading_error)); 
  58.                                     break;                                 case HmPlayerAdapter.ERROR_INVALID_OPERATION: 
  59.                                     toast.setText(                                             AppUtil.getStringResource( 
  60.                                                     getContext(), ResourceTable.String_invalid_operation));                                     break; 
  61.                                 default:                                     toast.setText( 
  62.                                             AppUtil.getStringResource(                                                     getContext(), ResourceTable.String_undefined_error_type)); 
  63.                                     break;                             } 
  64.                             abilitySlice.getUITaskDispatcher().asyncDispatch(toast::show);                         }); 
  65.             }             //添加核心组件,播放时间进度滑块 
  66.             addCoreComponent(player);             //添加自定义组件 
  67.             HiLog.debug(LABEL, "initPlayer finish");         } 
  68.     }  
  69.      
  70.     private void addCoreComponent(VideoPlayerView player) {         HiLog.debug(LABEL, "addCoreComponent"); 
  71.         //添加播放按钮组件         player.addPlaybackButton(new VideoPlayerPlaybackButton(getContext()), VideoBoxArea.BOTTOM); 
  72.         //添加播放进度条组件         player.addSeekBar( 
  73.                 new VideoPlayerSlider(getContext()),                 VideoBoxArea.BOTTOM, 
  74.                 (int) AppUtil.getFloatResource(getContext(), ResourceTable.Float_normal_margin_24));     } 
  75.       
  76.     private void startVideoPlayDetail(VideoModel item,VideoPlayerView player) {         HiLog.debug(LABEL, "startVideoPlayDetail "); 
  77.         //启动评论播放页面         Intent intentService = new Intent(); 
  78.         //播放视频评论数         intentService.setParam("comments",String.valueOf(item.getComments())); 
  79.          VideoInfo videoInfo=item.getVideoInfo(); 
  80.          if(videoInfo!=null) { 
  81.             //播放视频在播放列表中的索引             intentService.setParam("currentPlayingIndex", videoInfo.getIndex()); 
  82.             //播放视频的分辨率索引             intentService.setParam("currentPlayingResolutionIndex", currentPlayingResolutionIndex); 
  83.             //当前视频播放的位置             intentService.setParam(RemoteConstant.INTENT_PARAM_REMOTE_START_POSITION,(int)player.getCurrentPosition()); 
  84.             HiLog.debug(LABEL,RemoteConstant.INTENT_PARAM_REMOTE_START_POSITION+":"+player.getCurrentPosition());         } 
  85.         Operation operation =                 new Intent.OperationBuilder() 
  86.                         .withDeviceId("")                         .withBundleName(abilitySlice.getBundleName()) 
  87.                         .withAbilityName(VideoPlayAbility.class)                         .build(); 
  88.         intentService.setOperation(operation);         abilitySlice.startAbility(intentService); 
  89.     } } 
3.实现一个评论功能

3.1.页面布局,评论列表布局页 hm_sample_ability_video_comments.xml

使用了StackLayout,DependentLayout布局组件和ListContainer,TextField,Text 组件

  1. ...      
  2.             ohos:height="40vp"         ohos:width="match_parent" 
  3.         ohos:background_element="#FFDDDADA"         ohos:layout_alignment="top" 
  4.         ohos:top_margin="250vp">  
  5.                     ohos:height="match_parent"             ohos:width="match_content" 
  6.             ohos:align_parent_left="true"             ohos:left_margin="10vp" 
  7.             ohos:orientation="horizontal"             ohos:padding="4vp"> 
  8.                              ohos:id="$+id:text_favorites"                 ohos:height="match_parent" 
  9.                 ohos:width="match_parent"                 ohos:left_padding="5vp" 
  10.                 ohos:text="简介"                 ohos:text_size="16fp" 
  11.                 ohos:text_weight="600">  
  12.                       
  13.                      ohos:id="$+id:comment"             ohos:height="match_parent" 
  14.             ohos:width="match_content"             ohos:end_of="$id:favorite" 
  15.             ohos:left_margin="20vp"             ohos:orientation="horizontal" 
  16.             ohos:padding="4vp">  
  17.                             ohos:height="match_parent"                 ohos:width="match_content" 
  18.                 ohos:left_padding="5vp"                 ohos:text="评论" 
  19.                 ohos:text_weight="600"                 ohos:text_size="16fp"> 
  20.               
  21.                             ohos:height="match_parent"                 ohos:width="match_content" 
  22.                 ohos:left_padding="5vp"                 ohos:text="1161" 
  23.                 ohos:text_weight="600"                 ohos:text_size="16fp"> 
  24.                       
  25.       
  26.       
  27.             ohos:height="match_parent"         ohos:width="match_parent" 
  28.         ohos:background_element="#FFFDFFFF"         ohos:top_margin="290vp"> 
  29.                      ohos:id="$+id:comments_container"             ohos:height="match_parent" 
  30.             ohos:width="match_parent"             ohos:layout_alignment="horizontal_center" 
  31.             ohos:orientation="vertical"/>  
  32.       
  33.                  ohos:id="$+id:comments_dialog"         ohos:height="70vp" 
  34.         ohos:width="match_parent"         ohos:background_element="#FFF4F4F8" 
  35.         ohos:layout_alignment="bottom"         ohos:padding="5vp"> 
  36.                      ohos:id="$+id:comment_tf"             ohos:height="match_parent" 
  37.             ohos:width="match_parent"             ohos:hint="发一条友好的评论吧" 
  38.             ohos:right_padding="60vp"             ohos:text_size="16vp"> 
  39.                      ohos:id="$+id:sent_comment"             ohos:height="match_parent" 
  40.             ohos:width="60vp"             ohos:align_parent_right="true" 
  41.             ohos:background_element="#FF7ECCCF"             ohos:text="发送" 
  42.             ohos:input_enter_key_type="enter_key_type_send"             ohos:text_alignment="center" 
  43.             ohos:text_size="16vp">          
  44.      

3.2.页面布局,单条评论组件布局 comments_item.xml

使用了DependentLayout,DirectionalLayout布局组件和Image,Component,Text 组件

  1.      xmlns:ohos="http://schemas.huawei.com/res/ohos"     ohos:height="match_content" 
  2.     ohos:width="match_parent">  
  3.             ohos:height="50vp"         ohos:width="50vp" 
  4.         ohos:end_margin="13vp"         ohos:left_margin="5vp" 
  5.         ohos:image_src="$media:ic_header"         ohos:scale_mode="stretch" 
  6.         ohos:top_margin="13vp"/>  
  7.             ohos:height="match_content"         ohos:width="250vp" 
  8.         ohos:bottom_padding="5vp"         ohos:orientation="vertical" 
  9.         ohos:right_of="$id:header_item_icon">  
  10.                     ohos:height="match_content"             ohos:width="160vp" 
  11.             ohos:layout_alignment="vertical_center"             ohos:padding="5vp" 
  12.             ohos:text="我是一只鱼"             ohos:text_color="#FFA09E9E" 
  13.             ohos:text_size="16vp"/>  
  14.                     ohos:height="match_content"             ohos:width="match_parent" 
  15.             ohos:layout_alignment="vertical_center"             ohos:multiple_lines="true" 
  16.             ohos:padding="5vp"             ohos:text="这是一条评论" 
  17.             ohos:text_color="$color:default_black_color"             ohos:text_size="16vp"/> 
  18.                      ohos:id="$+id:comment_date"             ohos:height="match_content" 
  19.             ohos:width="match_content"             ohos:layout_alignment="vertical_center" 
  20.             ohos:padding="5vp"             ohos:text="2天前" 
  21.             ohos:text_color="#FFA09E9E"             ohos:text_size="16vp"/> 
  22.       
  23.              ohos:height="match_content"         ohos:width="match_content" 
  24.         ohos:id="$+id:goods_view"         ohos:align_parent_right="true" 
  25.         ohos:padding="5vp"         ohos:right_margin="5vp" 
  26.         ohos:right_of="$id:comment_item_content">  
  27.                     ohos:height="25vp"             ohos:width="match_parent" 
  28.             ohos:image_src="$media:ic_great"             ohos:scale_mode="stretch" 
  29.             ohos:top_margin="13vp"             /> 
  30.                      ohos:id="$+id:comment_goods"             ohos:height="match_content" 
  31.             ohos:width="match_parent"             ohos:text="42" 
  32.             ohos:text_alignment="center"             ohos:text_color="#FFA09E9E" 
  33.             ohos:text_size="12vp">  
  34.       
  35.             ohos:width="match_parent"         ohos:align_bottom="$id:comment_item_content"> 
  36.                     ohos:height="1vp"             ohos:width="match_parent" 
  37.             ohos:background_element="$graphic:list_divider"/>      
  38.  

3.3.Java代码

创建评论列表提供程序类 CommentItemProvider.java

  1. public class CommentItemProvider extends baseItemProvider {     private static final HiLogLabel LABEL = new HiLogLabel(0, 0, "=>CommentsItemProvider"); 
  2.     private final Context context;     private final List list; 
  3.     private AbilitySlice abilitySlice;  
  4.          public CommentItemProvider(Context context, List list, AbilitySlice slice) { 
  5.         this.context = context;         this.list = list; 
  6.         this.abilitySlice = slice;     } 
  7.      @Override 
  8.     public int getCount() {         return list == null ? 0 : list.size(); 
  9.     }  
  10.     @Override     public Object getItem(int position) { 
  11.         if (list != null && position >= 0 && position < list.size()) {             return list.get(position); 
  12.         }         return new CommentModel(); 
  13.     }  
  14.     public void addComment(CommentModel comment) {         if (comment == null) return; 
  15.          list.add(0, comment); 
  16.         notifyDataSetItemInserted(0);     } 
  17.      @Override 
  18.     public long getItemId(int position) {         return position; 
  19.     }  
  20.     @Override     public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { 
  21.         final Component cpt;         if (convertComponent == null) { 
  22.             cpt = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_comments_item, null, false);         } else { 
  23.             cpt = convertComponent;         } 
  24.   
  25.         CommentModel item = list.get(position);         //评论人头像 
  26.         Image headerIcon = (Image) cpt.findComponentById(ResourceTable.Id_header_item_icon);         headerIcon.setPixelMap(ResourceTable.Media_ic_header); 
  27.          //评论人名称 
  28.         Text uName = (Text) cpt.findComponentById(ResourceTable.Id_comment_uname);         uName.setText(item.getuName()); 
  29.          //评论内容 
  30.         Text uContent = (Text) cpt.findComponentById(ResourceTable.Id_comment_content);         uContent.setText(item.getCommentContent()); 
  31.         //点击事件         uContent.setClickedListener(component -> { 
  32.             DependentLayout commentDialog = (DependentLayout) abilitySlice.findComponentById(ResourceTable.Id_comments_dialog);             if (commentDialog.getVisibility() == Component.VISIBLE) { 
  33.                 commentDialog.setVisibility(Component.VISIBLE);             } 
  34.             TextField comment = (TextField) abilitySlice.findComponentById(ResourceTable.Id_comment_tf);             comment.setText(""); 
  35.             comment.setHint("回复 " + item.getuName() + ":");             comment.requestFocus(); 
  36.         });  
  37.          //评论日期 
  38.         Text uDate = (Text) cpt.findComponentById(ResourceTable.Id_comment_date);         uDate.setText(item.getCommentDate()); 
  39.          //已赞数 
  40.         Text goods = (Text) cpt.findComponentById(ResourceTable.Id_comment_goods);         HiLog.debug(LABEL, "goods:" + item.getCommentGoods()); 
  41.         goods.setText(item.getCommentGoods() + "");  
  42.         //点赞         Image greatImage = (Image) cpt.findComponentById(ResourceTable.Id_good_icon); 
  43.         //点赞加一         greatImage.setClickedListener(component1 -> { 
  44.             greatImage.setPixelMap(ResourceTable.Media_ic_great_red);             goods.setTextColor(Color.RED); 
  45.             goods.setText((item.getCommentGoods() + 1) + "");         }); 
  46.          if (position == list.size() - 1) { 
  47.             Component divider = cpt.findComponentById(ResourceTable.Id_device_item_divider);             divider.setVisibility(Component.INVISIBLE); 
  48.         }  
  49.         return cpt;     } 

 初始化评论列表和评论功能 VideoPlayAbilitySlice.java

  1.  private void initComments(AbilitySlice slice) { 
  2.     //评论列表,以及设置点击的监听事件、传递数据     ListContainer listContainer = (ListContainer) findComponentById(ResourceTable.Id_comments_container); 
  3.     List list = new ArrayList<>();     for (int i = 0; i < 10; i++) { 
  4.         CommentModel obj = new CommentModel();         obj.setuId(i + ""); 
  5.         obj.setuName(getRandomUname());         obj.setCommentContent(getRandomText()); 
  6.         obj.setCommentDate("刚刚");         obj.setCommentGoods(new Random().nextInt(100)); 
  7.         list.add(obj);     } 
  8.      //容器绑定数据提供程序 
  9.     provider = new CommentItemProvider(this, list, slice);     listContainer.setItemProvider(provider); 
  10.      Component sendComment = findComponentById(ResourceTable.Id_sent_comment); 
  11.     TextField comment = (TextField) findComponentById(ResourceTable.Id_comment_tf);  
  12.     //评论功能     sendComment.setClickedListener(component -> { 
  13.         if (comment.getText().isEmpty()) {             new ToastDialog(getContext()).setText("评论不能为空").show(); 
  14.             return;         } 
  15.         CommentModel model = new CommentModel();         model.setCommentContent(comment.getText()); 
  16.         model.setuId(UUID.randomUUID().toString());         model.setuName("robot"); 
  17.         model.setCommentDate("刚刚");  
  18.         //添加到数据提供程序中         provider.addComment(model); 
  19.          comment.setText(""); 
  20.         //评论数+1         commentsText.setText(String.valueOf(Integer.valueOf(comments) + 1)); 
  21.          new ToastDialog(getContext()).setText("评论成功").show(); 
  22.      }); 
问题总结

1.播放器列表滑动时,会重复添加播放组件的问题

2.评论功能,输入框跟随输入法调整位置的问题(待完善)

3.播放列表滑动时,根据ScrollView的位置控制视频播放(待完善)

4.播放列表中播放视频进度同步到播放详情页的问题(待完善)

文章相关附件可以点击下面的原文链接前往下载

https://harmonyos.51cto.com/resource/1338

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com



 

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/796728.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号