网页多宫格布局及适配(16:9)

前言:网页多宫格布局本来不是一件难实现的功能,是一个比较通用的需求。但是这里的多宫格布局的使用场景是 视频的监控画面布局,这对布局的有了一点要求;一般视频的纵横比在 16:9,所以需要设计一个满足不同分辨率下 16:9 的布局模型。

这里提供一种多个宫格(一宫格、四宫格、六宫格、九宫格、16宫格)的画面布局写法,添加上了不同分辨率下横纵比 16:9 适配,并添加全屏功能。

 

 1、页面绘制(html+css)

由于是在实际项目中遇到的实际问题,所以这里的实例用 vue 的代码来写

1.1、html

    <!-- 最外层盒子,宽高根据设计UI来 -->
    <div class="page" id="preId">
      <!-- 多宫格布局,宽高根据计算适配 -->
      <div class="box" id="split-box">
        <!-- 主盒子 -->
        <div :class="[`box-group${type}`, 'box-com', 'clearfix']" >
          <!-- 子元素 -->
          <div 
          v-for="item in computedGroup"
          class="item" 
          :class="{'item-main':item == '3-1'}"></div>
        </div>
      </div>
    </div>

    <!-- 切换按钮 -->
    <div class="btn">
      <el-button @click="change(1)">1宫格</el-button>
      <el-button @click="change(2)">4宫格</el-button>
      <el-button @click="change(3)">6宫格</el-button>
      <el-button @click="change(4)">9宫格</el-button>
      <el-button @click="change(5)">16宫格</el-button>
    </div>

 1.2 js

  data() {
    return {
      type: 1,
      group1: ["1-1"],
      group2: ["2-1", "2-2", "2-3", "2-4"],
      group3: ["3-1", "3-2", "3-3", "3-4", "3-5",'3-6'],
      group4: ["4-1", "4-2", "4-3", "4-4", "4-5", "4-6", "4-7", "4-8", "4-9"],
      group5: [
        "5-1",
        "5-2",
        "5-3",
        "5-4",
        "5-5",
        "5-6",
        "5-7",
        "5-8",
        "5-9",
        "5-10",
        "5-11",
        "5-12",
        "5-13",
        "5-14",
        "5-15",
        "5-16"
      ],
      st:null,
    };
  },
  computed: {
    computedGroup(){
      let key = 'group'+this.type 
      return  this[key]
    }
  },
  methods: {
    change(type){
      this.type = type
    },
  }

 html + js 主要功能就是点击不同按钮时生成不同子元素,比较简单易懂

1.3、css 样式

  • css样式这块的实现,始终觉得自己写的不是特别简洁。因为这里的宫格需要满足这几个要求:1、宫格之间不要有间隔;2、宫格的宽高不能写死,需要根据外层的宽高来适配,而外层的宽高也是响应式变化的;3、满足上面两点其实并不难,但是还要有一点,每个宫格的横纵比要满足 16:9
  • 基于以上的要求,这里提供一种我写的方法,可做个参考,如果别的同学有更好的写法,可以一起交流。话不多说,直接贴代码。
<style lang="less">
html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

* {
  box-sizing: border-box;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* text-align: center; */
  color: #2c3e50;
  /* margin-top: 60px; */
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  position: relative;
  box-sizing: border-box;
}

.clearfix:after {
  /*伪元素是行内元素 正常浏览器清除浮动方法*/
  content: "";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

.clearfix {
  *zoom: 1;
  /*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/
}

.btn{
  text-align: center;
  margin: 50px auto 0;
}

// 外层盒子
.page{
  width: 80%;
  height: 500px;
  border: 1px solid pink;
  margin: 0 auto;
  overflow: hidden;
}

.box {
  margin: 0 auto;
  aspect-ratio: auto 16 / 9;
}

.box-com {
  width: 100%;
  height: 100%;
  overflow: hidden;
  box-sizing: border-box;

  .item {
    float: left;
    border: 1px solid #707070;
    background: #000;
    color: #fff;
    font-size: 25px;
  }
}

// 一宫格布局
.box-group1 {
  .item {
    width: 100%;
    height: 100%;
  }
}
// 四宫格布局
.box-group2 {
  .item {
    width: 50%;
    height: 50%;
  }
}
// 六宫格布局
.box-group3 {
  background: #000;
  .item-main {
    float: left;
    border: 1px solid #707070;
    width: 66.66%!important;
    height: calc(66.66% - 1px)!important;
    border-bottom: none!important;
    border-right: none!important;
  }
  .item {
    width: 33.33%;
    height: 33.33%;
  }
}
// 九宫格布局
.box-group4 {
  .item {
    width: calc(100% / 3);
    height: calc(100% / 3);
  }
}
// 16宫格布局
.box-group5 {
  .item {
    width: 25%;
    height: 25%;
  }
}
</style>
  •  代码比较已读,本质就是通过百分比来计算的
  • 六宫格比较特殊,他长下面这个样子

按道理来说第一个子盒子宽高应该是 外层盒子的 2/3 。于是写成 66.66%,理论来说是没什么问题的,但是实际上这样处理,高度可能在不足 1px 的地方取整成多 1px,由于是浮动,就把下面元素挤掉了,这里 .box-group3 减掉的 1px 就是这么来的。因为减掉了 1px 于是底部边框索性去掉,看起来更舒服一些。 

2、 16:9 页面响应式适配

前面说了这个多宫格布局是应用在视频监控的需求里面的,视频的宽高比一般是在16:9,为了最大的保持原视频布局,我们盒子也需要保持 16:9 。

具体思路是:

  • 监听分辨率变化,获取 .page 宽高
  • 如果 .page比较宽,就让 .box 高度撑满,宽度适配
  • 如果 .page比较高,就让 .box 宽度撑满,高度适配
  • 上面的比较宽(高)是相对于 16:9 来说的,比如 .pre 的 宽/高 > 16:9, 说明就是比较宽。

贴代码:

  mounted() {
    this.startResize()
  },
  beforeDestroy(){
    // 销毁的时候移除
    this.endResize()
  },
  methods: {
    startResize(){
      this.$nextTick(() => {
        this.resizeTheBox()
      })
      window.addEventListener('resize',this.resizeFun)
    },
    endResize(){
      this.st && clearTimeout(this.st)
      window.removeEventListener('resize',this.resizeFun)
    },
    resizeFun(){
      // 防抖,防止频繁改变
      if(this.st){
          clearTimeout(this.st)
          this.st = null
        }
      this.st = setTimeout(()=>{
        this.$nextTick(()=>{
          this.resizeTheBox()
        })
        clearTimeout(this.st)
        this.st = null
      },100)
    },

    // 容器 16:9 适配
    resizeTheBox(){
      let dom = document.getElementById('preId')
      let width = dom.clientWidth || dom.offsetWidth
      let height = dom.clientHeight || dom.offsetHeight
      let el = document.getElementById('split-box')
      if(width*9 > height*16){
        if(CSS.supports("aspect-ratio", "auto 16 / 9")){
          el.style.width = 'auto'
        }else{
          el.style.width = height*16/9 + 'px'
        }
        // el.style.width = height*16/9 + 'px'
        el.style.height = '100%'
      }else{
        if(CSS.supports("aspect-ratio", "auto 16 / 9")){
          el.style.height = 'auto'
        }else{
          el.style.height = width*9/16 + 'px'
        }
        // el.style.height = width*9/16 + 'px'
        el.style.width = '100%'
      }
    },
  },

 代码可读性是有的,这里就不赘述了。说一下 aspect-ratio,这个 css 属性的作用是元素宽高比。

3、全屏、退出全屏

都写到这儿了,最后分享一个让元素全屏和退出的方法,让监控画面充满整个电脑屏幕

      <el-button @click="handleFull">全屏</el-button>
      <el-button @click="exitFullScreen">退出全屏</el-button>  

 


 handleFull(){
      this.fullScreen(document.getElementById('split-box'));
    },

    fullScreen(el) {
      let rfs =
          el.requestFullScreen ||
          el.webkitRequestFullScreen ||
          el.mozRequestFullScreen ||
          el.msRequestFullScreen,
        wscript;
      if (typeof rfs != "undefined" && rfs) {
        rfs.call(el);
        return;
      }
      if (typeof window.ActiveXObject != "undefined") {
        wscript = new ActiveXObject("WScript.Shell");
        if (wscript) {
          wscript.SendKeys("{F11}");
        }
      }
    },
    // 退出全屏
    exitFullScreen() {
      var el = document,
        cfs =
          el.cancelFullScreen ||
          el.webkitCancelFullScreen ||
          el.mozCancelFullScreen ||
          el.exitFullScreen,
        wscript;
      if (typeof cfs != "undefined" && cfs) {
        cfs.call(el);
        return;
      }
      if (typeof window.ActiveXObject != "undefined") {
        wscript = new ActiveXObject("WScript.Shell");
        if (wscript != null) {
          wscript.SendKeys("{F11}");
        }
      }
    },

 谢谢!

在Android中,ListView通常用于显示一列可滚动的内容,如果要实现多个宫格(Grid View)并且内容能根据屏幕宽度自适应换行,你需要使用`GridView`或`RecyclerView`配合`GridLayoutManager`。`GridLayoutManager`允许你在列表视图中创建网格布局,每个网格中的项目会自动换行以适应屏幕宽度。 以下是实现步骤: 1. **引入依赖**: 如果你使用的是`RecyclerView`,确保已经添加了RecyclerView库: ```xml <implementation 'androidx.recyclerview:recyclerview:1.3.0' /> ``` 2. **创建布局文件**: 使用`ConstraintLayout`或者`LinearLayout`作为根布局,创建一个`GridView`或`RecyclerView`作为主要容器。设置`columnCount`属性,如 `android:numColumns="auto_fit"`(让系统自动调整列数)。 ```xml <androidx.recyclerview.widget.RecyclerView android:id="@+id/grid_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:numColumns="auto_fit" /> ``` 3. **创建Adapter**: 使用`GridLayoutManager`初始化`RecyclerView`的适配器,确保在`onCreateViewHolder`方法中为每个单元格分配正确的布局,并设置宽高比例。 ```java GridLayoutManager layoutManager = new GridLayoutManager(context, GridLayoutManager.AUTO_FIT); recyclerView.setLayoutManager(layoutManager); @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { // 创建并返回ViewHolder,使用合适的布局 View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_grid, parent, false); return new GridViewHolder(itemView); } // ... 实现其他适配器方法,如 onBindViewHolder() ``` 4. **自适应布局**: 在`item_grid.xml`布局文件中,确保子视图(例如`ImageView`, `TextView`等)使用百分比宽度或 wrap_content 以适应网格布局的变化。 ```xml <ImageView android:layout_width="0dp" android:layout_weight="1" android:src="@drawable/your_image" /> ``` 5. **调整网格大小**: 可以根据需要在运行时调整网格大小,例如,当屏幕尺寸变化时,通过监听屏幕变化事件来动态设置`columnCount`。 ```java // 获取屏幕宽度 DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int screenWidth = metrics.widthPixels; // 更新列数 layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return screenWidth <= YOUR_BREAKPOINT ? 1 : AUTO_FIT; } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值