精华内容
下载资源
问答
  • 网格布局

    2021-01-12 17:11:34
    能说出网格布局常用的属性 能利用网格布局实现简单的界面设计 一、网格布局概述 1、布局特点 GridLayout布局使用虚细线将布局划分为行、列和单元格,也支持一个控件在行、列上都有交错排列。 2、继承关系图 3、常用...

    零、学习目标
    能说出网格布局常用的属性
    能利用网格布局实现简单的界面设计
    一、网格布局概述
    1、布局特点
    GridLayout布局使用虚细线将布局划分为行、列和单元格,也支持一个控件在行、列上都有交错排列。
    2、继承关系图
    在这里插入图片描述
    3、常用属性
    (1)针对布局的属性
    rowCount:行数
    columnCount:列数
    (2)针对子控件的属性
    layout_row:子控件在布局的行数
    layout_column:子控件在布局的列数
    layout_rowSpan:跨行数
    layout_columnSpan:跨列数
    二、案例演示——计算器界面
    (一)运行效果
    在这里插入图片描述
    (二)涉及知识点

    1、网格布局(GridLayout)
    2、线性布局(LinearLayout)
    3、文本视图(TextView)
    4、按钮(Button)
    (三)实现步骤
    1、创建安卓应用【GridLayoutCalculator】
    在这里插入图片描述
    在这里插入图片描述
    2、将一张背景图片拷贝到drawable目录里
    在这里插入图片描述
    3、主布局资源文件activity_main.xml
    在这里插入图片描述

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    android:orientation="vertical"
    android:padding="15dp"
    android:gravity="center_horizontal"
    tools:context="net.hw.calculator.MainActivity">
    
    <GridLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:columnCount="5"
    android:rowCount="7">
    
    <TextView
    android:layout_width="320dp"
    android:layout_height="50dp"
    android:layout_row="0"
    android:layout_column="0"
    android:layout_columnSpan="5"
    android:gravity="right"
    android:background="@drawable/custom_border"
    android:paddingRight="10dp"
    android:text="0123456789"
    android:textColor="#0000ff"
    android:textSize="25sp"
    android:layout_marginBottom="30dp"/>
    
    <Button
    android:layout_width="65dp"
    android:layout_row="1"
    android:layout_column="0"
    android:text="MC" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="1"
    android:layout_column="1"
    android:text="MR" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="1"
    android:layout_column="2"
    android:text="MS" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="1"
    android:layout_column="3"
    android:text="M+" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="1"
    android:layout_column="4"
    android:text="M-" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="2"
    android:layout_column="0"
    android:text="←" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="2"
    android:layout_column="1"
    android:text="CE" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="2"
    android:layout_column="2"
    android:text="C" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="2"
    android:layout_column="3"
    android:text="±" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="2"
    android:layout_column="4"
    android:text="√" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="3"
    android:layout_column="0"
    android:text="7" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="3"
    android:layout_column="1"
    android:text="8" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="3"
    android:layout_column="2"
    android:text="9" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="3"
    android:layout_column="3"
    android:text="/" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="3"
    android:layout_column="4"
    android:text="%" />
    
    
    <Button
    android:layout_width="65dp"
    android:layout_row="4"
    android:layout_column="0"
    android:text="4" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="4"
    android:layout_column="1"
    android:text="5" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="4"
    android:layout_column="2"
    android:text="6" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="4"
    android:layout_column="3"
    android:text="*" />
    
    <Button
    android:layout_width="65dp"
    android:layout_row="4"
    android:layout_column="4"
    android:text="1/x" />
    
    

    4、在drawable目录里添加custom_border.xml
    在这里插入图片描述
    5、启动应用,查看效果
    在这里插入图片描述
    三、课后作业
    1、网格布局练习1
    在这里插入图片描述
    2、网格布局练习2
    在这里插入图片描述
    图片配文字
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 其中网格布局(grid)作为css3的产物,它更加贴近网页设计师所使用的布局策略,学习并利用好它可以让我们免受很多布局困扰。虽然网格布局好处有很多,但学习起来并不简单,原因是用来设置布局的属性实在太多,其中光是...

    所有奇技淫巧都只在方寸之间。

    几乎从我们踏入前端开发这个领域开始,就不停地接触不同的布局技术。从常见的浮动到表格布局,再到如今大行其道的flex布局,css布局技术一直在不断地推陈出新。其中网格布局(grid)作为css3的产物,它更加贴近网页设计师所使用的布局策略,学习并利用好它可以让我们免受很多布局困扰。

    虽然网格布局好处有很多,但学习起来并不简单,原因是用来设置布局的属性实在太多,其中光是作用于父容器的属性就有17种,再加上子元素属性有10种,另外还有这些属性值的不同取值方式。这些对于记忆来说绝对是个不小的负担。那么这么多属性以及用法,要如何在短时间内消化掉呢?在接下来这篇文章里,我将针对这27种属性以及它们各自的用法,分享我独家的学习策略,希望对大家的学习有所帮助。

    布局之道

    CSS作为一种网页排版设计语言,其核心的设计思想必然要遵守相关的领域知识。网格布局是一种二维布局结构,它是由纵横相交的两组网格线形成的框架性布局结构。网页设计者可以利用这些由行(row)和列(column)形成的框架性结构来布局设计元素。

    在定义一种网格布局结构的时候,我们需要在父容器上描述要布局的主体框架结构。为了描述这一框架结构,我们就需要给它的基本构成元素命名。一个网格布局的构成元素可以概括为以下几种概念:

    row line: 行线

    column line: 列线

    track: 网格轨道,即行线和行线,或列线和列线之间所形成的区域,用来摆放子元素

    gap: 网格间距,行线和行线,或列线和列线之间所形成的不可利用的区域,用来分隔元素

    cell: 网格单元格,由行线和列线所分隔出来的区域,用来摆放子元素

    area: 网格区域,由单个或多个网格单元格组成,用来摆放子元素

    2da7ef77e400

    grid基本概念

    牢记上述这些概念是之后熟练掌握和应用网格布局的基础。

    构建之法

    要熟练掌握一门技术,核心是找到最基本的套路,然后不断练习从而可以在之后的实践过程中减少决策的时间。所以,这一部分主要就是介绍网格布局构建过程中的一些常用套路。

    这里我们要解决的问题是,如何利用最基本的规则来构建出理想的布局模型。在布局过程中,归根结底需要处理的就两种页面元素:父容器和子元素。前者主要用来设置基础的布局框架,相当于建筑中的设计蓝图,而后者就是用来进行个性化的布局调整。因此我个人归纳了在使用网格布局过程中的套路是:针对父容器元素进行设置需要三个步骤:定框架、设间隔和找对齐,对子元素来说有两个步骤:摆位置和找对齐。我把它们统称为"32构建之法"。

    在这一小节中,我将把重心主要放在网格布局中所有用到的27个属性名的讲解上,而取值逻辑将在最后一部分进行统一介绍。

    父容器

    定框架

    设置父容器的网格布局的第一步就是将父容器的盒模型设置为grid,这样就能触发渲染引擎的网格布局算法。

    .parent {

    display: grid;

    }

    接着我们要开始准备"画线",即设置所需行和列的基础线。这些线条将构成我们接下来进行布局排布的基础模板(template)。在画线过程中,我们需要分别根据行(row)和列(column)两个维度进行设置。你需要画几条线,就设置几个值(不包括边框),其取值是轨道(track)的大小。这里我先画出一个3x3的网格框架,代码如下:

    .parent {

    display: grid;

    grid-template-rows: 100px 100px 100px;

    grid-template-columns: 100px 100px 100px;

    }

    在这里你也可以选择使用缩写形式同时为行和列设置值,采用/分隔开:

    .parent {

    display: grid;

    grid-template: 100px 100px 100px / 100px 100px 100px;

    }

    2da7ef77e400

    image.png

    画完线后,下一步我们可以选择为这些线条和线条之间形成的网格区域(area)进行命名,这样在后续使用的时候就能直接使用这些名字,便于子元素的定位。

    .parent {

    display: grid;

    grid-template-areas: "a a b"

    "c d e"

    "c d ."

    }

    上面这两步画线和命名同样可以采用缩写形式进行设置,代码如下:

    .parent {

    display: grid;

    grid-template: "a a b" 101px

    "c d e" 102px

    "c d ." 103px / 104px 105px 105px

    }

    因为使用grid-template同时设置行列和区域名的写法比较复杂,为了讲解方便,我把值设置成规律的递增数字。其中(101, 102,103)设置的是grid-template-rows的值,而(104,105,106)设置的则是grid-template-columns的值。

    2da7ef77e400

    image.png

    到这一步,我们可以说已经完成所需工作的一大半了。

    设间隔

    间距(gap)的设置在实际开发中是可选的,主要根据网页设计的需求而定。如果你需要给网格线之间设置间距,我们可以在行列两个维度上分别进行设置, 下面这段代码将给每个行和列分别设置10px的间隔:

    .parent {

    display: grid;

    grid-template: 100px 100px 100px / 100px 100px 100px;

    grid-row-gap: 10px;

    grid-column-gap: 10px;

    }

    如果采用缩写形式,上述代码又可以简化成:

    .parent {

    display: grid;

    grid-template: 100px 100px 100px / 100px 100px 100px;

    grid-gap: 10px 10px;

    }

    设置后的效果如下:

    2da7ef77e400

    找对齐

    有了前面两个步骤,我们的网格布局框架基本上算是搭建得差不多了。每个子元素都会默认占据一个网格区域。而在父容器这里我们如果有需要,就要进行最后一个步骤:找对齐。所谓对齐方式,可以分为内部和外部两种(前者是针对每个网格区域的子元素而言,而后者是相对于网格区域本身)。另外在行和列(更专业的术语是main axis和cross axis)上又各自有两个维度,这就构成了4种设置对齐的方式。

    先来处理一下每个子元素相对网格区域内部的对齐方式:

    .parent {

    display: grid;

    grid-template: 100px 100px 100px / 100px 100px 100px;

    grid-gap: 10px 10px;

    justify-items: center;

    align-items: center;

    }

    在上面的代码中我分别在行和列方向上都设置了居中对齐,这样每个网格区域中的子元素相对于各自的区域行为是一致的,都能均匀排布。可以看到效果如下图所示:

    2da7ef77e400

    image.png

    再来看一下另一种情况:

    .parent {

    display: grid;

    width: 500px;

    height: 500px;

    grid-template: 100px 100px 100px / 100px 100px 100px;

    grid-gap: 10px 10px;

    justify-content: space-between;

    align-content: center;

    }

    有时候我们设置的网格不足以覆盖整个父容器的大小时,比如在上述的例子中整个父容器有500px*500px的大小,而我们只设置了300px*300px的网格区域,这时候就需要指定多出来空间的处理规则。justify-content和align-content就是分别在行和列两个方向上用来解决这个问题的属性。它们将针对每个网格区域去设置其在父容器中的对齐方式。

    2da7ef77e400

    image.png

    justify和align这两个单词在方向上比较容易搞混,所以我在记忆上采取的方式是记住justifyrow和aligncolumn这两个合并词,它们长度差不多。如果你有更好的记忆方式,请留言告诉我。

    子元素

    我们通过在父容器上搭建好了基础的框架后,对于大部分子元素来说,就已经能够很好地满足布局要求了。针对部分子元素,可以根据需求进行微调。如果要在子元素上进行布局微调,通常需要以下两个步骤:摆位置和找对齐。

    摆位置

    像下棋一样,针对子元素的排布,我们需要给它们指定要摆放的具体位置。要确定具体位置,可以利用之前在父容器中所指定的线名和区域名来定位。一种方式是直接通过设置起始行,结束行和起始列,结束列来给子元素划定它所要摆放的区域,另外一种方式是指定要摆放的区域名。

    /* 指定起始行,结束行,起始列,结束列 */

    .child:first-child {

    grid-row-start: 1;

    grid-row-end: 2;

    grid-column-start: 1;

    grid-column-end: 3;

    background: red;

    }

    /* 使用缩写形式 */

    .child:nth-child(2) {

    grid-row: 2/3;

    grid-column: 2/4;

    background: yellow;

    }

    /* 直接指定区域名 */

    .child:nth-child(3) {

    grid-area: i;

    background: green;

    }

    这段代码的效果如下:

    2da7ef77e400

    image.png

    还有一种更加灵活的设置位置方式,是指定跨越的行数和列数,关键字span用来控制一次跨越的行数或列数, 如上面第三个子元素可以改写成:

    .child-nth-child(3) {

    grid-row: 2/3;

    grid-column: span 2;

    }

    找对齐

    和父容器中所设置的对齐方式类似,针对个别子元素的对齐处理,我们可以按照行列两组属性进行分别处理:

    /* 列对齐 */

    .child:nth-child(1) {

    align-self: end;

    }

    /* 行对齐 */

    .child:nth-child(2) {

    justify-self: end;

    }

    /* 采用缩写形式 */

    .child:nth-child(3) {

    place-self: center center;

    }

    2da7ef77e400

    image.png

    *隐式网格

    灵活性是网格布局的一大优势,除了采用上述那种手动指定框架结构的方式,网格布局还有一套自动化布局的机制,这套机制称为“隐式网格布局”。当我们在网格定义的区域外放置子元素时,或因子元素数量过多而需要更多的网格线时,布局算法就会自动生成隐式网格。默认情况下这些隐式网格的大小也会随着内容尺寸不同而变化,而我们可以利用属性grid-auto-rows和grid-auto-columns来控制隐式网格的大小。

    考虑下面这个例子:

    .parent {

    display: grid;

    grid-auto-rows: 100px;

    grid-auto-columns: 100px;

    }

    通过手动在父容器中设置隐式网格大小为100x100的大小后,效果如下:

    2da7ef77e400

    image.png

    如果子元素引用了不存在的行号和列号,父容器会自动生成隐式网格以容纳所有子元素:

    .child:first-child {

    grid-row-start: 1;

    grid-row-end: 2;

    grid-column-start: 1;

    grid-column-end: 3;

    background: red;

    }

    2da7ef77e400

    image.png

    有了网格大小的控制,我们还需要位置的控制。默认情况下,子元素都是先将行填充满,容器大小不够的时候才会生成新的隐式行。如果要改变这一默认行为,我们需要使用grid-auto-flow属性来控制:

    .parent {

    display: grid;

    grid-auto-rows: 100px;

    grid-auto-columns: 100px;

    grid-template-areas: "a b c" "d e f" "g h i";

    grid-auto-flow: column;

    }

    2da7ef77e400

    image.png

    取值之术

    介绍完所有的网格布局属性后,我们再来说一下各种属性的取值策略。

    大小

    在CSS中,我们通常使用px,em等取值单位进行属性大小的设置,对于灵活的布局需求来说,百分比也是常用的取值单位。这些单位在平常工作中似乎已经足够用了。不过,为了让布局能够更加灵活,网格布局中引入了一种新单位fr,它是fraction这个单词的缩写,意思是容器内剩余空间的分数比。考虑下面这个例子:

    .parent {

    height: 100px;

    display: grid;

    grid-template-columns: 100px 1fr 100px;

    }

    我们通过设置100px 1fr 100px的布局框架,从而很轻松地就实现了两边宽度固定,中间自适应的效果。

    2da7ef77e400

    image.png

    如果要实现有比例关系的布局结构,还可以使用多个fr的取值:

    .parent {

    width: 400px;

    height: 100px;

    display: grid;

    grid-template-rows: 100px 1fr 100px;

    grid-template-columns: 1fr 1fr 2fr;

    grid-template-areas: "a b c"

    }

    可以看到区域a,b,c之间的比例关系就是"1:1:2"的关系。

    2da7ef77e400

    image.png

    除了上述这个支持自适应的单位外,网格布局中还能够使用max-content和min-content这组关键字来达到自适应的目的。要理解这两个关键字,首先需要理解内在尺寸(intrinsic size)和外部尺寸(extrinsic size)这两个概念。先说一下extrinsic size,它的相对值计算是相对于父容器对应的属性值。我们知道,width如果使用百分比单位,其计算值是相对于该元素所在的容器宽度的,比如父容器宽度100px, 子元素设置width: 20%,那么它的宽度就是100px * 20% = 20px。在css3中引入了intrinsic size则是相对于元素自身尺寸进行计算。max-content和min-content就是相对于元素自身内容块进行计算的属性值。

    min-content顾名思义是根据元素内容来设置的最小宽度大小,在英文句子中,通常是最长单词的那个长度,而中文中则是一个字的长度。比如下面这个例子:

    .parent {

    display: grid;

    grid-template-columns: auto min-content auto;

    }

    2da7ef77e400

    image.png

    可以看到,中间那个网格的那个宽度就等于scq000这个单词的长度。

    与min-content相对应,max-content会将尺寸设置成内容尺寸能达到的最大宽度。我们把代码改成下面这样:

    .parent {

    display: grid;

    grid-template-columns: auto max-content auto;

    }

    2da7ef77e400

    image.png

    有了这两个属性值,我们可以很容易地让布局区域根据内容进行自适应。

    函数

    函数是用来避免重复性工作的一种有效工具,在网格布局中提供了一些常用CSS函数来方便我们的工作。

    第一个要介绍的是minmax这个函数。在设置网格框架的过程中,对于自适应的网格区域,我们都会设置一个最小值和最大值,这个函数就是用来实现这个目的的。

    .parent {

    display: grid;

    grid-template-columns: 100px minmax(100px, 200px) 100px;

    }

    /* 最常用的情况是只设置最小,不设置最大值 */

    .parent {

    display: grid;

    grid-template-columns: 100px minmax(100px, auto) 100px;

    }

    利用这个函数设置的网格布局可以做到很好的自适应,在页面伸缩过程中也能保证布局的稳定性。

    另一个很有用的函数是fit-content,它实际上是min(maximum size, max(minimum size, argument))的简写,表示将元素宽度收缩到内容宽度。说得通俗点就是,使用这个函数后会尽量不占用多余的空间。如果内容的宽度小于fit-content中设置的长度,那么实际子元素宽度是内容宽度。如果内容宽度超出了fit-content中设置的长度,那么实际子元素宽度就是设置的那个长度。下面看两个例子:

    .parent {

    display: grid;

    grid-template-rows: auto fit-content(200px) auto;

    }

    2da7ef77e400

    image.png

    2da7ef77e400

    image.png

    第一个句子中的长度超出了200px,那么此时中间网格的宽度是200px。而第二个例子中内容宽度不足200px,此时中间网格的宽度是句子实际占用的宽度。

    最后要介绍的是repeat函数,它主要用来批量设置框架的间距,这个函数接受两个参数,第一个参数控制循环次数,第二个参数控制间距大小。让我们用这个函数改写一下上述例子:

    .parent {

    display: grid;

    grid-template-rows: 100px 100px 100px;

    grid-template-columns: 100px 100px 100px;

    }

    /* 利用repeat函数改写 */

    .parent {

    display: grid;

    grid-template-rows: repeat(3, 100px);

    grid-template-columns: repeat(3, 100px);

    }

    另外,第一个参数除了可以使用数字显示设置网格数量外,还能使用auto-fit和auto-fill两个关键字自动分配空间。通常情况下,这两个关键字的使用效果都差不多,唯一的差别是空余空间的分配规则。搭配minmax函数可以看出区别,如下面这两个例子:

    .parent {

    display: grid;

    width: 500px;

    height: 100px;

    grid-gap: 10px;

    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));

    }

    .parent {

    display: grid;

    width: 500px;

    height: 100px;

    grid-gap: 10px;

    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));

    }

    2da7ef77e400

    auto-fit

    2da7ef77e400

    image.png

    在单行布局的时候,如果有空余空间auto-fit会将它们平均分配到所有子元素中,而auto-fill会自动创建空白的列。

    命名

    我们在创建网格布局框架的时候,通过"画线"来指定基本布局结构。默认情况下,网格布局会给每一条网格线进行命名,命名顺序同书写顺序一致:从左到右,由上至下按数字命名。假设我们指定的是3x3的网格布局结构,那么包含边框线,就会生成4+4=8条线。

    2da7ef77e400

    image.png

    除了采用默认命名方式,我们还能够自定义网格线的名称以便于后续在子元素定位中使用。

    .parent {

    display: grid;

    grid-template-rows: [row-a] 100px [row-b] 100px [row-c] 100px [row-d];

    }

    对齐

    对齐是布局过程中一个不可缺少的步骤,它的取值是通过已有的关键字来指定的。其中用于网格布局中对齐的关键字有start,center, end和stretch四个。

    我们先从默认值stretch看起,这个关键字是伸展的意思,所以在默认情况下网格中的子元素会尽可能地填充满网格区域,由于是默认值所以平常写代码的时候就不太会可以去用这个关键字进行声明。

    接着再来看一下常用的对齐取值策略,只需要记住一点就可以了:用属性justify-*,align-*来分别控制横轴和纵轴两个方向,属性值控制其对齐位置。 start,center和end三个属性值就分别对应了前中后三个位置。

    .parent {

    display: grid;

    }

    .child:first-child {

    justify-self: start;

    }

    .child:first-child {

    justify-self: center;

    }

    .child:first-child {

    justify-self: end;

    }

    *排列

    让我们重新回到隐式网格那部分,隐式的排列规则是通过指定grid-auto-flow这个属性来设置的。它的取值只有三个row,column和dense。上面属性部分已经介绍过row和column两个属性值,前者是按行优先来摆放子元素,后者是按列优先来摆放子元素。这里主要介绍一下dense这个属性值。通常情况下,排列子元素会按照顺序填充行或列,如果空间不足的时候,会换行或换列。而使用了dense属性后,会尽量使用空余空间,考虑下面这段代码:

    .parent {

    display: grid;

    grid-template-columns: repeat(3, 100px);

    }

    1
    2
    3
    4
    5

    默认情况下,显示效果是这样的:

    2da7ef77e400

    image.png

    当我们使用dense值进行排列的时候,就相当于开启“紧凑”模式,会尽可能利用空余空间。

    .parent {

    display: grid;

    grid-auto-flow: row dense;

    /* 由于默认为按行排列,可省略为dense */

    grid-auto-flow: dense;

    }

    所以,显示效果如下:

    2da7ef77e400

    image.png

    总结

    在这篇文章里,我通过拆解分类所有网格布局相关的知识点,希望能够为大家提供一个比较系统的运用网格布局的指导方法。在实际应用过程中,沿着"32构建之法”的这个套路来走,可以节约很多思考和决策时间。另外,由于这篇文章信息密度可能比较大,希望大家能够多多复习,并跟着例子实际操练几遍,这样在实际工作运用中才能如鱼得水。最后,送上一张思维导图,帮助大家能够一览本文所有的重点。

    2da7ef77e400

    image.png

    推荐阅读

    展开全文
  • 发现流式布局与网格布局的自定义很有意思,是学习自定义控件的一个很好的方式,所以就撸了个几百行代码的控件,既实用又具有学习价值。一、AutoFlowLayout应用场景流式布局,在很多标签类的场景中可以用的;而网格...

    近期工作需要用到流式布局,网上也有很多关于这方面的资料。发现流式布局与网格布局的自定义很有意思,是学习自定义控件的一个很好的方式,所以就撸了个几百行代码的控件,既实用又具有学习价值。

    一、AutoFlowLayout应用场景

    流式布局,在很多标签类的场景中可以用的;而网格布局在分类中以及自拍九宫格等场景很常见。如下所示:

    1FP6095231-2325-0.jpeg

    如此使用频繁而又实现简单的控件,怎能不自己撸一个呢?控件,还是定制的好啊。

    二、AutoFlowLayout实现效果

    先介绍下自己撸的这个控件的功能及效果。

    1.功能

    流式布局

    自动换行

    行数自定:单行/多行

    支持单选/多选

    支持行居中/靠左显示

    支持添加/删除子View

    支持子View点击/长按事件

    网格布局

    行数/列数自定

    支持单选/多选

    支持添加/删除子View

    支持子View点击/长按事件

    支持添加多样式分割线及横竖间隔

    2.效果

    下面以gif图的形式展现下实现的效果,样式简单了些,不过依然能展示出这个简单控件的多功能实用性。

    流式布局

    1FP6095231-3911-1.gif

    1FP6095231-5158-2.gif

    网格布局

    1FP6095231-33T-3.gif

    最后一个是带间隔以及分割线的,由于录屏原因,只在跳过去的一瞬间显示了粉红色的一条线。真实如下图所示,可以定义横竖间距的大小,以及分割线的颜色,宽度。

    1FP6095231-43N-4.jpeg

    三、AutoFlowLayout使用

    1.添加依赖

    ①.在项目的 build.gradle 文件中添加

    allprojects {

    repositories {

    ...

    maven { url 'https://jitpack.io' }

    }

    }

    ②.在 module 的 build.gradle 文件中添加依赖

    dependencies {

    compile 'com.github.LRH1993:AutoFlowLayout:1.0.2'

    }

    2.属性说明

    下表是自定义的属性说明,可在xml中声明,同时有对应的get/set方法,可在代码中动态添加。

    1FP6095231-3003-5.png

    3.使用示例

    布局

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    android:id="@+id/afl_cotent"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"/>

    代码设置数据

    mFlowLayout.setAdapter(new FlowAdapter(Arrays.asList(mData)) {

    @Override

    public View getView(int position) {

    View item = mLayoutInflater.inflate(R.layout.special_item, null);

    TextView tvAttrTag = (TextView) item.findViewById(R.id.tv_attr_tag);

    tvAttrTag.setText(mData[position]);

    return item;

    }

    });

    与ListView,GridView使用方式一样,实现FlowAdapter即可。

    四、AutoFlowLayout原理

    ViewGroup的测量、布局及绘制顺序如下所示:

    1FP6095231-5537-6.png

    详细的自定义View原理参考:图解View测量、布局及绘制原理

    下面具体介绍自定义实现网格布局的过程。

    1.重写generateLayoutParams()方法

    因为我们要在onMeasure以及onLayout的过程中,测量子View的margin,所以要重写该方法,并返回MarginLayoutParams。

    @Override

    public LayoutParams generateLayoutParams(AttributeSet attrs)

    {

    return new MarginLayoutParams(getContext(), attrs);

    }

    @Override

    protected LayoutParams generateLayoutParams(LayoutParams p) {

    return new MarginLayoutParams(p);

    }

    @Override

    protected LayoutParams generateDefaultLayoutParams() {

    return new MarginLayoutParams(super.generateDefaultLayoutParams());

    }

    2.onMeasure过程

    主要针对wrap_content情况下,要逐行逐列的测量每个子View的宽高,padding,margin以及横竖间距,来获得最终ViewGroup的宽高。

    private void setGridMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    // 获得它的父容器为它设置的测量模式和大小

    int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);

    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

    int modeWidth = MeasureSpec.getMode(widthMeasureSpec);

    int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

    //获取viewgroup的padding

    int paddingLeft = getPaddingLeft();

    int paddingRight = getPaddingRight();

    int paddingTop = getPaddingTop();

    int paddingBottom = getPaddingBottom();

    //最终的宽高值

    int heightResult;

    int widthResult;

    //未设置行数 推测行数

    if (mRowNumbers == 0) {

    mRowNumbers = getChildCount()/mColumnNumbers == 0 ?

    getChildCount()/mColumnNumbers : (getChildCount()/mColumnNumbers + 1);

    }

    int maxChildHeight = 0;

    int maxWidth = 0;

    int maxHeight = 0;

    //统计最大高度/最大宽度

    for (int i = 0; i < mRowNumbers; i++) {

    for (int j = 0; j < mColumnNumbers; j++) {

    final View child = getChildAt(i * mColumnNumbers + j);

    if (child != null) {

    if (child.getVisibility() != GONE) {

    measureChild(child,widthMeasureSpec,heightMeasureSpec);

    // 得到child的lp

    MarginLayoutParams lp = (MarginLayoutParams) child

    .getLayoutParams();

    maxWidth +=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;

    maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin);

    }

    }

    }

    maxHeight += maxChildHeight;

    maxChildHeight = 0;

    }

    int tempWidth = (int) (maxWidth+mHorizontalSpace*(mColumnNumbers-1)+paddingLeft+paddingRight);

    int tempHeight = (int) (maxHeight+mVerticalSpace*(mRowNumbers-1)+paddingBottom+paddingTop);

    if (tempWidth > sizeWidth) {

    widthResult = sizeWidth;

    } else {

    widthResult = tempWidth;

    }

    //宽高超过屏幕大小,则进行压缩存放

    if (tempHeight > sizeHeight) {

    heightResult = sizeHeight;

    } else {

    heightResult = tempHeight;

    }

    setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth

    : widthResult, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight

    : heightResult);

    }

    3.onLayout过程

    网格布局默认所有子View的宽高一致,先推算出每个子View的平均宽高,然后逐个推算每个子View的left,top,right,bottom位置,调用child.layout()进行子View布局。

    private void setGridLayout() {

    mCheckedViews.clear();

    mCurrentItemIndex = -1;

    int sizeWidth = getWidth();

    int sizeHeight = getHeight();

    //子View的平均宽高 默认所有View宽高一致

    View tempChild = getChildAt(0);

    MarginLayoutParams lp = (MarginLayoutParams) tempChild

    .getLayoutParams();

    int childAvWidth = (int) ((sizeWidth - getPaddingLeft() - getPaddingRight() - mHorizontalSpace * (mColumnNumbers-1))/mColumnNumbers)-lp.leftMargin-lp.rightMargin;

    int childAvHeight = (int) ((sizeHeight - getPaddingTop() - getPaddingBottom() - mVerticalSpace * (mRowNumbers-1))/mRowNumbers)-lp.topMargin-lp.bottomMargin;

    for (int i = 0; i < mRowNumbers; i++) {

    for (int j = 0; j < mColumnNumbers; j++) {

    final View child = getChildAt(i * mColumnNumbers + j);

    if (child != null) {

    mCurrentItemIndex++;

    if (child.getVisibility() != View.GONE) {

    setChildClickOperation(child, -1);

    int childLeft = (int) (getPaddingLeft() + j * (childAvWidth + mHorizontalSpace))+j * (lp.leftMargin + lp.rightMargin) + lp.leftMargin;

    int childTop = (int) (getPaddingTop() + i * (childAvHeight + mVerticalSpace)) + i * (lp.topMargin + lp.bottomMargin) + lp.topMargin;

    child.layout(childLeft, childTop, childLeft + childAvWidth, childAvHeight +childTop);

    }

    }

    }

    }

    }

    4.dispatchDraw过程

    绘制分割线得问过程,需要逐个对子View进行绘制分割线。所以重写dispatchDraw()方法。因为不需要对自己进行绘制,所以不需要重写onDraw()方法。

    需要额外注意下,绘制过程中,考虑横竖间距的大小,这种情况下默认不考虑margin。

    protected void dispatchDraw(Canvas canvas) {

    super.dispatchDraw(canvas);

    if (mIsGridMode && mIsCutLine) {

    Paint linePaint = new Paint();

    linePaint.setStyle(Paint.Style.STROKE);

    linePaint.setStrokeWidth(mCutLineWidth);

    linePaint.setColor(mCutLineColor);

    for (int i = 0; i < mRowNumbers; i++) {

    for (int j = 0; j < mColumnNumbers; j++) {

    View child = getChildAt(i * mColumnNumbers + j);

    //最后一列

    if (j == mColumnNumbers-1) {

    //不是最后一行 只画底部

    if (i != mRowNumbers-1){

    canvas.drawLine(child.getLeft()-mHorizontalSpace/2,child.getBottom()+mVerticalSpace/2,

    child.getRight(),child.getBottom()+mVerticalSpace/2,linePaint);

    }

    } else {

    //最后一行 只画右部

    if (i == mRowNumbers -1) {

    canvas.drawLine(child.getRight()+mHorizontalSpace/2, child.getTop()-mVerticalSpace/2,

    child.getRight()+mHorizontalSpace/2,child.getBottom(),linePaint);

    } else {

    //底部 右部 都画

    if (j == 0) {

    canvas.drawLine(child.getLeft(),child.getBottom()+mVerticalSpace/2,

    child.getRight()+mHorizontalSpace/2,child.getBottom()+mVerticalSpace/2,linePaint);

    } else {

    canvas.drawLine(child.getLeft()-mHorizontalSpace/2,child.getBottom()+mVerticalSpace/2,

    child.getRight()+mHorizontalSpace/2,child.getBottom()+mVerticalSpace/2,linePaint);

    }

    if (i == 0) {

    canvas.drawLine(child.getRight()+mHorizontalSpace/2, child.getTop(),

    child.getRight()+mHorizontalSpace/2,child.getBottom()+mVerticalSpace/2,linePaint);

    } else {

    canvas.drawLine(child.getRight()+mHorizontalSpace/2, child.getTop()-mVerticalSpace/2,

    child.getRight()+mHorizontalSpace/2,child.getBottom()+mVerticalSpace/2,linePaint);

    }

    }

    }

    }

    }

    }

    }

    绘制流式标签的过程类似,一样的简单。不过通过实现的过程,确实加深了对自定义ViewGroup的理解。

    展开全文
  • css布局 一、知识补充 1. 浮动的特性 只会影响后面的元素 文本不会被浮动元素覆盖(浮动的特性就是图文混合) 具备内联盒子特性:宽度由内容决定 具备块级盒子特性:支持所有样式 浮动放不下,会自动折行 template...

    css布局

    一、知识补充

    1. 浮动的特性

    • 只会影响后面的元素
    • 文本不会被浮动元素覆盖(浮动的特性就是图文混合)
    • 具备内联盒子特性:宽度由内容决定
    • 具备块级盒子特性:支持所有样式
    • 浮动放不下,会自动折行

    template:

    <div class="class">
            <div></div>
            <div></div>
            <div>图文混合</div>
        </div>
    

    css样式

    .class div:nth-of-type(1){
    	width: 50px;
        height: 50px;
        background-color: green;
    }
    .class div:nth-of-type(2){
        float: left;
        width: 100px;
        height: 100px;
        background-color: blue;
    }
    .class div:nth-of-type(3){
        width: 200px;
        height: 200px;
        background-color: red;
    }
    

    2. 相对定位及特性 (position: relative)

    • 相对定位的元素是在文档中的正常位置偏移给定的值
    • 不影响其他元素布局
    • 相对于自身进行偏移

    3. 绝对定位及特性 (positon: absolute)

    • 绝对定位的元素脱离了文档流,绝对定位元素不占据空间
    • 具备内联盒子特性:宽高由内容决定(float)
    • 具备块级盒子特性:支持所有样式(float)
    • 绝对定位元素相对于最近非static祖先元素定位。当这样的祖先元素不存在时,则相对于可视区定位

    4.固定定位及特性 (positon: fixed)

    • 固定定位与绝对定位相似,但是会固定在可视区中
    • 具备内联盒子特性:宽高由内容决定(absolute, float)
    • 具备块级盒子特性:支持所有样式 (absolute, float)
    • 固定定位元素不受祖先元素影响

    5. 黏性定位及特性 (position: sticky)

    涨知识:
    • 黏性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。
    position: sticky;
    top: 0
    

    6. 页面消失方法

    1. display:none

    元素不存在,不会占据页面位置;会对页面进行重绘,重排,重新绘制元素信息及重新安排页面元素位置

    2. visibility:hidden

    3. opacity: 0

    display:nonevisibility: hiddenopacity: 0
    页面中不存在存在存在
    重绘不一定
    重排不会不会
    自身绑定事件不触发不触发可触发
    transition不支持支持支持
    子元素复原不能不能
    被遮挡元素触发事件不影响不影响影响

    二、弹性布局 flex

    1. 主轴和交叉轴

    在这里插入图片描述

    2. flex容器与flex子项

    flex容器:

    • flex-direction
    • flex-wrap
    • flex-flow
    • justify-content
    • align-items
    • align-content

    flex子项

    • order
    • flex-grow
    • flex-shrink
    • flex-basis
    • flex
    • align-self

    flex-direction 改变主轴的方向

    • row 主轴方向五为横向 (默认横向)
    • column 主轴方向为竖向
    • row-reverse 主轴方向横向 从后面开始排列
    • column-reverse 主轴方向竖向 从最下面开始排列

    3. 换行与缩写

    flex-wrap: 换行属性

    • nowrap (默认) 不进行换行
    • wrap 换行
    • wrap-reverse 反向折行

    Tips:

    • 不设置换行的话,当子项的总宽大于父容器的宽度,子项会平均的分父容器的宽。
    • 当子项不设置宽度时,子项会根据内容获取宽度
    • 当子项不设置高度时,子项会获取父容器的高度
    • 当换行时,将父容器按所分的列数平分高度,子项会在平分的首行

    4. 主轴对齐详解

    justify-content 改变主轴的对齐方式

    • flex-start (默认) 对齐方式:靠右
    • flex-end 对齐方式:靠右
    • center 居中
    • space-around 平均分配所有空间,中间的空隙是两侧空隙的两倍
    • space-between 第一个子项和最后一个子项会贴到父容器的两侧,其余的平均分配空隙
    • space-evenly 子项之间的空隙都是等价的,不管最右边和最左边的空隙还是中间的空隙都是等价的

    5.交叉轴对齐详解

    align-content 交叉轴的整体的对齐方式

    • stretch (默认) 拉伸
    • flex-start
    • flex-end
    • center
    • space-around
    • space-between
    • space-evently

    Tips:

    • align-content 在不设置折行的情况下是不生效的 (flex-wrap)

    align-items 针对每一行的对齐方式

    • stretch (默认)
    • flex-start 在它自身的那一行的容器当中是顶对齐的
    • flex-end
    • center
    • baselind

    6. 元素上下左右居中

    内联的上下居中方式

    template:

    <div class="box">
        测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字
    </div>
    
    1. 弹性布局
    .box {
        width: 300px;
        height: 200px;
        background: skyblue;
        display: flex;
        align-items: center
    }
    

    或者

    .box {
        width: 300px;
        height: 200px;
        background: skyblue;
        display: flex;
        flex-wrap: wrap;
        align-content: center
    }
    
    2. 设置行高的方式
    涨知识:

    行高的方式上下居中只能适用于单行,多行文字的话不行

    .box {
        width: 300px;
        height: 200px;
        background: skyblue;
    	line-height: 200px;
    }
    
    3. display: table-cell
    .box {
        width: 300px;
        height: 200px;
        background: skyblue;
    	display: table-cell;
        vertical-align: middle;
    }
    

    块级元素的上下左右居中方式

    template

    <div class="box">
       <div>
           
        </div>
    </div>
    
    1. 弹性布局
    .box {
        width: 300px;
        height: 200px;
        background:  skyblue;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .box div {
        width: 100px;
        height: 100px;
        background: pink;
    }
    
    2. 绝对定位
    .box {    width: 300px;    height: 200px;    background:  skyblue;    position: relative;}.box div {    width: 100px;    height: 100px;    background: pink;    position: absolute;    top: 50%;    left: 50%;    transform: translate(-50%, -50%);}
    
    3. margin: auto
    .box {
        width: 300px;
        height: 200px;
        background:  skyblue;
        position: relative;
        display: flex;
    }
    .box div {
        width: 100px;
        height: 100px;
        background: pink;
        margin: auto;
    }
    

    .box {
        width: 300px;
        height: 200px;
        background:  skyblue;
        position: relative;
    }
    .box div {
        width: 100px;
        height: 100px;
        background: pink;    
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        margin: auto;
    }
    
    涨知识:

    弹性可以解决margin遗留下来的全部问题,像margin的叠加,传递,auto上下布局中等问题。

    不定项居中布局

    不定项:不确定元素的个数

    7. flex-grow 扩展比例

    flex子项的flex-grow : 默认值为 0 ,表示不占用剩余的空白间隙扩展自己的宽度

    template :

    <div class="main">
        <div>
            
        </div>
    </div>
    

    css:

    .main {
        width: 500px;
        height: 300px;
        background: skyblue;
        display: flex;
    }
    .main div {
        width: 100px;
        height: 100px;
        background: pink;
        flex-grow: 1;
    }
    

    flex-grow: 0; 默认值

    如果比例值为1,就占满剩余所有空间

    如果 0.5 的话 ,按照上面的布局 (500-100) * 0.5 + 100

    如果比例值大于等于1时, 都会占满剩余所有空间

    如果N个子项(N>1)都有扩展比例时,会把剩余空间以扩展比例等比分配;

    8. flex-shrink 收缩比例

    与扩展比例 flex-grow 相反;

    默认值为1, 自动收缩,跟容器大小相同

    9. flex-basis及flex缩写

    flex-basis 设置主轴方向的宽度(高度)

    主轴方向为从左到右时 ,flex-basis指的就是宽度

    主轴方向从上到下时 , flex-basis指的就是高度

    template:

    <div class="main">
        <div>
            
        </div>
    </div>
    
    .main {
        width: 500px;
        height: 300px;
        background: skyblue;
        display: flex;
    }
    .main div {
        width: 100px;
        height: 100px;
        background: pink;
        flex-basis: 200px;
    }
    /* 宽度为200px */
    

    或者

    .main {
        width: 500px;
        height: 300px;
        background: skyblue;
        display: flex;
        flex-direction: column;
    }
    .main div {
        width: 100px;
        height: 100px;
        background: pink;
        flex-basis: 200px;
    }
    /* 高度为200px */
    

    flex-basis的默认值为auto,会自适应内容定义宽高

    如果设置成 0 的话,将会没有宽高,会将内容单行或单列布局

    flex

    flex 是 flex-grow , flex-shrink及flex-basis的缩写

    10. order 及 align-self

    涨知识

    order : 默认值0,改变某一个flex子项的排序位置

    template:

    <div class="main">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
    </div>
    

    css

    .main {
        width: 500px;
        height: 300px;
        background: skyblue;
        display: flex;
    }
    .main div {
        width: 100px;
        height: 100px;
        background: pink;
    }
    .main div:nth-of-type(1) {
        order: 1;
    }
    .main div:nth-of-type(4) {
        order: -1;
    }
    

    上面的样式中,第一个div会跳到最后,第四个div会显示在第一

    align-self

    默认值为auto , 控制单独某一个flex子项的垂直对齐方式

    涨知识:

    auto 是跟父容器的align-items一样的值

    11. 等高布局

    弹性默认是拉伸的,所以默认就有等高布局的特性

    template:

    <div class="main">
        <div>
        	<p>测试内容</p>
            <p>测试内容</p>
        </div>
        <div>
        	<p>测试内容</p>
            <p>测试内容</p>
            <p>测试内容</p>
            <p>测试内容</p>
            <p>测试内容</p>
            <p>测试内容</p>
        </div>
    </div>
    

    css

    .main {
        width: 500px;
        background: skyblue;
        display: flex;
        justify-content: space-between;
    }
    .main div{
        width: 100px;
        background: pink;
    }
    

    三、网格布局grid

    grid容器

    在这里插入图片描述

    grid子项

    在这里插入图片描述

    定义网格及fr单位

    • grid-template-rows / grid-template-columns 基于网格行和列的维度,定义网格线的名称和网格轨道的尺寸大小
    display:grid;
    grid-template-columns: 50px 50px 50px;
    grid-template-rows: 50px 50px 50px;
    

    上面的是3x3的网格,每格的宽高都为50px , 宽高可以是百分比,px,fr单位。

    fr 单位:均分父容器的宽高

    1. fr 都为 1 的话 均分父容器的宽高
    2. 其中一个fr 比别的fr 等比大的话 该网格会占据等比大的宽高
    3. fr 之和小于1 的话 网格百分比占据容器 , 会剩余宽高。

    合并网格及网格命名

    • grid-template-areas 使用命名方式定义网格区域,需配合子项的
      grid-area 斜体样式属性进行使用

    父容器

    width:300px;
    height:300px
    display:grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr 1fr;
    grid-template-areas:
    "a1 a1 a2"
    "a1 a1 a2"
    "a3 a3 a3";
    

    子项

    div:nth-of-type(1){
        grid-area: a1;
    }
    ...
    

    tips: 少命名网格的话,未命名的网格会自动填充到未定义的空隙中,自动填充特性

    • grid-template grid-template-rows grid-template-columns grid-template-areas的缩写
    grid-template:
    "a1 a1 a2" 1fr
    "a1 a1 a2" 1fr
    "a3 a3 a3" 1fr
    /1fr 1fr 1fr;
    

    网格间隙及简写

    • grid-row-gap
    • grid-column-gap
    • grid- gap

    为了弹性设置,对应的别的样式的间隙问题,grid去掉的,

    • row-gap
    • column-gap
    • gap

    flex布局中也可以使用

    网格对齐方式及简写

    • justify-items
    • align-items
    • place-items
      • start 开始位置
      • center 中间位置
      • end 结束位置

    默认值 stretch 拉伸的,指定子项在网格中的对齐方式;子项在自己所属的单元格中的对齐方式

    当子项的大小 小于 单元格的大小是才会生效。

    • justify-content
    • align-content
    • place-content
      • start 开始位置
      • center 中间位置
      • end 结束位置
      • space-between 平分(两边没有空隙)
      • space-around 平分(两边有空隙)
      • space-evenly 完全均分

    默认值 stretch 拉伸的,指定所有单元格(网格)在父容器中的对齐方式

    当父容器大于网格时 才会生效,就是给网格的单元格指定大小后总大小小于父容器的大小

    基于线的元素位置

    • grid-column-start
    • grid-column-end
    • grid-row-start
    • grid-row-end

    表示grid子项所占据的区域的起始位置和终止位置,包括水平和垂直方向

    span 表示占据网格数据

    在定义网格行列的时候是可以定义线的命名的

    grid-template-columns:[col1] 1fr [col2] 1fr [col3] 1fr [col4];
    grid-template-rows:[row1] 1fr [row2] 1fr [row3] 1fr [row4];
    

    grid-area: 其实是 grid-row-start grid-column-start grid-row-end grid-column-end属性的缩写,额外支持grid-template-areas设置的网格名称

    也可以这样写,也支持span

    grid-column: 1/2;
    grid-row: 2/3;
    

    repeat() 和 minmax()

    当定义行列时大小都一样时,可以用repeat进行简写

    grid-template-columns: 100px 100px 100px;
    //可以写成
    grid-template-columns: repeat(3, 100px);
    grid-template-columns: repeat(auto-fill, 100px);
    

    auto-fill 自适应的现象;自动根据父容器的大小决定拆分多少的单元格,比如 grid-template-columns: repeat(autofill, 100px); 不管容器大小多大都是固定的4个网格,当一行放不下时会折到下一行,用autofill的话在一行可承载的情况下会覆盖整个一行。

    minmax 定义网格的最大值和最小值

    grid-template-columns: 100px 1fr 100px;
    grid-template-rows: 100px;
    //上面的第二个网格是自适应的宽度,根据拉伸网页变动,当网页的宽度小于等于200px就会消失,这是就可以使用minmiax解决
    
    grid-template-columns: 100px minmax(100px,1fr) 100px;
    grid-template-rows: 100px;
    //这样的话 不管怎么拉伸网格的宽度始终大于100px
    

    例子:需求,在行中的网格的数量根据分辨率的大小改变

    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    grid-template-rows: 100px;
    grid-auto-rows: 100px;
    gap: 20px;
    

    叠加布局

    原理:将两个内容通过网格的定义单元格的所属区域的方式,定在同一个单元格中

    <div class="main">
            <img src="../images/map.png" alt="">
            <span>地球</span>
        </div>
    /*   样式   */
    <style>
            .main{
                height: 6.475rem;
                width: 6.475rem;
                display: grid;
            
            }
            .main img{
                grid-area: 1/1/1/1;
            }
            .main span{
                /* grid-column: 1/2;
                grid-row: 1/2; */
                grid-area: 1/1/1/1;
                justify-self: center;
                align-self: center;
                font-size: 40px;
                color: white;
            }
        </style>
    

    四、display: table

    1. table标签

    <table border="1">
      <caption>我的标题</caption>
      <thead>
        <tr>
          <th>Month</th>
          <th>Savings</th>
        </tr>
      </thead>
    
      <tfoot>
        <tr>
          <td>Sum</td>
          <td>$180</td>
        </tr>
      </tfoot>
    
      <tbody>
        <tr>
          <td>January</td>
          <td>$100</td>
        </tr>
        <tr>
          <td>February</td>
          <td>$80</td>
        </tr>
      </tbody>
    </table>
    

    caption标题 thead 表头 ,tbody表身 tfoot 表脚 tr 行 th(用在表头中),td单元格

    colgroup和col

    • COLGROUP 元素指定表格中一列或一组列的默认属性。
    • COL 指定基于列的表格默认属性

    template:

    <table border="1" width="2500" height="500">
    		<colgroup>
    			<col span="2" style="background:pink;">
    			<col width="300">
    			<col style="color:blue;">
    			<col style="width:300px;">
    			<col align="left" >
    			<col align="center" style="text-decoration:underline;">
    			<col align="right" style="font-size:20px;font-family:Courier New">
    			<col align="justify" style="cursor:pointer">
    			<col valign="top">
    			<col valign="middle">
    			<col valign="bottom" style="padding:20px;">
    			<col valign="baseline" >
    		</colgroup>
    		<tr>
    			<td>span="2"</td>
    			<td>span="2"</td>
    			<td>width="300"</td>
    			<td>color:blue;</td>
    			<td>width:300px</td>
    			<td>align="left"</td>
    			<td>align="center"</td>
    			<td>align="right"</td>
    			<td>align="justify"</td>
    			<td>valign="top"</td>
    			<td>valign="middle"</td>
    			<td>valign="bottom"</td>
    			<td>valign="baseline"</td>
    		</tr>
    		<tr>
    			<td>span="2"</td>
    			<td>span="2"</td>
    			<td>width="300"</td>
    			<td>color:blue;</td>
    			<td>width:300px</td>
    			<td>align="left"</td>
    			<td>align="center"</td>
    			<td>align="right"</td>
    			<td>align="justify"</td>
    			<td>valign="top"</td>
    			<td>valign="middle"</td>
    			<td>valign="bottom"</td>
    			<td>valign="baseline"</td>
    		</tr>
    	</table>
    

    Tips:

    • 只有 width 和 background生效了,尽量不用吧

    2. display:table用法

    目前,在大多数开发环境中,已经基本不用table元素来做网页布局了,取而代之的是div+css,那么为什么不用table系表格元素呢?

    1、用DIV+CSS编写出来的文件k数比用table写出来的要小,不信你在页面中放1000个table和1000个div比比看哪个文件大

    2、table必须在页面完全加载后才显示,没有加载完毕前,table为一片空白,也就是说,需要页面完毕才显示,而div是逐行显示,不需要页面完全加载完毕,就可以一边加载一边显示

    3、非表格内容用table来装,不符合标签语义化要求,不利于SEO

    4、table的嵌套性太多,用DIV代码会比较简洁

    display:table系列与之相对应的table系的元素,如下:

    display: tabletable标签讲义
    tabletable此元素会作为会计表格来显示,表格前后带有换行符
    inline-tabletable此元素作为内联表格来显示,表格卡后没有换行符
    table-row-grouptbody此元素会作为一个或多个行的分组来显示
    tabel-head-groupthead此元素会作为一个或多个行的分组来显示
    table-footer-grouptfoot此元素会作为一个或多个行的分组来显示
    table-rowtr此元素会作为一个表格行来显示
    table-column-groupcolgroup此元素会作为一个或多个列的分组来显示
    table-columncol此元素会作为一个单元格列显示。
    table-cellth , td此元素会作为一个表格单元格显示。
    table-captioncaption此元素会作为一个表格标题显示。

    模拟表格: template

    <div class="table">
        <div class="row">
            <div class="cell">张三</div>
            <div class="cell">李四</div>
            <div class="cell">王五</div>
        </div>
        <div class="row">
            <div class="cell">张三</div>
            <div class="cell">李四</div>
            <div class="cell">王五</div>
        </div>
    </div>
    

    css

    .table {
            display: table;
            border: 1px solid #cccccc;
            margin: 5px;
            /*display: table时padding会失效*/
        }
        .row {
            display: table-row;
            border: 1px solid #cccccc;
            /*display: table-row时margin、padding同时失效*/
        }
        .cell {
            display: table-cell;
            border: 1px solid #cccccc;
            padding: 5px;
            /*display: table-cell时margin会失效*/
        }
    

    Tips :

    • display: table-cell 指让标签元素以表格单元格的形式呈现,使元素类似于 td 标签
    • display: table-cell 属性也会被 float,position : absolute 等属性**破坏效果**,应避免同时使用。

    table 解决问题:

    1. 多行文字居中

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>table</title>
        <style>
            .parent{
                display: table;
                width: 400px;
                height: 400px;
                text-align: center;
                border:1px solid red;
                margin:0 auto;
                background: blue;   /*背景颜色无效*/
            }
            .child{
                display: table-cell;    /*子元素成为表格单元格(类似 <td> 和 <th>)*/
                height: 200px;
                background: yellow;
                vertical-align: middle; /*表格容器可以设置垂直对齐属性*/
                white-space: pre;
            }
        </style>
    </head>
    <body>
        <div class="parent">
            <div class="child">
    			display: table-row-group;
    			display: table-header-group;
    			display: table-footer-group;
    			display: table-row;
    			display: table-cell;
    			display: table-column-group;
    			display: table-column;
    			display: table-caption;
    			display: ruby-base;
    			display: ruby-text;
    			display: ruby-base-container;
    			display: ruby-text-container;
            </div>
        </div>
    </body>
    </html>
    

    Tips :

    设置了display:table-cell的元素:

    • 对宽度高度敏感
    • 对margin值无反应
    • 响应padding属性
    • 内容溢出时会自动撑开父元素

    2. 制作自适应搜索框

    涨知识:white-space 属性详解

    我们熟知的是:

    • 在开发中,无论我们敲多少空格和回车,显示在页面上的都会合并成一个
    • 我们的文字在超过一行的情况下,就会自动换行

    属性介绍:
    在这里插入图片描述

    这个古诗是怎么打出来的呢?

    床(空格)前(空格)(空格)(空格)(空格)明月光,疑是地上霜

    (回车)

    举头望明月,低头(Tab)思故乡

    下面一个表格来说明一下出现这种情况的原因:

    属性效果兼容
    normal 默认所有空格、回车、制表符都合并成一个空格,文本自动换行IE7\IE6 +
    nowrap所有空格、回车、制表符都合并成一个空格,文本不换行IE7\IE6 +
    pre所有东西原样输出,文本不换行IE7\IE6 +
    pre-wrap所有东西原样输出,文本换行IE8 +
    pre-line所有空格,制表符合并成一个空格,回车不变,文本换行IE8 +
    inherit继承父元素IE不支持,不推荐使用

    属性使用:

    1. 列表溢出换行处理

    同样是320px的手机,iphone4可以在一行显示,但是安卓端就会有错位现象,这个开始让我很头疼,这样的话使用媒体查询也无法处理,所以在这一行的父元素中设置,所有的元素强制一行显示。

    ul {
        white-space: nowrap; /*强制内容在一行显示*/
        overflow: hidden;  /*超出部分隐藏*/
    }
    
    1. 文字溢出省略处理

    文字超出去怎么办?一般都自动换行了,想要文字溢出的部分自动用省略号表示,那么离不开三个属性:

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;  /*溢出部分使用省略号*/
    
    1. 文字展示

    如果是显示诗歌,或者文案之类的,很多情况需要输入什么样子,出来什么样子。

    这个时候用pre属性是最合适的(毕竟兼容性最好么):

    white-space: pre;
    

    五、媒体查询

    1. 媒体查询概念

    媒体查询:

    • 媒体类型
      • all :适用于所有设备
      • print :适用于在打印预览模式
      • screen :只要用于屏幕
      • speech : 主要用于语音合成器
    • 媒体特性 :描述了user agent、输出设备,或浏览环境的具体特征
      • width: viewport的宽度
      • height: viewport的高度
      • aspect-ratio: viewport的宽高比
      • orientation:viewport的旋转方向 ( landscope 水平方向 portrait 垂直方向 )
    • 逻辑操作符
      • and
      • not
      • only
      • 逗号 ,(类似或)
    • link标签方式 (通过media属性设置媒体查询类型和媒体特性)

    写法如下:

    template

    <div class="box">
        aaaaaaaaaaaa
    </div>
    

    css

    @media print {
        .box {
            font-size: 60px
        }
    }
    /* 上面的样式只会在打印模式下会生效 */
    
    @media screen and (min-width: 700px) and ( max-width: 1200px){
        .box {
            width: 200px;
            height: 200px;
            background: pink;
        }
    }
    /* 上面的样式只会在屏幕下宽度大于700px并且小于1200px时会生效 */
    

    2. 响应断点(阈值)设定

    • Extra Small < 576px
    • Small >= 576px , sm
    • medium >= 768px , md
    • large >= 992px, lg
    • x-large >= 1200px , xl
    • xx-large >= 1400px, xxl
    展开全文
  • Java 网格布局

    2021-03-09 05:45:22
    /** 网络布局* */package com.swing;import java.awt.GridLayout;import javax.swing.JButton;import javax.swing.JFrame;class gridlayout extends JFrame{int size=6;private JButton jbtn[]=new JButton[size];...
  • Vue网格布局 Vue.js的网格布局系统,如用于Vue.js的Gridster。深受React网格布局的启发
  • Android Studio网格布局刷新我有一个GridLayout与24行和5列,并且所有单元格包含CardView。例如,这是我layout.xml(小版):android:id="@+id/ScrollView01"android:layout_width="fill_parent"android:layout_height...
  • 本文介绍了CSS网格布局的示例代码,分享给大家,具体如下:浏览器兼容性可以看出CSS网格布局从Safari 10.1, Firefox 52, Chrome 60,Edge 15开始受到支持。网格布局页面基本元素:OneTwoThreeFourFive样式:.wrapper...
  • JAVA 网格布局管理器

    2021-02-27 18:56:56
    //网格布局管理器import java.awt.*;import javax.swing.*;public class Jiemian3 extendsJFrame{//定义组件JButton[] an = {null,null,null,null,null,null,null,null};public static voidmain(String[] args){//...
  • ## 简言CSS网格布局(Grid)是一套二维的页面布局系统,它的出现将完全颠覆页面布局的传统方式。传统的CSS页面布局 一直不够理想。包括table布局、浮动、定位及内联块等方式,从本质上都是Hack的方式,并且遗漏了一些...
  • CSS Grid 网格布局教程

    千次阅读 2020-12-29 00:25:34
    一、概述网格布局(Grid)是最强大的 CSS 布局方案。它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。上图这样的布局,就是 ...
  • 一、Grid网格布局概述Grid网格布局它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。Grid 布局则是将容器划分成”行”和”列”,产生单元格,然后指定”项目所在”的单元格,可以看作是二维...
  • 【Qt】Qt之网格布局

    2021-03-30 22:15:10
    Qt设计师使用网格布局05. 使用代码实现网格布局06. 附录 01. 概述 QGridLayout:格栅布局,也被称作网格布局(多行多列)。 栅格布局将位于其中的窗口部件放入一个网状的栅格之中。QGridLayout需要将提供给它的空间...
  • RecyclerView网格布局

    2021-04-16 10:31:50
    我们可以试下recyclerview的网格布局,进行动态适配各行的item 可行,扩展性够 二、解决问题 方案:使用recyclerview的网格布局 定义itemType,针对不同的类型填充不同的布局 这里我们用不同itemType,之后可以在...
  • 弹性布局和网格布局

    2021-02-27 16:34:50
    弹性布局和网格布局 1、Flex 弹性布局 1-1、Flex容器属性(常用) flex-direction justify-content align-items align-content flex-wrap flex-shrink 我们用上面的容器属性可以来实现一些常见的效果 1-1、水平排列...
  • 发现流式布局与网格布局的自定义很有意思,是学习自定义控件的一个很好的方式,所以就撸了个几百行代码的控件,既实用又具有学习价值。一、AutoFlowLayout应用场景流式布局,在很多标签类的场景中可以用的;而网格...
  • java:布局方法(网格布局

    千次阅读 2021-04-22 00:42:38
    网格布局简单说明关键代码流程图例子说明默认情况源码运行效果其他情况 简单说明 网格布局,用常说的几行几列来理解便可,按几行几列分成多个大小统一的组件(这里选“按钮”)。一个窗体,在里边布置“按钮”用网格...
  • 您可以动态生成GridView.GridView将根据您的需要包含ImageView和TextView.您必须使用自定义适配器.在它的getView方法中,填充ImageView和TextView.例:GridView item.xml:android:layout_width="fill_parent"android...
  • 2 QVBoxLayout 垂直布局 QVBoxLayout 其中的 “V” 就是单词 vertical 的简写,垂直的意思,就是该布局中的组件都是垂直方向排列的。 简单示例: int main(int argc, char *argv[]) { QApplication a(argc, argv); ...
  • 应用开发的时候,有时我们需要将一些...这里就可以使用GridView,android中的网格布局来实现了。GridView控件用于把一系列的控件组织成二维网格的形式显示出来,应用较多的也就是图片的组合显示了。关于GridView的...
  • Web 前端 - CSS - Grid 网格布局及通用PC端布局实战[toc]一、概述序号属性描述1解释网格布局是一个二维的基于网格的布局系统2特点由水平(行)和垂直(列)线集合创建的一个模式,我们可以根据这个模式排列我们的设计...
  • swiper网格布局

    2021-07-23 15:22:15
    需要引入:swiper相关插件,官网上有详细步骤 官网地址:https://www.swiper.com.cn/api/index.html 实现效果: 左滑: ... }, 注: slidesPerColumnFill: column:列布局 row:行布局
  • 安卓案例:网格布局实现计算器界面一、网格布局(GridLayout)GridLayout布局使用虚细线将布局划分为行、列和单元格,也支持一个控件在行、列上都有交错排列。(一)继承关系图 (二)常用属性1、针对布局的属性(1)...
  • RecyclerView在网格布局或者瀑布流布局下,如果要设置间距,可以使用ItemDecoration。下面的代码是设置显示两列数据RecyclerView的情况。cat.png@Overridepublic void getItemOffsets(@NonNull Rect outRect, @...
  • CSS进阶之关于网格布局(Grid) 你了解哪些

    千次阅读 多人点赞 2021-05-15 17:19:33
    CSS 进阶:网格布局(Grid)及其基本属性 网格布局(Grid)是最强大的 CSS 布局方案。起初我也认为 flex 布局就可以完成绝大部分布局场景,但谁不希望用更直观、更简洁的方式来布局自己的网页呢,于是 Grid 就是...
  • Android网格布局

    2021-01-27 11:53:35
    1、网格布局简述 网格布局是Android4.0新增的布局,它实现了控件的交错显示,能够避免因布局嵌套对设备性能的影响,更利于自由布局的开发。 网格布局用一组无限细的直线将绘图区域分成行,列和单元,并指定控件的...
  • flex布局和网格布局

    2021-01-25 14:56:58
    伸缩布局=弹性布局=伸缩盒布局=弹性盒布局=flex布局 采用flex布局的元素,成为flex容器,简称“容器”。他的所有子元素自动成为欸容器成员,称为flex项目,简称“项目”。(通过给父盒子添加flex属性,来控制盒子的...
  • 使用css实现网格布局

    2021-06-14 03:10:16
    css实现的网格布局,自适应宽度变化,间隙完全相等,每个小格子的宽和高也相等。实现这样的页面效果所涉及的知识点:块元素在行内布局时,注意两个div之间的空格。css实现div宽和高相等的关键是使用padding-bottom这...
  • 1. 概述GridLayout,网格布局管理器。它以矩形网格形式对容器的组件进行布置,把容器按行列分成大小相等的矩形网格,一个网格中放置一个组件,组件宽高自动撑满网格。以行数和总数优先: 通过构造方法或 setRows 和 ...
  • 计算器的布局比较整齐,利用网格布局排列计算器按钮是一种比较理想的方式,实现的java程序如下:import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.*;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 64,154
精华内容 25,661
关键字:

网格布局