美文网首页
鸿蒙next朋友圈来了

鸿蒙next朋友圈来了

作者: xq9527 | 来源:发表于2024-08-13 09:58 被阅读0次

前言导读

各位同学大家,有段时间没有跟大家见面了,因为最近一直在更新鸿蒙的那个实战课程所以就没有去更新文章实在是不好意思, 所以今天就给大家更新一期实战案例 朋友圈案例 希望帮助到各位同学工作和学习

效果图

image.png image.png

具体实现

  • 定义数据模型

@Observed
class MomentClass {
  public nickName: string;
  public content: string;
  public date: string;
  public showC: boolean;
  public images: string[];

  public iconimage:string;


  constructor(nickName: string,content: string,date: string,showC: boolean,images:string[],iconimage:string) {
    this.nickName = nickName;
    this.content = content;
    this.date = date;
    this.showC = showC;
    this.images = images;
    this.iconimage=iconimage;
  }
}
  • 准备本地数据
      @State momentList: MomentClass[] = [
        new MomentClass('赵云','除非雨落之后任然是雨','刚刚',false,['/image/youning.jpg'],'/image/youning.jpg'),
        new MomentClass('祐宁','如今你的气质里,藏着你走过的路,读过的书和爱过的人','2分之前',false,['/image/xuanwomingren.jpg','/image/zuozhu.jpg','/image/youning.jpg'],'/image/xuanwomingren.jpg'),
        new MomentClass('铠皇','海的遍有我未曾见证的风采','1天前',false,[],'/image/zuozhu.jpg'),
        new MomentClass('韩信','人,总得有个活着的理由。','2天前',false,[],'/image/xuanwomingren.jpg'),
        new MomentClass('鲁班','来的我呀,你打不打开我的哈哈哈 ','8天前',false,[],'/image/xuanwomingren.jpg'),
    
      ];
    
    
  • 底部弹窗实现

    actionSheetShow(){
      ActionSheet.show({
        title: null,
        message: null,
        autoCancel: true,
        confirm: {
          value: '取消',
          action: () => {
            console.log('Get Alert Dialog handled')
          }
        },
        cancel: () => {
          console.log('actionSheet canceled')
        },
        alignment: DialogAlignment.Bottom,
        offset: { dx: 0, dy: 0 },
        sheets: [
          {
            title: '拍摄',
            action: () => {
              console.log('apples')
            }
          },
          {
            title: '从手机相册选择',
            action: () => {
              console.log('bananas')
            }
          },
    
        ]
      })
    }
    
  • 朋友圈信息实现
    @Component
    struct momentrow{
    
      private  index?:number=0;
      @State menuWidth:number = 0.001
      @State menuX:number = 120
      @ObjectLink @Watch('onCountUpdated2') momentItem: MomentClass;
    
      private  selectIndex?:number;
      private  showMenuValue?:boolean;
    
      private  imageClick?:(rowIndex:number,index:number)=>void
    
    
      calcGridColum(){
        if(this.momentItem.images.length == 0){
          return 0
        }else if(this.momentItem.images.length == 1){
          return 200
        } else if(this.momentItem.images.length > 1 && this.momentItem.images.length <= 3){
          return 100
        }else if(this.momentItem.images.length > 3 && this.momentItem.images.length <= 6){
          return 200
        }else {
          return 300
        }
      }
      calcGridRow(){
        if(this.momentItem.images.length == 1){
          return 150
        }else {
          return 300
        }
      }
    
      calcRowsTemplate(){
        if(this.momentItem.images.length <= 3){
          return '1fr'
        }else if(this.momentItem.images.length > 3 && this.momentItem.images.length <= 6){
          return '1fr 1fr'
        }else {
          return '1fr 1fr 1fr'
        }
      }
    
      calcColumnsTemplate(){
        if(this.momentItem.images.length <= 1){
          return '1fr'
        }else if(this.momentItem.images.length == 2){
          return '1fr 1fr'
        }else {
          return '1fr 1fr 1fr'
        }
      }
    
      onCountUpdated2(propName: string): void {
        if(this.momentItem.showC){
          this.menuWidth = 120
          this.menuX = 0
        }else {
          this.menuWidth = 0.001
          this.menuX = 120
        }
    
      }
    
    
    
      build(){
        // Stack({alignContent:Alignment.Bottom}){
          Flex({direction:FlexDirection.Row}){
            Image(this.momentItem.iconimage)
              .width(50)
              .height(50)
              .borderRadius(5)
              .backgroundColor(Color.Red)
            .margin({left:10})
    
            Flex({direction:FlexDirection.Column}){
              Text(this.momentItem.nickName)
                .fontColor('rgb(95,105,134)')
                .fontSize(18)
                .fontWeight(700)
              Text(this.momentItem.content)
                .fontColor('rgb(30,30,30)')
                .fontSize(17)
                .margin({top:8})
                .lineHeight(25)
              .width(330)
    
              Grid(){
                  ForEach(this.momentItem.images, (imagePath: string,index:number) => {
                    GridItem() {
                      Image(imagePath)
                        .onClick(() => {
                          //this.imageClick(this.index,index)
                        })
                    }
                  })
              }
              .columnsTemplate(this.calcColumnsTemplate())
              .rowsTemplate(this.calcRowsTemplate())
              .width(this.calcGridRow())
              .height(this.calcGridColum())
              .columnsGap(7)
              .rowsGap(7)
              .margin({top:5})
    
              Stack({alignContent:Alignment.End}){
                Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.SpaceBetween,alignItems:ItemAlign.Center}){
                  Text(this.momentItem.date)
                    .fontColor('rgb(185,185,185)')
                    .fontSize(13)
                  Text('••')
                    .width(35)
                    .height(18)
                    .borderRadius(5)
                    .fontSize(12)
                    .fontWeight(900)
                    .textAlign(TextAlign.Center)
                    .fontColor('rgb(90,109,150)')
                    .backgroundColor('rgb(247,247,247)')
                    .onClick(()=>{
    
                      animateTo({
                        duration: 300,
                        onFinish:() => {
                          this.momentItem.showC = !this.momentItem.showC
                        }
                      }, () => {
                        if(!this.momentItem.showC){
                          this.menuX = 0
                          this.menuWidth = 120
                        }else {
                          this.menuX = 120
                          this.menuWidth = 0.001
                        }
    
                      })
    
                      this.selectIndex = this.index
                      this.showMenuValue = this.momentItem.showC
                    })
                }
                .padding({right:20})
                .height(40)
    
    
                Flex({direction:FlexDirection.Row,}){
                  Flex({direction:FlexDirection.Row}){
                    Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.Center,alignItems:ItemAlign.Center}){
                      Image($r('app.media.like'))
                        .width(18)
                        .height(18)
                      Text('赞')
                        .fontColor(Color.White)
                        .fontSize(14)
                        .textAlign(TextAlign.Center)
                    }
                    .width(60)
                    .height(40)
                    Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.Center,alignItems:ItemAlign.Center}){
                      Image($r('app.media.commen'))
                        .width(18)
                        .height(18)
                      Text('评论')
                        .fontColor(Color.White)
                        .fontSize(14)
                        .textAlign(TextAlign.Center)
                    }
                    .width(60)
                    .height(40)
    
    
                  }
                  .borderRadius(4)
                  .width(this.menuWidth)
                  .height(40)
                  .position({x:this.menuX})
                  .backgroundColor('rgb(22,22,22)')
    
                }
                .margin({right:60})
                .width(120)
                .height(40)
    
              }
              .height(40)
            }
            .margin({left:10})
          }
      }
    }
    
  • 整体布局实现

    @Entry
    @Component
    struct Index {
      scroller: Scroller = new Scroller()
      @State message: string = 'Hello World'
      @State navHide:boolean = true
    
      @State @Watch('selectIndexChanged') selectIndex:number = 0
      @State  showMenuValue:boolean = false
      // @State @Watch('showPreviewChanged')  showPreviewImage:boolean = false
    
      @State previewAlpha:boolean = false
    
      @State momentList: MomentClass[] = [
        new MomentClass('赵云','除非雨落之后任然是雨','刚刚',false,['/image/youning.jpg'],'/image/youning.jpg'),
        new MomentClass('祐宁','如今你的气质里,藏着你走过的路,读过的书和爱过的人','2分之前',false,['/image/xuanwomingren.jpg','/image/zuozhu.jpg','/image/youning.jpg'],'/image/xuanwomingren.jpg'),
        new MomentClass('铠皇','海的遍有我未曾见证的风采','1天前',false,[],'/image/zuozhu.jpg'),
        new MomentClass('韩信','人,总得有个活着的理由。','2天前',false,[],'/image/xuanwomingren.jpg'),
        new MomentClass('鲁班','来的我呀,你打不打开我的哈哈哈 ','8天前',false,[],'/image/xuanwomingren.jpg'),
    
      ];
    
      @State bigImageIndex:number = 0
      @State bigImageRowIndex:number = 0
      @State bigImageList:string[] = []
    
      selectIndexChanged(){
        console.log("selectIndexChanged333")
        this.configCommentMenu()
      }
    
      actionSheetShow(){
        ActionSheet.show({
          title: null,
          message: null,
          autoCancel: true,
          confirm: {
            value: '取消',
            action: () => {
              console.log('Get Alert Dialog handled')
            }
          },
          cancel: () => {
            console.log('actionSheet canceled')
          },
          alignment: DialogAlignment.Bottom,
          offset: { dx: 0, dy: 0 },
          sheets: [
            {
              title: '拍摄',
              action: () => {
                console.log('apples')
              }
            },
            {
              title: '从手机相册选择',
              action: () => {
                console.log('bananas')
              }
            },
    
          ]
        })
      }
    
    
    
    
      configCommentMenu() {
        let arr:MomentClass[] = []
        for (let i = 0; i < this.momentList.length; i++) {
          let element = this.momentList[i];
          if(i == this.selectIndex){
            element.showC = this.showMenuValue
          }else {
            element.showC = false
          }
          arr.push(element)
        }
        this.momentList = arr;
        console.log("this.momentList:",JSON.stringify(this.momentList))
      }
    
      closeMenu(){
        let arr:MomentClass[] = []
        for (let i = 0; i < this.momentList.length; i++) {
          let element = this.momentList[i];
          element.showC = false
          arr.push(element)
        }
        this.momentList = arr;
      }
    
    
    
      @Builder NavigationMenus() { // CustomBuilder类型的菜单栏
        Row() {
    
          Image($r('app.media.camera_black'))
            .size({ width: 25, height: 25 })
            .margin({ left: 5 })
            .onClick(()=>{
              this.actionSheetShow()
            })
            // .backgroundColor(Color.Black)
        }.justifyContent(FlexAlign.End)
      }
    
      @Builder NavigationTitle() {
        Row(){
          Text("朋友圈")
            .width('100')
        }
        .width('80%')
    
        .justifyContent(FlexAlign.Center)
      }
    
      build() {
        Stack({alignContent:Alignment.Top}){
          Navigation(){
    
            Stack({alignContent:Alignment.Top}){
              List(){
                ListItemGroup(){
                  ListItem(){
                    Stack({alignContent:Alignment.BottomEnd}){
                      Flex() {
                        Image('/image/icon2.png')
                          .width('100%')
                          .height(300)
    
                      }
    
                      Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.End,alignItems:ItemAlign.Center}){
                        Text("祐宁")
                          .fontColor(Color.White)
                          .margin({right:5})
                        Image('/image/youning.jpg')
                          .width(70)
                          .height(70)
                          .borderRadius(8)
                      }
                      .padding({right:10})
                      // .position({x:})
                      .width('100%')
                      .height(70)
                      .margin({bottom:-20})
                      // }
    
                    }
                    .width('100%')
                    .height(300)
                  }
                  .width('100%')
                  .height(300)
                }
    
                ListItemGroup({space:10}) {
    
                  ForEach(this.momentList,(item:MomentClass,index:number)=>{
                    ListItem() {
                      momentrow({index:index,selectIndex:this.selectIndex,showMenuValue:this.showMenuValue,momentItem:item,imageClick:(rowIndex,index)=>{
                        let b = this.momentList[rowIndex]
                        this.bigImageList = b.images
    
                        this.bigImageIndex = index
                        console.log("bigImageList:",this.bigImageList)
    
                        animateTo({ duration: 500 }, () => {
                          // 动画闭包内控制Image组件的出现和消失
                          this.previewAlpha = !this.previewAlpha;
                        })
                      }})
    
                    }
    
                  })
    
                }
                .divider({ strokeWidth: 1, color: 'rgb(247,247,247)', startMargin: 0, endMargin: 0 }) // 每行之间的分界线
    
                .margin({top:30})
              }
              .onScroll((setNumber:number,state:ScrollState)=>{
    
                this.closeMenu()
              })
              .onItemDragEnter((ItemDragInfo)=>{
                console.log('ItemDragInfo:',ItemDragInfo)
              })
              .onScrollIndex((start,end)=>{
                if(start == 0 && end == 1){
                  this.navHide = true
                }
                if(start == 1 && end == 1){
                  this.navHide = false
                }
    
              })
              .width('100%')
              .height('100%')
              .backgroundColor(Color.White)
    
    
              Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.SpaceBetween}){
                Row(){
                  Image($r('app.media.back_white'))
                    .width(25)
                    .height(25)
                }
                .justifyContent(FlexAlign.Center)
                .alignItems(VerticalAlign.Center)
                .width(50)
                .height(50)
                .margin({left:10})
    
                Row(){
                  Image($r('app.media.camera_white'))
                    .width(25)
                    .width(25)
                    .onClick(()=>{
                      this.actionSheetShow()
                    })
                }
                .justifyContent(FlexAlign.Center)
                .alignItems(VerticalAlign.Center)
                .width(50)
                .height(50)
                .margin({right:10})
    
              }
              .visibility(this.navHide?Visibility.Visible : Visibility.Hidden)
            }
          }
          .title(this.NavigationTitle())
          .mode(NavigationMode.Stack)
          .titleMode(NavigationTitleMode.Mini)
          .hideBackButton(false)
          .menus(this.NavigationMenus())
          .size({ width: '100%', height: '100%' })
          .backgroundColor('rgb(237,237,237)')
          .hideTitleBar(this.navHide)
    
    
          if (this.previewAlpha) {
            List({initialIndex:this.bigImageIndex}){
              ForEach(this.bigImageList,(imagePath:string,index:number)=>{
                ListItem(){
                  Image(imagePath)
                    .width('100%')
                    .height('100%')
                    .objectFit(ImageFit.Auto)
                }
              })
    
            }
            .edgeEffect(EdgeEffect.Spring)
            .listDirection(Axis.Horizontal)
            .width('100%')
            .height('100%')
            .backgroundColor(Color.Black)
            .onClick(()=>{
              animateTo({ duration: 500 }, () => {
                // 动画闭包内控制Image组件的出现和消失
                this.previewAlpha = !this.previewAlpha;
              })
            })
            .transition({ type: TransitionType.Insert, translate: { x: 20, y: 20 },scale: { x: 0, y: 0 } })
            .transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })
          }
        }
    
    
      }
    }
    

后续目标

  1. 朋友圈完善成联网发布功能

  2. 配合之前的高仿微信app完善一整个即时通讯的app

  3. 支持评论功能

  4. 支持朋友圈上传小视频功能

最后总结:

因为篇幅有限我也不能整个项目都展开讲,有兴趣的同学能可以关注我B站课程。 后续能我会把这个项目更新到项目里面 供大家学习

B站课程地址:www.bilibili.com/cheese/play…

团队介绍

团队介绍:坚果派由坚果等人创建,团队由12位华为HDE以及若干热爱鸿蒙的开发者和其他领域的三十余位万粉博主运营。专注于分享 HarmonyOS/OpenHarmony,ArkUI-X,元服务,仓颉,团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙 原生应用,三方库60+,欢迎进行课程,项目等合作。

相关文章

  • 华为鸿蒙系统手机来了

    #华为鸿蒙系统手机来了# 当大家还在观望的时候,华为鸿蒙系统1.0版本已经于一年前的华为开发者大会上正式发布。现在...

  • 鸿蒙尾班车,终于来了

  • 鸿蒙如何才能“成功”

    1、鸿蒙为何物? 鸿蒙包括手机鸿蒙和万物鸿蒙,此文讨论的鸿蒙重点是基于万物互联的鸿蒙,而不仅仅是手机鸿蒙。也只有在...

  • 期待鸿蒙越来越好

    近日,华为鸿蒙3.0发布更新,带来了6项新的变化,更新围绕超级终端、鸿蒙智联、万能卡片、流畅性能、隐私安全和信息无...

  • 华为鸿蒙到底是不是安卓系统套了个壳?

    余承东在2月份宣布:鸿蒙将于4月份全面上线,果然没有食言 华为鸿蒙2.0来了,首批升级机型名单包括:Mate X2...

  • BAF to Jimple

    first steps: next steps: next steps: next steps: the end ...

  • 神兽“鸿蒙”来了,华为能翻身吗?

    鸿蒙是个什么鬼? 鸿蒙是谁?听起来萌萌哒,一问却很少有人认识,到底啥是鸿蒙?鸿蒙,中国神话传说的...

  • KMP算法swift版本

    从上图中我们可以分析到,与其说是next数组,不如说是最小公共子前缀数组那么问题来了,怎么求这个next数组呢?根...

  • 黑猴子的家:SVN 服务端安装

    1、双击运行 2、Next 3、Next 4、Next 5、Standard Edition 6、Next 7、I...

  • 路由守卫

    在路由守卫中,只有next()是放行,其他的诸如:next('/logon') 、 next(to)或者 next...

网友评论

      本文标题:鸿蒙next朋友圈来了

      本文链接:https://www.haomeiwen.com/subject/uttjkjtx.html