纯血鸿蒙ArkUI的网格布局详解

news2025/1/4 15:08:12

网格布局概要

网格布局是由行和列分割的单元格组成,通过指定项目所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力,子组件占比控制能力,是一种重要的自适应布局组件,其使用场景有九宫格图片展示、日历、计算器等。

ArkUI提供了Grid容器组件和子组件GridItem,用于构建网格布局。Grid用于设置网格布局相关参数,GridItem定义子组件相关特征。Grid组件支持使用条件渲染、循环渲染、懒加载等方式生成子组件。

布局与约束

Grid组件为网格容器,其中容器内各条目对应一个GridItem组件,如下图所示。

Grid与GridItem组件的关系

说明:

Grid的子组件必须是GridItem组件。

网格布局是一种二维布局。Grid组件支持自定义行列数和每行每列尺寸占比、设置子组件横跨几行或者几列,同时提供了垂直和水平布局能力。当网格容器组件尺寸发生变化时,所有子组件以及间距会等比例调整,从而实现网格布局的自适应能力。根据Grid的这些布局能力,可以构建出不同样式的网格布局,如下图所示。

网格布局

如果Grid组件设置了宽高属性,则其尺寸为设置值。如果没有设置宽高属性,Grid组件的尺寸默认适应其父组件的尺寸。

Grid组件根据行列数量与占比属性的设置,可以分为三种布局情况:

  • 行、列数量与占比同时设置:Grid只展示固定行列数的元素,其余元素不展示,且Grid不可滚动。(推荐使用该种布局方式)

  • 只设置行、列数量与占比中的一个:元素按照设置的方向进行排布,超出的元素可通过滚动的方式展示。

  • 行列数量与占比都不设置:元素在布局方向上排布,其行列数由布局方向、单个网格的宽高等多个属性共同决定。超出行列容纳范围的元素不展示,且Grid不可滚动。

设置排列方式

设置行列数量与占比

通过设置行列数量与尺寸占比可以确定网格布局的整体排列方式。Grid组件提供了rowsTemplate和columnsTemplate属性用于设置网格布局行列数量与尺寸占比。

rowsTemplate和columnsTemplate属性值是一个由多个空格和'数字+fr'间隔拼接的字符串,fr的个数即网格布局的行或列数,fr前面的数值大小,用于计算该行或列在网格布局宽度上的占比,最终决定该行或列宽度。

行列数量占比示例

如上图所示,构建的是一个三行三列的网格布局,其在垂直方向上分为三等份,每行占一份;在水平方向上分为四等份,第一列占一份,第二列占两份,第三列占一份。

只要将rowsTemplate的值为'1fr 1fr 1fr',同时将columnsTemplate的值为'1fr 2fr 1fr',即可实现上述网格布局。

// 声明背景色数组
let colors: Color[] = [
  Color.Black, Color.Blue, Color.Brown,
  Color.Gray, Color.Green, Color.Grey,
  Color.Orange, Color.Pink, Color.Red
]

@Entry
@Component
struct GridSample {
  build() {
    // 网格布局组件
    Grid() {
      ForEach(colors, (color: Color, index: number) => {
        // 网格布局单元组件
        GridItem().backgroundColor(color)
      }, (index: number) => index.toString())
    }
    // 三行等高划分
    .rowsTemplate('1fr 1fr 1fr')
    // 第一列和第三列占据一个单位的宽度,第二列占据两个单位的宽度
    .columnsTemplate('1fr 2fr 1fr')
  }
}

显示效果如下图所示:

说明:

当Grid组件设置了rowsTemplate或columnsTemplate时,Grid的layoutDirection、maxCount、minCount、cellLength属性不生效。

设置子组件所占行列数

除了大小相同的等比例网格布局,由不同大小的网格组成不均匀分布的网格布局场景在实际应用中也十分常见,如下图所示。

在Grid组件中,可以通过在创建Grid时传入合适的 GridLayoutOptions 实现如下图所示的单个网格横跨多行或多列的场景。其中,irregularIndexesonGetIrregularSizeByIndex 用于仅设置rowsTemplate或columnsTemplate的Grid,onGetRectByIndex 用于同时设置rowsTemplate和columnsTemplate的Grid。

不均匀网格布局

例如计算器的按键布局就是常见的不均匀网格布局场景。例如下图中的计算器,按键“0”和“=”,按键“0”横跨第一、二两列,按键“=”横跨第五、六两行。使用Grid构建的网格布局,其行列标号从0开始,依次编号。

在网格中,可以通过onGetRectByIndex返回的[rowStart,columnStart,rowSpan,columnSpan]来实现跨行跨列布局,其中rowStart和columnStart属性表示指定当前元素起始行号和起始列号,rowSpan和columnSpan属性表示指定当前元素的占用行数和占用列数。

所以“0”按键横跨第一列和第二列,“=”按键横跨第五行和第六行,只要将“0”对应onGetRectByIndex的rowStart和columnStart设为5和0,rowSpan和columnSpan设为1和2,将“=”对应onGetRectByIndex的rowStart和columnStart设为4和3,rowSpan和columnSpan设为2和1即可。

代码如下:

@Entry
@Component
struct GridSample {
  // 布局选项
  layoutOptions: GridLayoutOptions = {
    regularSize: [1, 1], // 绝大多数网格的尺寸,通常是占据1行1列
    onGetRectByIndex: (index: number) => {
      switch (index) {
        // 返回值格式:[<rowStart>, <columnStart>, <rowSpan>, <columnSpan>]
        case 1: return [1, 0, 1, 1] // 从[1, 0]开始,跨行1,跨列1
        case 2: return [1, 1, 1, 1] // 从[1, 1]开始,跨行1,跨列1
        case 3: return [1, 2, 1, 1] // 从[1, 2]开始,跨行1,跨列1
        case 4: return [1, 3, 1, 1] // 从[1, 3]开始,跨行1,跨列1
        case 5: return [2, 0, 1, 1] // 从[2, 0]开始,跨行1,跨列1
        case 6: return [2, 1, 1, 1] // 从[2, 1]开始,跨行1,跨列1
        case 7: return [2, 2, 1, 1] // 从[2, 2]开始,跨行1,跨列1
        case 8: return [2, 3, 1, 1] // 从[2, 3]开始,跨行1,跨列1
        case 9: return [3, 0, 1, 1] // 从[3, 0]开始,跨行1,跨列1
        case 10: return [3, 1, 1, 1] // 从[3, 1]开始,跨行1,跨列1
        case 11: return [3, 2, 1, 1] // 从[3, 2]开始,跨行1,跨列1
        case 12: return [3, 3, 1, 1] // 从[3, 3]开始,跨行1,跨列1
        case 13: return [4, 0, 1, 1] // 从[4, 0]开始,跨行1,跨列1
        case 14: return [4, 1, 1, 1] // 从[4, 1]开始,跨行1,跨列1
        case 15: return [4, 2, 1, 1] // 从[4, 2]开始,跨行1,跨列1
        case 16: return [4, 3, 2, 1] // 从[4, 3]开始,跨行2,跨列1
        case 17: return [5, 0, 1, 2] // 从[5, 0]开始,跨行1,跨列1
        case 18: return [5, 2, 1, 1] // 从[5, 2]开始,跨行1,跨列1
        default: return [0, 0, 1, 4] // 从[0, 0]开始,跨行1,跨列4
      }
    }
  }

  // 显示的文本数组
  texts: string[] = [
    'CE', 'C', '/', 'X', '7', '8', '9', '-', '4', '5', '6', '+',
    '1', '2', '3', '=', '0', '.'
  ]

  build() {
    // 设置使用指定的布局选项layoutOptions
    Grid(undefined, this.layoutOptions) {
      GridItem() {
        Text('0').width('100%').height('100%').backgroundColor('#cccccc')
          .padding(5).fontSize(30).textAlign(TextAlign.End).borderRadius(5)
      }.padding(5)
      ForEach(this.texts, (text: string) => {
        GridItem() {
          Button(text).type(ButtonType.Normal).height('100%').width('100%')
            .backgroundColor('#aaaaaa').borderRadius(5).fontSize(20)
        }.padding(5)
      }, (index: number) => index.toString())
    }
    // 设置4列等宽
    .columnsTemplate("1fr 1fr 1fr 1fr")
    // 设置6行,第一行占据两个单位高度,其余一个单位高度
    .rowsTemplate("2fr 1fr 1fr 1fr 1fr 1fr")
    .height('70%').width('100%').backgroundColor('#eeeeee').padding(5)
  }
}
设置主轴方向

使用Grid构建网格布局时,若没有设置行列数量与占比,可以通过layoutDirection设置网格布局的主轴方向,决定子组件的排列方式。此时可以结合minCount和maxCount属性来约束主轴方向上的网格数量。

主轴方向示意图

当前layoutDirection设置为Row时,先从左到右排列,排满一行再排下一行。当前layoutDirection设置为Column时,先从上到下排列,排满一列再排下一列,如上图所示。此时,将maxCount属性设为3,表示主轴方向上最大显示的网格单元数量为3。

实例代码如下所示:

@Entry
@Component
struct GridSample {
  // 显示的文本数组
  texts: string[] = [
    '1', '2', '3', '4', '5', '6', '7', '8', '9'
  ]

  build() {
    Row() {
      Grid() {
        ForEach(this.texts, (text: string) => {
          GridItem({}) {
            Text(text).height(100).width(100)
              .backgroundColor('#aaaaaa').borderRadius(5).fontSize(20)
              .fontColor(Color.White).textAlign(TextAlign.Center)
          }.padding(5)
        }, (index: number) => index.toString())
      }
      // 注意,如果设置了多个layoutDirection,则最后一次设置的生效
      // 设置主轴方向为行的从左向右
      .layoutDirection(GridDirection.Row)
      // 设置主轴方向为从上向下
      .layoutDirection(GridDirection.Column)
      // 设置主轴方向为从右向左
      .layoutDirection(GridDirection.RowReverse)
      // 设置主轴方向为从下向上
      .layoutDirection(GridDirection.ColumnReverse)
      // 设置主轴方向最多显示3个网格单元,最少3个网格单元
      .maxCount(3)
    }
    .justifyContent(FlexAlign.Center)
    .backgroundColor('#eeeeee')
    .width('100%').height('50%')
  }
}

说明:

  • layoutDirection属性仅在不设置rowsTemplate和columnsTemplate时生效,此时元素在layoutDirection方向上排列。

  • 仅设置rowsTemplate时,Grid主轴为水平方向,交叉轴为垂直方向。

  • 仅设置columnsTemplate时,Grid主轴为垂直方向,交叉轴为水平方向。

在网格布局中显示数据

网格布局采用二维布局的方式组织其内部元素,如下图所示。

通用办公服务

Grid组件可以通过二维布局的方式显示一组GridItem子组件。

@Entry
@Component
struct GridSample {

  texts: string[] = [
    '会议', '签到', '投票', '打印'
  ]

  build() {
    Row() {
      Grid() {
        ForEach(this.texts, (text: string) => {
          GridItem({}) {
            Text(text).height('100%').width('100%')
              .backgroundColor('#aaaaaa').borderRadius(10).fontSize(30)
              .fontColor(Color.White).textAlign(TextAlign.Center)
          }.padding(10)
        }, (index: number) => index.toString())
      }
      .padding(10)
      .rowsTemplate('1fr 1fr')
      .columnsTemplate('1fr 1fr')
    }
    .justifyContent(FlexAlign.Center)
    .backgroundColor('#eeeeee')
    .width('100%').height('50%')
  }
}

对于内容结构相似的多个GridItem,通常更推荐使用ForEach语句中嵌套GridItem的形式,来减少重复代码。

设置行列间距

在两个网格单元之间的网格横向间距称为行间距,网格纵向间距称为列间距,如下图所示。

注意,下图中与父组件边框交界的位置使用了父组件的内边距设置,我们需要注意的是列间距和行间距。

网格的行列间距

通过Grid的rowsGap和columnsGap可以设置网格布局的行列间距。

@Entry
@Component
struct GridSample {
  build() {
    Row() {
      Grid() {
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
        GridItem().backgroundColor('#999999')
      }.rowsTemplate('1fr 1fr 1fr 1fr').columnsTemplate('1fr 1fr 1fr')
      // 设置列间距为10vp
      .columnsGap(10)
      // 设置行间距为10vp
      .rowsGap(10)
    }
    // 设置内边距为10vp
    .padding(10)
    // 子组件水平方向居中显示
    .justifyContent(FlexAlign.Center)
    .backgroundColor('#eeeeee')
    .width('100%').height('65%')
  }
}

构建可滚动的网格布局

可滚动的网格布局常用在文件管理、购物或视频列表等页面中,如下图所示。在设置Grid的行列数量与占比时,如果仅设置行、列数量与占比中的一个,即仅设置rowsTemplate或仅设置columnsTemplate属性,网格单元按照设置的方向排列,超出Grid显示区域后,Grid拥有可滚动能力。

横向可滚动网格布局

如果设置的是columnsTemplate,Grid的滚动方向为垂直方向;如果设置的是rowsTemplate,Grid的滚动方向为水平方向。

如上图所示的横向可滚动网格布局,只要设置rowsTemplate属性的值且不设置columnsTemplate属性,当内容超出Grid组件宽度时,Grid可横向滚动进行内容展示。

案例代码如下:

@Entry
@Component
struct GridSample {

  @State services: Array<string> = [
    '直播', '分类', '领券', '会员', '积分',
    '进口', '充值', '抽奖', '收藏', '更多'
  ]

  build() {
    Column({ space: 5 }) {
      Grid() {
        ForEach(this.services, (service: string, index) => {
          GridItem() {
            Button(service).type(ButtonType.Circle).backgroundColor('#aaaaaa')
              .height('90%').width('90%').stateEffect(false)
          }.width('25%').height('50%')
        }, (service:string):string => service)
      }
      // 只设置rowsTemplate属性,当内容超出Grid区域时,可水平滚动。
      .rowsTemplate('1fr 1fr')
      .rowsGap(15)
      .scrollBar(BarState.Off)
    }.height(185).backgroundColor('#dddddd')
  }
}

控制滚动位置

与新闻列表的返回顶部场景类似,控制滚动位置功能在网格布局中也很常用,例如下图所示日历的翻页功能。

日历翻页如下图所示:

日历翻页

Grid组件初始化时,可以绑定一个Scroller对象,用于进行滚动控制,例如通过Scroller对象的scrollPage方法进行翻页。

在日历页面中,用户在点击“下一页”按钮时,应用响应点击事件,通过指定scrollPage方法的参数next为true,滚动到下一页。

案例代码如下所示:

@Entry
@Component
struct GridSample {
  // 通过Scroller对象的scrollPage方法进行翻页
  private scroller: Scroller = new Scroller()
  months: number[][] = [
    [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
    ], [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
    ], [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
    ], [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
    ], [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
    ], [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
    ]
  ]

  build() {
    Column({ space: 5 }) {
      // 设置滚动控制器
      Grid(this.scroller) {
        ForEach(this.months, (days: number[]) => {
          ForEach(days, (day: number[]) => {
            GridItem() {
              Text(day.toString()).width('100%').height(50)
                .backgroundColor('#aaaaaa').textAlign(TextAlign.Center)
                .fontColor(Color.White).fontWeight(FontWeight.Bold)
            }.padding({ left: 5, top: 5 })
          }, (dayIndex: number) => Math.random().toString() + dayIndex)
        }, (monthIndex: number) => Math.random().toString() + monthIndex)
      }.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
      .scrollBar(BarState.Off)
      .height(220)

      Row({ space: 20 }) {
        Button('上一页')
          .onClick(() => {
            // 调用滚动控制器的方法向下翻页
            this.scroller.scrollPage({ next: false })
          })

        Button('下一页')
          .onClick(() => {
            // 调用滚动控制器的方法向上翻页
            this.scroller.scrollPage({ next: true })
          })
      }
    }.backgroundColor('#eeeeee').height('100%')
  }
}

性能优化

与长列表的处理类似,循环渲染适用于数据量较小的布局场景,当构建具有大量网格项的可滚动网格布局时,推荐使用数据懒加载的方式实现按需迭代加载数据,从而提升列表性能。

当使用懒加载方式渲染网格时,为了更好的滚动体验,减少滑动时出现白块,Grid组件中也可通过cachedCount属性设置GridItem的预加载数量,只在懒加载LazyForEach中生效。

设置预加载数量后,会在Grid显示区域前后各缓存 cachedCount × 列数个GridItem,超出显示和缓存范围的GridItem会被释放。

Grid() {
  LazyForEach(this.dataSource, () => {
    GridItem() {
    }
  })
}.cachedCount(3)

说明:

cachedCount的增加会增大UI的CPU、内存开销。使用时需要根据实际情况,综合性能和用户体验进行调整。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2269489.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeRobot(1)

Train python lerobot/scripts/train.py \ policyact \ envaloha \ env.taskAlohaInsertion-v0 \ dataset_repo_idlerobot/aloha_sim_insertion_human \ load_data一直报错&#xff0c;忘记截图了&#xff0c;反正是ssh报错&#xff0c;下不下来&#xff0c;网…

【C++】B2085 第 n 小的质数

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述题目内容输入格式输出格式题目示例 &#x1f4af;原始做法分析解法源码解析1. 步骤分析2. 问题分析3. 性能问题 &#x1f4af;老师提供的优化解法优化代码每部分解…

Node.js详细安装教程

1.下载 [名称]&#xff1a;Node.js [大小]&#xff1a;26.4 MB [语言]&#xff1a;简体中文 [安装环境]&#xff1a;Win7/Win8/Win10 [Node.js15.11.0下载链接]&#xff1a; 通过网盘分享的文件&#xff1a;Node.js 链接: https://pan.baidu.com/s/12WlNlWlX-1ppdhz…

IDEA 搭建 SpringBoot 项目之配置 Maven

目录 1?配置 Maven 1.1?打开 settings.xml 文件1.2?配置本地仓库路径1.3?配置中央仓库路径1.4?配置 JDK 版本1.5?重新下载项目依赖 2?配置 idea 2.1?在启动页打开设置2.2?配置 Java Compiler2.3?配置 File Encodings2.4?配置 Maven2.5?配置 Auto Import2.6?配置 C…

SpringCloud 系列教程:微服务的未来(三)IService接口的业务实现

本文将介绍 IService 接口的基本业务操作、复杂业务操作、Lambda 方法的使用以及批量增加操作&#xff0c;帮助开发者深入了解如何高效地利用 MyBatis-Plus 提供的功能进行数据库操作。无论是简单的单表查询&#xff0c;还是复杂的多表联动&#xff0c;甚至是大数据量的批量操作…

MAC环境安装(卸载)软件

MAC环境安装&#xff08;卸载&#xff09;软件 jdknode安装node&#xff0c;并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净&#xff0c;可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…

VScode SSH 错误:Got bad result from install script 解決

之前vscode好好的&#xff0c;某天突然连接报错如下 尝试1. 服务器没有断开,ssh可以正常连接 2. 用管理员权限运行vscode&#xff0c;无效 3. 删除服务器上的~/.vscode-server 文件夹&#xff0c;无效 试过很多后&#xff0c;原来很可能是前一天anaconda卸载导致注册表项 步…

MATLAB中与矩阵运算相关的函数简介

d e t ( a ) det(a) det(a)表示求方阵的秩 t r a c e ( a ) trace(a) trace(a)表示求方阵对角线之和 i n v ( a ) inv(a) inv(a)表示求方阵的逆矩阵 t r i u ( a ) triu(a) triu(a)表示求矩阵的上三角部分&#xff0c;其余变成0 t r i l ( a ) tril(a) tril(a)表示求矩阵的…

20241227通过配置nomodeset参数解决更新grub之后,ubuntu20.04.5无法启动的问题

20241227通过配置nomodeset参数解决更新grub之后&#xff0c;ubuntu20.04.5无法启动的问题 2024/12/27 17:34 0.397475]pci0000:00:07.0:DPC:RPPI0 l0gsize 0 is invalid dev/nvmeon1p9:clean,251849/4276224 files,3266309/17089792 blocks 缘起&#xff1a;公司电脑要安装加密…

46. Three.js案例-创建颜色不断变化的立方体模型

46. Three.js案例-创建颜色不断变化的立方体模型 实现效果 知识点 Three.js基础组件 WebGLRenderer THREE.WebGLRenderer是Three.js提供的用于渲染场景的WebGL渲染器。它支持抗锯齿处理&#xff0c;可以设置渲染器的大小和背景颜色。 构造器 antialias: 是否开启抗锯齿&am…

ES elasticsearch-8.17.0-windows-x86_64使用

1、下载ES(elasticsearch 简称 ES 下载链接&#xff1a;https://www.elastic.co/downloads/elasticsearch) ES 下载链接&#xff1a;https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.17.0-windows-x86_64.zip))&#xff0c;需要在修改ES配置&#xff0…

4G报警器WT2003H-16S低功耗语音芯片方案开发-实时音频上传

一、引言 在当今社会&#xff0c;安全问题始终是人们关注的重中之重。无论是家庭、企业还是公共场所&#xff0c;都需要一套可靠的安全防护系统来保障人员和财产的安全。随着科技的飞速发展&#xff0c;4G 报警器应运而生&#xff0c;为安全防范领域带来了全新的解决方案。…

uniapp Stripe 支付

引入 Stripe npm install stripe/stripe-js import { loadStripe } from stripe/stripe-js; Stripe 提供两种不同类型组件 Payment Element 和 Card Element&#xff1a;如果你使用的是 Payment Element&#xff0c;它是一个更高级别的组件&#xff0c;能够自动处理多种支…

java Redisson 实现限流每秒/分钟/小时限制N个

1.引入maven包: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>red…

2D图像测量到3D点云之物体三维尺寸测量!!!!

0&#xff0c;引言 本文将从双目采集的2D图像到3D点云进行转化&#xff0c;并进行物体尺寸测量&#xff0c;旨在为读者展示2D图像如何关联3D点云&#xff0c;并进行相关工业应用。 将2D图像转化为3D点云&#xff0c;并进行物体尺寸测量的技术&#xff0c;在工业领域有着广泛的…

【专题】2024年出口跨境电商促销趋势白皮书报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38722 在当今全球化加速演进、数字经济蓬勃发展的大背景下&#xff0c;跨境电商行业正以前所未有的态势重塑国际贸易格局&#xff0c;成为各方瞩目的焦点领域。 根据亚马逊发布的《2024年出口跨境电商促销趋势白皮书》&#xff0c;…

【亚马逊云】基于Amazon EC2实例部署 NextCloud 云网盘并使用 Docker-compose 搭建 ONLYOFFICE 企业在线办公应用软件

文章目录 1. 部署EC2实例2. 安装 Docker 服务3. 安装docker-compose4. 创建Docker-compose文件5. 创建nginx.conf文件6. 运行docker-compose命令开始部署7. 访问ONLYOFFICE插件8. 访问NextCloud云盘9. 下载并启用ONLYOFFICE插件10. 上传文件测试11. 所遇问题12. 参考链接 1. 部…

Flutter:打包apk,详细图文介绍

困扰了一天&#xff0c;终于能正常打包apk安装了&#xff0c;记录下打包的流程。建议参考我这篇文章时&#xff0c;同时看下官网的构建说明。 官网构建并发布 Android 应用详情 1、AS创建Flutter项目 2、cmd执行命令 生成一个sunluyi.jks的文件&#xff0c;可以自行把sunluyi替…

k8s部署nginx+sshd实现文件上传下载

要通过 nginx 和 sshd 实现文件的上传和下载&#xff0c;通常的做法是结合 SSH 协议和 HTTP 协议&#xff0c;使用 nginx 提供 Web 服务器功能&#xff0c;同时使用 sshd&#xff08;即 SSH 服务&#xff09;来处理通过 SSH 协议进行的文件传输。 SSH 实现文件的上传和下载&…

Java开发生态2024年度总结报告

1 关键要点 尽管数据显示 Java 17 是最常用 JDK&#xff0c;但其用户占比并未超过半数。根据 New Relic 2024 Java 生态系统状态报告&#xff0c;Java 17、11 和 8 的用户比例分别为 35%、33% 和 29%。New Relic 数据中所谓“快速采用”指 Java 21 的采用率仅为 1.4%。虽相较 J…