#HarmonyOS NEXT体验官#仿微信朋友圈 原创

小方头狮子
发布于 2024-8-5 20:35
浏览
0收藏

仿微信朋友圈

本示例通过拉起系统相机实现发布图片评论。

效果预览

#HarmonyOS NEXT体验官#仿微信朋友圈-鸿蒙开发者社区

#HarmonyOS NEXT体验官#仿微信朋友圈-鸿蒙开发者社区

使用说明:

1.启动后点击文本框,再点击相机按钮,拉起系统相机。

2.拍照后返回,点击发布按钮。

工程目录

├──entry/src/main/ets
│  ├──commmon
│  │  └──CommonConstants.ets       // 常量类                             
│  ├──entryability  
│  │  └──EntryAbility.ets          // 程序入口
│  ├──model
│  │  ├──CommentModel.ets          // 评论类
│  │  └──MockCommentData.ets       // 评论数据
│  ├──pages                                     
│  │  └──Index.ets                 // 首页
│  ├──utils                                 
│  │  └──CameraUtils.ets           // 拉起相机
│  └──view
│     ├──CommentInputDialog.ets    // 发布评论弹窗
│     ├──CommentItemView.ets       // 评论组件
│     └──ImageListView.ets         // 评论图片列表
└──entry/src/main/resources        // 应用资源目录

首先需要做签名

#HarmonyOS NEXT体验官#仿微信朋友圈-鸿蒙开发者社区

#HarmonyOS NEXT体验官#仿微信朋友圈-鸿蒙开发者社区

为了方便热重载

#HarmonyOS NEXT体验官#仿微信朋友圈-鸿蒙开发者社区

这里我们主要关注的是几个内容

第一个是model

#HarmonyOS NEXT体验官#仿微信朋友圈-鸿蒙开发者社区

接下来再看一下

图片选择工具类

export async function cameraCapture(context: common.UIAbilityContext): Promise<string> {
  const result: common.AbilityResult = await context.startAbilityForResult({
    action: Constants.ACTION_PICKER_CAMERA,
    parameters: {
      'supportMultiMode': false,
      'callBundleName': context.abilityInfo.bundleName
    }
  });
  if (result.resultCode === 0) {
    const param: Record<string, Object> | undefined = result.want?.parameters;
    if (param !== undefined) {
      const resourceUri: string = param[Constants.KEY_RESULT_PICKER_CAMERA] as string;
      return resourceUri;
    }
  }
  return "";
}

弹窗使用

/*
 * 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 { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { cameraCapture } from '../utils/CameraUtils';
import { ImageListView } from './ImageListView';

const MAX_SELECT_IMAGE: number = 9;
const ID_TEXT_INPUT: string = "id_text_input";
const ID_IMAGE_CAMERA: string = "id_image_camera";
const ID_TEXT_PUSH: string = "id_text_publish";

@CustomDialog
@Component
export struct CommentInputDialog {
  @State selectedImages: string[] = [];
  @State text: string = "";
  @Link textInComment: string;
  @Link imagesInComment: string[];
  controller?: CustomDialogController;
  publish: () => void = (): void => {}

  build() {
    Column() {
      RelativeContainer() {
        TextInput()
          .height($r('app.integer.text_input_height'))
          .padding({
            left: $r('app.integer.text_input_padding_left'),
            right: $r('app.integer.text_input_padding_right'),
            top: $r('app.integer.text_input_padding_top'),
            bottom: $r('app.integer.text_input_padding_bottom')
          })
          .margin({
            right: $r('app.integer.text_input_margin_top')
          })
          .onChange((textInComment: string) => {
            this.text = textInComment;
          })
          .defaultFocus(true)
          .alignRules({
            top: { anchor: "__container__", align: VerticalAlign.Top },
            bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
            left: { anchor: "__container__", align: HorizontalAlign.Start },
            right: { anchor: ID_TEXT_PUSH, align: HorizontalAlign.Start }
          })
          .id(ID_TEXT_INPUT)
        Image($r('app.media.camera'))
          .height($r('app.integer.image_camera_height'))
          .width($r('app.integer.image_camera_width'))
          .onClick(async () => {
            if (this.selectedImages.length >= MAX_SELECT_IMAGE) {
              promptAction.showToast({ message: $r('app.string.most_select_image') });
              return;
            }
            const image: string = await cameraCapture(getContext(this) as common.UIAbilityContext);
            if (image !== "") {
              this.selectedImages.push(image);
            }
          })
          .margin({
            right: $r('app.integer.image_camera_margin_top')
          })
          .alignRules({
            top: { anchor: ID_TEXT_INPUT, align: VerticalAlign.Top },
            bottom: { anchor: ID_TEXT_INPUT, align: VerticalAlign.Bottom },
            right: { anchor: ID_TEXT_INPUT, align: HorizontalAlign.End }
          })
          .id(ID_IMAGE_CAMERA)
        Button($r('app.string.publish'))
          .width($r('app.integer.button_publish_width'))
          .height($r('app.integer.button_publish_height'))
          .borderRadius($r('app.integer.button_publish_border_radius'))
          .backgroundColor($r('app.color.button_publish_background'))
          .fontColor(Color.White)
          .onClick(() => {
            if (this.controller) {
              this.textInComment = this.text;
              this.imagesInComment = this.selectedImages;
              this.publish();
              this.controller.close();
              this.textInComment = "";
              this.imagesInComment = [];
            }
          })
          .alignRules({
            top: { anchor: "__container__", align: VerticalAlign.Top },
            bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
            right: { anchor: "__container__", align: HorizontalAlign.End }
          })
          .id(ID_TEXT_PUSH)
      }
      .height($r('app.integer.relative_container_input_height'))

      if (this.selectedImages.length > 0) {
        ImageListView({ selectedImages: this.selectedImages, imageEnableDelete: true })
      }
    }
    .padding($r('app.integer.column_input_padding'))
    .backgroundColor(Color.White)
    .offset({
      y: $r('app.integer.column_input_dialog_offset_y')
    })
  }
}

ImageListView

const ID_IMAGE: string = 'image';
const ID_DELETE: string = 'delete';

@Component
export struct ImageListView {
  @State selectedImages: ResourceStr[] = [];
  imageEnableDelete: boolean = false;

  build() {
    List({ space: 10 }) {
      ForEach(this.selectedImages, (image: string, index: number) => {
        ListItem() {
          RelativeContainer() {
            Image(image)
              .height($r('app.integer.image_comment_image_height'))
              .width($r('app.integer.image_comment_image_width'))
              .borderRadius($r('app.integer.image_comment_image_border_radius'))
              .alignRules({
                bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
                left: { anchor: "__container__", align: HorizontalAlign.Start }
              })
              .id(ID_IMAGE + index)
            if (this.imageEnableDelete) {
              Image($r('app.media.ic_public_close_filled'))
                .height($r('app.integer.image_delete_height'))
                .width($r('app.integer.image_delete_width'))
                .onClick(() => {
                  if (this.imageEnableDelete) {
                    // 点击图片时删除图片
                    this.selectedImages.splice(index, 1);
                  }
                })
                .alignRules({
                  top: { anchor: "__container__", align: VerticalAlign.Top },
                  right: { anchor: "__container__", align: HorizontalAlign.End }
                })
                .id(ID_DELETE + index)
            }
          }
          .width($r('app.integer.image_relative_container_width'))
          .height($r('app.integer.image_relative_container_height'))
        }
      })
    }
    .height($r('app.integer.list_comment_image_height'))
    .width($r('app.string.percent_100'))
    .padding({
      bottom: $r('app.integer.list_comment_image_padding_bottom')
    })
    .listDirection(Axis.Horizontal)
    .alignSelf(ItemAlign.Start)
  }
}

这里面主要做的就是自定义的组件。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
收藏
回复
举报
回复
    相关推荐