前端开发者30分钟搞定鸿蒙布局二

29 阅读10分钟

咖啡喝完没,喝完了,我们就继续看看后面后面布局 除了有传统的线性布局(从上到下 从左到右这种)还有一些特殊的布局 ,前端中还有相对布局 绝对布局  固定布局,响应式页面布局,在鸿蒙中都对应的是什么?

相对定位+绝对定位

一个父容器里面有一个子元素  在父元素的右下架  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
<style>
  .container {
    position: relative; /* 成为子元素绝对定位的参照物 */
    width: 300px;
    height: 200px;
    border: 1px solid gray;
  }
  
  .absolute-child {
    position: absolute;
    bottom: 10px; /* 相对于 container 底部定位 */
    right: 10px;  /* 相对于 container 右侧定位 */
    background: gold;
  }
</style>
</head>

<body>
  <div class="container">
    <div class="absolute-child">右下角按钮</div>
  </div>
</body>
</html>

效果

​编辑

鸿蒙中贼简单 使用position就可以了

 Column() {

         Text("右下角按钮").backgroundColor(Color.Yellow)
           .position({ //位置相对父元素的位置 默认在左上角(0,0)
             right:10,
             bottom:10
           })

    }
    .height(200)
    .width(300)
    .border({
      width:2,
      color:Color.Gray,
      style:BorderStyle.Solid
    })

效果:

​编辑

也可以用 RelativeContainer,用的里面的子元素参考父元素的位置,参考物叫做锚点(anchor后面的目标   相对子元素可以id 用id名称就可以了 )

@Entry
@Component
struct Three {

  build() {
    RelativeContainer() {

         Text("右下角按钮").backgroundColor(Color.Yellow).alignRules({
           right:{anchor:"__container__",align:HorizontalAlign.End},
           bottom:{anchor:"__container__",align:VerticalAlign.Bottom}
         }).offset({
           top:-10,
           right:10
        })

    }
    .height(200)
    .width(300)
    .border({
      width:2,
      color:Color.Gray,
      style:BorderStyle.Solid
    })
  }
}

​编辑

固定布局

场景页面有滚动条,滚动的时候有元素固定在页面的左边 不收到影响

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
  .fixed-sidebar {
    position: fixed;
    top: 100px;
    right: 20px;
    width: 200px;
    border: 1px solid #ddd;
    padding: 10px;
  }
  
  /* 在固定容器内使用相对定位微调元素 */
  .highlight {
    position: relative;  /* 相对于父容器定位 */
    left: -15px;         /* 向左偏移 */
    background: yellow;
    padding: 5px;
  }
</style>
</head>
<body>
  <div class="fixed-sidebar">
    <h3>侧边栏</h3>
    <div class="highlight">特惠内容 ← 相对定位微调</div>
    <p>其他信息...</p>
  </div>
  <div style="height: 2000px;">滚动页面,侧边栏位置不变</div>
</body>

</html>

效果如下

​编辑

鸿蒙中是实现的方式就就没有关键了  依然使用RelativeContainer

@Entry
@Component
struct Four {
  
  build() {
    RelativeContainer() {

      Column(){//悬浮框所在位置
        Text("特惠内容 ← 相对定位微调")
      }.width(100).height(100).border({
        width:2,
        color:Color.Gray,
        style:BorderStyle.Solid
      }).alignRules({
        right:{
          anchor:"__container__",align:HorizontalAlign.End
        }
      }).offset({
        right:10
      })

      List(){
        ListItem(){
          Text("滚动页面, 特惠内容不变")
        }.height(300)
        ListItem(){
          Text("滚动页面, 特惠内容不变")
        }.height(300)
        ListItem(){
          Text("滚动页面, 特惠内容不变")
        }.height(300)
      }.alignRules({//在父元素的左上角开始
        left:{anchor:"__container__",align:HorizontalAlign.Start},
        top:{anchor:"__container__",align:VerticalAlign.Top}
      })


    }
    .height('100%')
    .width('100%')
  }
}

效果如图

​编辑

用鸿蒙中层叠布局也可以实现

@Entry
@Component
struct Four {

  build() {
    Stack({alignContent:Alignment.TopEnd}) { //全部在右上角显示
      //top表示锤子方向上   End表示水平方向结束的地方

      Column(){//悬浮框所在位置
        Text("特惠内容 ← 相对定位微调")
      }.width(100).height(100).border({
        width:2,
        color:Color.Gray,
        style:BorderStyle.Solid
      }).offset({
        right:10
      })

      List(){//容器宽度需要变成100% 不然都回去父元素左边
        ListItem(){
          Text("滚动页面, 特惠内容不变")
        }.height(300)
        ListItem(){
          Text("滚动页面, 特惠内容不变")
        }.height(300)
        ListItem(){
          Text("滚动页面, 特惠内容不变")
        }.height(300)
      }.width("100%")

    }
    .height('100%')
    .width('100%')
  }
}

响应式页面布局

前端中常用媒体查询来做  需求

三种设备宽度 大屏幕 一行显示四个内容块, 中屏幕显示一行显示两个内容块, 小屏幕一行显示一个内容库,内容块的颜色不一样

需求的效果

大宽度屏幕

​编辑

中宽度屏幕

​编辑

小宽度屏幕

​编辑

前端完整代码 有点多

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>响应式内容块布局</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: #333;
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }
        
        header {
            text-align: center;
            padding: 30px 0;
            margin-bottom: 40px;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
        }
        
        h1 {
            font-size: 2.8rem;
            color: #1a2a6c;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
        }
        
        .subtitle {
            font-size: 1.4rem;
            color: #555;
            max-width: 800px;
            margin: 0 auto;
            line-height: 1.6;
        }
        
        .device-indicator {
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 12px 20px;
            border-radius: 30px;
            display: inline-block;
            margin-top: 20px;
            font-weight: bold;
            font-size: 1.2rem;
            box-shadow: 0 4px 10px rgba(0,0,0,0.3);
        }
        
        .blocks-container {
            display: flex;
            flex-wrap: wrap;
            gap: 25px;
            justify-content: center;
            margin-bottom: 40px;
        }
        
        .block {
            background: linear-gradient(135deg, #3498db, #2980b9);
            border-radius: 12px;
            padding: 30px;
            text-align: center;
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
            transition: all 0.3s ease;
            flex: 1 1 calc(25% - 25px);
            min-width: 250px;
            color: white;
        }
        
        .block:hover {
            transform: translateY(-10px);
            box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
        }
        
        .block h3 {
            font-size: 1.8rem;
            margin-bottom: 15px;
        }
        
        .block p {
            font-size: 1.1rem;
            line-height: 1.6;
        }
        
        .block-icon {
            font-size: 3.5rem;
            margin-bottom: 20px;
            color: rgba(255, 255, 255, 0.9);
        }
        
        .info-section {
            background: rgba(255, 255, 255, 0.9);
            padding: 30px;
            border-radius: 15px;
            margin-top: 40px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
        }
        
        .info-section h2 {
            color: #1a2a6c;
            margin-bottom: 20px;
            text-align: center;
            font-size: 2rem;
        }
        
        .media-query-info {
            display: flex;
            justify-content: space-around;
            flex-wrap: wrap;
            gap: 20px;
        }
        
        .device-info {
            background: white;
            padding: 25px;
            border-radius: 10px;
            flex: 1;
            min-width: 300px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
        }
        
        .device-info h3 {
            font-size: 1.5rem;
            color: #1a2a6c;
            margin-bottom: 15px;
            text-align: center;
        }
        
        .device-info ul {
            padding-left: 20px;
        }
        
        .device-info li {
            margin-bottom: 10px;
            font-size: 1.1rem;
            line-height: 1.5;
        }
        
        /* 大屏幕样式 (≥1200px) - 一行4个块 */
        @media (min-width: 1200px) {
            .block {
                background: linear-gradient(135deg, #3498db, #2980b9);
                flex: 1 1 calc(25% - 25px);
            }
            
            .device-indicator::after {
                content: "大屏幕 (≥1200px)";
                background: #3498db;
            }
        }
        
        /* 中屏幕样式 (768px - 1199px) - 一行2个块 */
        @media (min-width: 768px) and (max-width: 1199px) {
            .block {
                background: linear-gradient(135deg, #2ecc71, #27ae60);
                flex: 1 1 calc(50% - 25px);
            }
            
            .device-indicator::after {
                content: "中屏幕 (768px - 1199px)";
                background: #2ecc71;
            }
        }
        
        /* 小屏幕样式 (<768px) - 一行1个块 */
        @media (max-width: 767px) {
            .block {
                background: linear-gradient(135deg, #e74c3c, #c0392b);
                flex: 1 1 100%;
            }
            
            h1 {
                font-size: 2.2rem;
            }
            
            .subtitle {
                font-size: 1.2rem;
            }
            
            .device-indicator::after {
                content: "小屏幕 (<768px)";
                background: #e74c3c;
            }
        }
        
        .device-indicator::after {
            padding: 8px 20px;
            border-radius: 20px;
            display: block;
            color: white;
            font-weight: bold;
        }
        
        footer {
            text-align: center;
            color: white;
            padding: 20px;
            margin-top: 40px;
            font-size: 1.1rem;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>响应式内容块布局</h1>
            <p class="subtitle">使用CSS媒体查询根据不同设备宽度显示不同数量和颜色的内容块。调整浏览器窗口大小查看效果变化。</p>
            <div class="device-indicator"></div>
        </header>
        
        <div class="blocks-container">
            <div class="block">
                <div class="block-icon">📱</div>
                <h3>响应式设计</h3>
                <p>确保网站在各种设备上都能提供良好的用户体验,无论屏幕大小如何。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">💻</div>
                <h3>媒体查询</h3>
                <p>使用@media规则根据设备特性应用不同的CSS样式,实现布局变化。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">📐</div>
                <h3>弹性布局</h3>
                <p>通过Flexbox或Grid实现灵活的布局结构,适应不同屏幕尺寸。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">🌈</div>
                <h3>视觉反馈</h3>
                <p>在不同设备上使用不同颜色方案,提供清晰的视觉指示。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">⚙️</div>
                <h3>性能优化</h3>
                <p>针对不同设备优化资源加载,提升页面加载速度。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">👆</div>
                <h3>触摸友好</h3>
                <p>为移动设备设计更大的触摸目标和合适的手势支持。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">🔍</div>
                <h3>可读性</h3>
                <p>在小屏幕上调整字体大小和行高,确保内容易于阅读。</p>
            </div>
            
            <div class="block">
                <div class="block-icon">🚀</div>
                <h3>现代技术</h3>
                <p>使用CSS变量、Grid布局等现代技术简化响应式开发。</p>
            </div>
        </div>
        
        <div class="info-section">
            <h2>媒体查询实现方式</h2>
            <div class="media-query-info">
                <div class="device-info">
                    <h3>大屏幕 (≥1200px)</h3>
                    <ul>
                        <li>一行显示四个内容块</li>
                        <li>内容块背景:蓝色渐变</li>
                        <li>使用CSS: <code>@media (min-width: 1200px) { ... }</code></li>
                        <li>适合桌面电脑和大尺寸显示器</li>
                        <li>内容块宽度:约25%</li>
                    </ul>
                </div>
                
                <div class="device-info">
                    <h3>中屏幕 (768px - 1199px)</h3>
                    <ul>
                        <li>一行显示两个内容块</li>
                        <li>内容块背景:绿色渐变</li>
                        <li>使用CSS: <code>@media (min-width: 768px) and (max-width: 1199px) { ... }</code></li>
                        <li>适合平板电脑和小型笔记本</li>
                        <li>内容块宽度:约50%</li>
                    </ul>
                </div>
                
                <div class="device-info">
                    <h3>小屏幕 (&lt;768px)</h3>
                    <ul>
                        <li>一行显示一个内容块</li>
                        <li>内容块背景:红色渐变</li>
                        <li>使用CSS: <code>@media (max-width: 767px) { ... }</code></li>
                        <li>适合手机等移动设备</li>
                        <li>内容块宽度:100%</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    
    <footer>
        <p>响应式设计示例 &copy; 2023 | 调整浏览器窗口大小查看不同设备布局效果</p>
    </footer>
</body>
</html>

在鸿蒙实现

@Component
@Entry
struct Five {
  build() {

    Column() {
      GridRow({
        columns: {//占比
          xs: 1,//小屏幕中1表示全部
          sm: 2,//中  2表示全部    1表示 1/2
          md: 4//大   4表示全部   1表示1/4
        },
        gutter: 10,
        breakpoints: {
          value: ['320vp', '600vp', '840vp'],//三个范围
          reference: BreakpointsReference.WindowSize
        },
        direction: GridRowDirection.Row
      }) {

          GridCol() {
            Column().width('100%').height(100).backgroundColor(Color.Red)
          }.span({
            xs: 1,
            sm: 1,
            md: 1
          })

        GridCol() {
          Column().width('100%').height(100).backgroundColor( Color.Yellow)
        }.span({
          xs: 1,
          sm: 1,
          md: 1
        })

        GridCol() {
          Column().width('100%').height(100).backgroundColor( Color.Green)
        }.span({
          xs: 1,
          sm: 1,
          md: 1
        })

        GridCol() {
          Column().width('100%').height(100).backgroundColor( Color.Blue)
        }.span({
          xs: 1,
          sm: 1,
          md: 1
        })

      }
      .width('90%')
      .backgroundColor(0xFAEEE0)
      .padding({ top: 10, bottom: 10 })

    }.width('100%')

  }
}

效果 

宽屏幕

​编辑

中屏幕

​编辑

小屏幕

​编辑

响应式布局核心概念 特别重要

响应式布局(Responsive Design)是一种自适应的设计方法,使网页或应用能够根据用户的设备环境(系统、屏幕尺寸、方向等)自动调整布局和内容展示,提供最佳的用户体验。

核心原则:

  1. 流动网格:使用相对单位(如%、vw/vh)替代固定单位
  2. 弹性媒体:图片、视频等元素能随容器缩放
  3. 媒体查询:根据设备特性应用不同样式规则
  4. 移动优先:从小屏幕开始设计,逐步增强大屏体验

响应式布局关键要素

要素Web实现鸿蒙ArkTS实现说明
布局容器Flexbox/GridGridRow/GridCol创建灵活的布局结构
断点检测@media查询mediaQuery API检测设备特性变化
相对单位%、vw/vhvp(虚拟像素)确保元素相对缩放
状态管理CSS变量@State装饰器响应式更新UI
组件复用CSS类@Builder方法提高代码复用性

结论:响应式布局的核心价值

响应式布局不仅是技术方案,更是以用户为中心的设计哲学。它确保用户在任何设备上都能获得:

  1. 一致的内容体验 - 核心信息完整呈现
  2. 自然的交互方式 - 针对设备优化操作
  3. 高效的性能表现 - 按需加载资源
  4. 无缝的多屏切换 - 设备间体验连贯

随着设备形态的多样化(折叠屏、可穿戴设备等),响应式设计将成为数字产品的基础能力而非可选特性。

通过掌握响应式布局的核心原理和实现技术,开发者可以构建真正"一次开发,多端适配"的高质量应用体验。  

加入鸿蒙班级继续学