鸿蒙网格布局

https://blog.csdn.net/2401_88463044/article/details/143440323

网格布局

网格布局

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 网格布局
    Grid(){
      // 这里有12个元素
      ForEach([1,2,3,4,5,6,7,8,9,10,11,12], ()=>{
        // 里面的每一项,
        GridItem(){
          // 列组件;默认情况下;会将Column这个组件的宽度为你设置的90进行排列。
          // 当排列不下的时候,就会进行换行。
          Column(){

          }.width(60).height(90).backgroundColor(Color.Pink).border({
            width:1
          })
        }
      })
    }
  }
}

结论:1行默认宽度是360

根据上面的图片。我们可以发现这样一个结论。
1行默认宽度是360

通过columnsTemplate控制列数

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 网格布局
    Grid(){
      // 这里有12个元素
      ForEach([1,2,3,4,5,6,7,8,9,10,11,12], ()=>{
        // 里面的每一项,
        GridItem(){
          // 列组件;默认情况下;会将Column这个组件的宽度为你设置的90进行排列。
          // 当排列不下的时候,就会进行换行。
          Column(){

          }.width(120).height(90).backgroundColor(Color.Pink).border({
            width:1
          })
        }
      })
    }.columnsTemplate('1fr 1fr 1fr 1fr') // 手动显示4列
  }
}

按照上面我们说的:1行360;宽度是120;应该显示3列。
但是我们通过columnsTemplate;可以让1行显示4列

网格布局:rowsTemplate控制行数

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 网格布局
    Grid(){
      // 这里有12个元素
      ForEach([1,2,3,4,5,6,7,8,9,10,11,12], ()=>{
        // 里面的每一项,
        GridItem(){
          // 列组件;默认情况下;会将Column这个组件的宽度为你设置的90进行排列。
          // 当排列不下的时候,就会进行换行。
          Column(){

          }.width(120).height(90).backgroundColor(Color.Pink).border({
            width:1
          })
        }
      })
    }.columnsTemplate('1fr 1fr 1fr')  //3 列
     .rowsTemplate('1fr 1fr 1fr 1fr') // 4行
  }
}

通过rowsTemplate控制占的份数多少

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 网格布局
    Grid(){
      // 这里有12个元素
      ForEach([1,2,3,4,5,6,7,8,9,10,11,12], ()=>{
        // 里面的每一项,
        GridItem(){
          // 列组件;默认情况下;会将Column这个组件的宽度为你设置的90进行排列。
          // 当排列不下的时候,就会进行换行。
          Column(){

          }.width(120).height('100%').backgroundColor(Color.Pink).border({
            width:1
          })
        }
      })
    }.columnsTemplate('1fr 1fr 1fr')  //3 列
     .rowsTemplate('1fr 3fr 1fr') // 3行,中间这一个刚占3份
  }
}

控制行间距:行与行之间的上下间距是10

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 网格布局
    Grid(){
      // 这里有12个元素
      ForEach([1,2,3,4,5,6,7,8,9,10,11,12], ()=>{
        // 里面的每一项,
        GridItem(){
          // 列组件;默认情况下;会将Column这个组件的宽度为你设置的90进行排列。
          // 当排列不下的时候,就会进行换行。
          Column(){

          }.width(120).height('100%').backgroundColor(Color.Pink).border({
            width:1
          })
        }
      })
    }.columnsTemplate('1fr 1fr 1fr')  //3 列
     .rowsTemplate('1fr 3fr 1fr') // 3行,中间这一个刚占3份
      .rowsGap(10) // 行与行之间的上下间距是10
  }
}

columnsGap控制间距

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 网格布局
    Grid(){
      // 这里有12个元素
      ForEach([1,2,3,4,5,6,7,8,9,10,11,12], ()=>{
        // 里面的每一项,
        GridItem(){
          // 列组件;默认情况下;会将Column这个组件的宽度为你设置的90进行排列。
          // 当排列不下的时候,就会进行换行。
          Column(){

          }.width(120).height('100%').backgroundColor(Color.Pink).border({
            width:1
          })
        }
      })
    }.columnsTemplate('1fr 1fr 1fr')  //3 列
     .rowsTemplate('1fr 3fr 1fr') // 3行,中间这一个刚占3份
      .rowsGap(5) // 行与行之间的上下间距是5,
      .columnsGap(10) // 列与列之间的间距是10,向右的间距是10
  }
}

实现抽卡排列图

@Entry
@Component
struct Index {
  @State UserImgSrc: string =  'https://p9-passport.byteacctimg.com/img/user-avatar/473f3e32c874a82e2cf6f844ba77e362~160x160.png';
  @State userImgWidth: number  = 60
  build() {
    // 列容器
    Column(){
      // 网格布局
      Grid(){
        // 这里有6个元素
        ForEach([1,2,3,4,5,6], ()=>{
          // 里面的每一项,
          GridItem(){
            Badge({
              count:111, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
              maxCount: 99,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
              position: BadgePosition.RightTop,
              style:{
                fontSize:10, // 字体大小
                badgeSize:14,// 圆形大小
                badgeColor:'#FF0000' //角标的颜色
              }
            }){
              Image($r('app.media.ka')).width(110).backgroundImageSize(ImageSize.Cover)
            }
          }
        })
      }.columnsTemplate('1fr 1fr 1fr')  // 3列
       .rowsTemplate('1fr 1fr') // 2行
       .height(350)
       .backgroundColor(Color.Pink)
    }
  }
}

如何调整右上角顶部的消息Badge

我们可以通过position的来进行调整

GridItem(){
          Badge({
            count:111, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
            maxCount: 99,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
            position:{
              x:90,
              y:0
            }, // 调整Badge的间距,
            style:{
              fontSize:10, // 字体大小
              badgeSize:14,// 圆形大小
              badgeColor:'#FF0000' //角标的颜色
            }
          }){
            Image($r('app.media.ka')).width(110).backgroundImageSize(ImageSize.Cover)
          }
        }


动态渲染卡片


// 定义接口
interface ImageObjectInfo {
  url:string,
  count:number
}
@Entry
@Component
struct Index {
  @State listCard:ImageObjectInfo[] = [
    {
      url:'app.media.ka',
      count:3,
    },
    {
      url:'app.media.ka',
      count:10,
    },
    {
      url:'app.media.ka',
      count:6,
    },
    {
      url:'app.media.ka',
      count:8,
    },
    {
      url:'app.media.ka',
      count:9,
    },
    {
      url:'app.media.ka',
      count:11,
    }
  ]
  build() {
    // 列容器
    Column(){
      // 网格布局
      Grid(){
        // 这里有6个元素
        ForEach(this.listCard, (item:ImageObjectInfo,index:number)=>{
          // 里面的每一项,
          GridItem(){
            Badge({
              count:item.count, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
              maxCount: 10,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
              position: {
                x:98,
                y:0
              }, // 调整Badge的间距,
              style: {
                fontSize: 10,
                badgeSize: 14,
                badgeColor: '#FF0000',
              }
            }){
              Image($r(item.url)).width(110).backgroundImageSize(ImageSize.Cover)
            }
          }
        })
      }.columnsTemplate('1fr 1fr 1fr')  // 3列
       .rowsTemplate('1fr 1fr') // 2行
       .height(350)
       .backgroundColor(Color.Pink)
    }
  }
}

实现弹窗效果


// 定义接口
interface ImageObjectInfo {
  url:string,
  count:number
}
@Entry
@Component
struct Index {
  @State listCard:ImageObjectInfo[] = [
    {
      url:'app.media.ka',
      count:3,
    },
    {
      url:'app.media.ka',
      count:10,
    },
    {
      url:'app.media.ka',
      count:6,
    },
    {
      url:'app.media.ka',
      count:8,
    },
    {
      url:'app.media.ka',
      count:9,
    },
    {
      url:'app.media.ka',
      count:11,
    }
  ]
  build() {
    // 列容器
    Stack(){
      // 蒙层下的结构布局
      Column(){
        // 网格布局
        Grid(){
          // 这里有6个元素
          ForEach(this.listCard, (item:ImageObjectInfo,index:number)=>{
            // 里面的每一项,
            GridItem(){
              Badge({
                count:item.count, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
                maxCount: 10,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
                position: {
                  x:98,
                  y:0
                }, // 调整Badge的间距,
                style: {
                  fontSize: 10,
                  badgeSize: 14,
                  badgeColor: '#FF0000',
                }
              }){
                Image($r(item.url)).width(110).backgroundImageSize(ImageSize.Cover)
              }
            }
          })
        }.columnsTemplate('1fr 1fr 1fr')  // 3列
        .rowsTemplate('1fr 1fr') // 2行
        .height(350)
        .backgroundColor(Color.Pink)
      }

      // 弹窗的蒙层
      // 层叠布局:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
      // 层叠布局具有较强的组件层叠能力。
      Column(){
        Text('获得生肖卡').fontSize(22).fontColor("#fff").margin({top:30})
        Image($r('app.media.ka')).width(240).margin({top:30, bottom:30}).borderRadius(8)
        Button('开心收下').width(200).border({
          width:2,
          color:'#fff9e0'
        }).backgroundColor(Color.Transparent) // Color.Transparent代表的是完全透明,使用该颜色时,组件或区域的背景会变为透明,直接透出下层内容
      }.width('100%').height('100%').backgroundColor("#cc000000")
    }

  }
}

点击显示弹窗


// 定义接口
interface ImageObjectInfo {
  url:string,
  count:number
}
@Entry
@Component
struct Index {
  // 加载的数据
  @State listCard:ImageObjectInfo[] = [
    {
      url:'app.media.ka',
      count:3,
    },
    {
      url:'app.media.ka',
      count:10,
    },
    {
      url:'app.media.ka',
      count:6,
    },
    {
      url:'app.media.ka',
      count:8,
    },
    {
      url:'app.media.ka',
      count:9,
    },
    {
      url:'app.media.ka',
      count:11,
    }
  ]
  @State maskOpacity:number = 0  // 透明度
  @State  maskZIndex:number = -1
  build() {
    // 列容器
    Stack(){
      // 蒙层下的结构布局
      Column(){
        // 网格布局
        Grid(){
          // 这里有6个元素
          ForEach(this.listCard, (item:ImageObjectInfo,index:number)=>{
            // 里面的每一项,
            GridItem(){
              Badge({
                count:item.count, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
                maxCount: 10,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
                position: {
                  x:98,
                  y:0
                }, // 调整Badge的间距,
                style: {
                  fontSize: 10,
                  badgeSize: 14,
                  badgeColor: '#FF0000',
                }
              }){
                Image($r(item.url)).width(110).backgroundImageSize(ImageSize.Cover)
              }
            }
          })
        }.columnsTemplate('1fr 1fr 1fr')  // 3列
        .rowsTemplate('1fr 1fr') // 2行
        .height(350)
        .backgroundColor(Color.Pink)
        Button('立即抽奖').width(200).margin({
          top:10
        }).onClick(()=>{
          this.maskOpacity = 1
          this.maskZIndex = 100
        })
      }

      // 弹窗的蒙层
      // 层叠布局:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
      // 层叠布局具有较强的组件层叠能力。
      Column(){
        Text('获得生肖卡').fontSize(22).fontColor("#fff").margin({top:30})
        Image($r('app.media.ka')).width(240).margin({top:30, bottom:30}).borderRadius(8)
        Button('开心收下').width(200).border({
          width:2,
          color:'#fff9e0'
        }).backgroundColor(Color.Transparent) // 使用该颜色时,组件或区域的背景会变为透明,直接透出下层内容
          .onClick(()=>{
            this.maskOpacity = 0
            this.maskZIndex = -1
          })
      }.width('100%').height('100%').backgroundColor("#cc000000")
        .opacity(this.maskOpacity)
        .zIndex(this.maskZIndex)
      // .opacity(0) 表示看不见蒙层 1表示可以看见
    }
  }
}

点击显示透明度的变化动画


// 定义接口
interface ImageObjectInfo {
  url:string,
  count:number
}
@Entry
@Component
struct Index {
  // 加载的数据
  @State listCard:ImageObjectInfo[] = [
    {
      url:'app.media.ka',
      count:3,
    },
    {
      url:'app.media.ka',
      count:10,
    },
    {
      url:'app.media.ka',
      count:6,
    },
    {
      url:'app.media.ka',
      count:8,
    },
    {
      url:'app.media.ka',
      count:9,
    },
    {
      url:'app.media.ka',
      count:11,
    }
  ]
  @State maskOpacity:number = 0  // 透明度
  @State  maskZIndex:number = -1
  build() {
    // 列容器
    Stack(){
      // 蒙层下的结构布局
      Column(){
        // 网格布局
        Grid(){
          // 这里有6个元素
          ForEach(this.listCard, (item:ImageObjectInfo,index:number)=>{
            // 里面的每一项,
            GridItem(){
              Badge({
                count:item.count, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
                maxCount: 10,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
                position: {
                  x:98,
                  y:0
                }, // 调整Badge的间距,
                style: {
                  fontSize: 10,
                  badgeSize: 14,
                  badgeColor: '#FF0000',
                }
              }){
                Image($r(item.url)).width(110).backgroundImageSize(ImageSize.Cover)
              }
            }
          })
        }.columnsTemplate('1fr 1fr 1fr')  // 3列
        .rowsTemplate('1fr 1fr') // 2行
        .height(350)
        .backgroundColor(Color.Pink)
        Button('立即抽奖').width(200).margin({
          top:10
        }).onClick(()=>{
          this.maskOpacity = 1
          this.maskZIndex = 100
        })
      }

      // 弹窗的蒙层
      // 层叠布局:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
      // 层叠布局具有较强的组件层叠能力。
      Column(){
        Text('获得生肖卡').fontSize(22).fontColor("#fff").margin({top:30})
        Image($r('app.media.ka')).width(240).margin({top:30, bottom:30}).borderRadius(8)
        Button('开心收下').width(200).border({
          width:2,
          color:'#fff9e0'
        }).backgroundColor(Color.Transparent) // 使用该颜色时,组件或区域的背景会变为透明,直接透出下层内容
          .onClick(()=>{
            this.maskOpacity = 0
            this.maskZIndex = -1
          })
      }.width('100%').height('100%').backgroundColor("#cc000000")
        .opacity(this.maskOpacity)
        .zIndex(this.maskZIndex)
        .animation({
          duration:600 // 800ms内完成透明度的变化
        })
    }
  }
}

图片缩放效果


// 定义接口
interface ImageObjectInfo {
  url:string,
  count:number
}
@Entry
@Component
struct Index {
  // 加载的数据
  @State listCard:ImageObjectInfo[] = [
    {
      url:'app.media.ka',
      count:3,
    },
    {
      url:'app.media.ka',
      count:10,
    },
    {
      url:'app.media.ka',
      count:6,
    },
    {
      url:'app.media.ka',
      count:8,
    },
    {
      url:'app.media.ka',
      count:9,
    },
    {
      url:'app.media.ka',
      count:11,
    }
  ]
  @State maskOpacity:number = 0  // 透明度
  @State  maskZIndex:number = -1
  @State scaleX :number=0
  @State scaleY :number=0
  build() {
    // 列容器
    Stack(){
      // 蒙层下的结构布局
      Column(){
        // 网格布局
        Grid(){
          // 这里有6个元素
          ForEach(this.listCard, (item:ImageObjectInfo,index:number)=>{
            // 里面的每一项,
            GridItem(){
              Badge({
                count:item.count, // 角标数值,小于等于0且小于maxCount时不显示信息标记。
                maxCount: 10,// 最大消息数,超过最大消息时仅显示 maxCount+。如:99+
                position: {
                  x:98,
                  y:0
                }, // 调整Badge的间距,
                style: {
                  fontSize: 10,
                  badgeSize: 14,
                  badgeColor: '#FF0000',
                }
              }){
                Image($r(item.url)).width(110).backgroundImageSize(ImageSize.Cover)
              }
            }
          })
        }.columnsTemplate('1fr 1fr 1fr')  // 3列
        .rowsTemplate('1fr 1fr') // 2行
        .height(350)
        .backgroundColor(Color.Pink)
        Button('立即抽奖').width(200).margin({
          top:10
        }).onClick(()=>{
          this.maskOpacity = 1
          this.maskZIndex = 100
          this.scaleX =1
          this.scaleY =1
        })
      }

      // 弹窗的蒙层
      // 层叠布局:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
      // 层叠布局具有较强的组件层叠能力。
      Column(){
        Text('获得生肖卡').fontSize(22).fontColor("#fff").margin({top:30})
        Image($r('app.media.ka'))
          .width(240)
          .margin({top:30, bottom:30})
          .borderRadius(8)
          // 缩放的时候是600ms完成
          .scale({
            x:this.scaleX,
            y:this.scaleY
          })
          .animation({
            duration:600
          })
        Button('开心收下').width(200).border({
          width:2,
          color:'#fff9e0'
        }).backgroundColor(Color.Transparent) // 使用该颜色时,组件或区域的背景会变为透明,直接透出下层内容
          .onClick(()=>{
            this.maskOpacity = 0
            this.maskZIndex = -1
            this.scaleX =0
            this.scaleY =0
          })
      }.width('100%').height('100%').backgroundColor("#cc000000")
        .opacity(this.maskOpacity)
        .zIndex(this.maskZIndex)
        .animation({
          duration:600 // 800ms内完成透明度的变化
        })
    }
  }
}
.scale({
          x:1,
          y:
        }) //表示不进行缩放 
        .animation({
          duration:600
        }) // 600ms完成这个缩放过程
//
// Math.random() 会产生[0,1)之间的随机数。不包含1哈
// 如果我们想要取到[1,5]之间的随机数,怎么写?
console.log('1', Math.random()*6) // [0,6)
console.log('2', parseInt((Math.random()*6 + '')))
console.log('3', Math.floor(Math.random()*6)) // 向下取整

组件可以嵌套在if语句中的哈

  // 通过if表达式来判断是否执行下面的代码
      if(this.getGift){
        Column(){
          Text('获得生肖卡').fontSize(22).fontColor("#fff").margin({top:30})
          Image($r('app.media.ka'))
            .width(240)
            .margin({top:30, bottom:30})
            .borderRadius(8)
              // 缩放的时候是600ms完成
            .scale({
              x:this.scaleX,
              y:this.scaleY
            })
            .animation({
              duration:600
            })
          Button('开心收下').width(200).border({
            width:2,
            color:'#fff9e0'
          }).backgroundColor(Color.Transparent) // 使用该颜色时,组件或区域的背景会变为透明,直接透出下层内容
            .onClick(()=>{
              this.maskOpacity = 0
              this.maskZIndex = -1
              this.scaleX =0
              this.scaleY =0
            })
        }.width('100%').height('100%').backgroundColor("#cc000000")
        .opacity(this.maskOpacity)
        .zIndex(this.maskZIndex)
        .animation({
          duration:600 // 800ms内完成透明度的变化
        })
      }else{

      }
    }
posted @ 2025-06-26 11:34  南风晚来晚相识  阅读(13)  评论(0)    收藏  举报