赞
踩
本着不拖更的原则,今天上新了,今天实现了类微信app的发现页和我的页面。先看效果。
效果是不是看着还不错。其实这两个页面功能实现还是比较简单的,接下来还是老规矩,先进行页面的拆分和代码实现,然后进行相关我认为比较重要的知识点的说明。
页面看似复杂,但是其实经过拆分之后,发现就是由两部分组合。
TitleBar
Cell
复杂的内容区域部分,无非就是由一个个小的内容Cell
复用组装起来的嘛,上篇文章也写过了。一个Foreach
而已嘛。
实现TitleBar
,在实现TitleBar的时候,为了练习控件使用,专门引入了RelativeContainer
组件的使用。在知识解惑部分会做详细说明。
@Preview @Component export default struct SearchTitleBar { @Prop title: string; build() { RelativeContainer() { Text(this.title) .fontColor(0x333333) .fontSize(18) .fontWeight(FontWeight.Medium) .alignRules({ left: { anchor: "__container__", align: HorizontalAlign.Start }, right: { anchor: "__container__", align: HorizontalAlign.End }, top: { anchor: "__container__", align: VerticalAlign.Top }, bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, }) .textAlign(TextAlign.Center) .id("id_title") Column() { Image($r('app.media.toolbar_search')) .width(22) .height(22) } .height('100%') .margin({ right: 12 }) .justifyContent(FlexAlign.Center) .alignRules({ right: { anchor: "id_more", align: HorizontalAlign.Start } }) .id("id_search") Column() { Image($r('app.media.toolbar_more')) .width(22) .height(22) .margin({ right: 16 }) } .height('100%') .justifyContent(FlexAlign.Center) .alignRules({ right: { anchor: "__container__", align: HorizontalAlign.End }, }) .id("id_more") } .width('100%') .height(50) .backgroundColor(0xEDEDED) } }
对于Cell
的实现代码,在下面的讲解Column
部分,也会列出来,如果这会不想看,在看完Flex
和Column
之后,看起来会更加清晰。
import { DiscoverCellEntity } from '../../common/bean/DiscoverCellEntity' import commonDataViewModel from '../../viewmodel/CommonDataViewModel'; @Preview @Component export default struct CellItemView { private discoverCellEntity: DiscoverCellEntity; build() { Row({ space: 5 }) { Row() { Image(this.discoverCellEntity.icon) .width(22) .height(22) .margin({ left: 16 }) Text(this.discoverCellEntity.title) .fontWeight(FontWeight.Regular) .fontSize(16) .fontColor(0x333333) .margin({ left: 12 }) Row() .width(5) .height(5) .margin({ left: 4 }) .borderRadius(2.5) .backgroundColor(0xF14400) .visibility(this.discoverCellEntity.hasNew ? Visibility.Visible : Visibility.Hidden) } Row() { Image(commonDataViewModel.getUserAvatar()) .width(35) .height(35) .objectFit(ImageFit.Cover) .borderRadius(4) .visibility(this.discoverCellEntity.hasAvatar ? Visibility.Visible : Visibility.Hidden) Image($r('app.media.ic_right_arrow')) .width(22) .height(22) .margin({ right: 12 }) } .justifyContent(FlexAlign.Center) .height('100%') .onClick(() => { }) } .justifyContent(FlexAlign.SpaceBetween) .width('100%') .height(60) .backgroundColor(0xFFFFFF) } }
由于在上篇文章中,牵扯到的一些布局知识点,没有讲解到,我一个同事看了我的文章之后,建议,对于一些基础的知识,也带一带简单做个说明,所以本次会把上次和本地用到的布局相关知识进行一个简单说明,如果对相关的知识比较熟悉,这部分内容可以酌情阅读。
类似于Android中的LinearLayout,只是类似。对于Column和Row本身如果对于前端Flex布局比较熟悉的话,基本上看一眼就知道啥意思了。所以我在讲解Column和Row之前,先讲解一下Flex布局。
如果想做详细理解同学,可以直接先看一下我引入的这篇文章,你会了解到更多关于flex的知识。
flex入门 来源于知乎。
Flex是一个支持横向和纵向填充内容的布局容器。在布局填充到flex中之后,我们可以通过对横向和纵向进行控制,用来实现容器内内容的横竖向排列方式,可以帮我们实现等分、居左、居右等很多种对其方式。
我们用来在纵向和横向上控制的内容,在flex中,被描述成了相应的主轴和副轴(交叉轴)。比如一个横向的布局排列,主轴就是对应的横向,而副轴(交叉轴)就是竖向了。
//默认起点对齐
justify-content: flex-start;
//终点对齐
justify-content: flex-end;
//居中对齐
justify-content: center;
//两端对齐
justify-content: space-between;
//周围分布相同空间
justify-content: space-around;
//均匀空间
justify-content: space-evenly;
自己懒得画这些效果图,所以直接从别人博客拿了图。大家理解着看,理解之后,会发现很简单。
declare class ColumnAttribute extends CommonMethod<ColumnAttribute> { /** * Sets the alignment format of the subassembly in the horizontal direction. * @since 7 */ /** * Sets the alignment format of the subassembly in the horizontal direction. * @form * @since 9 */ alignItems(value: HorizontalAlign): ColumnAttribute; /** * Sets the alignment format of the subassembly in the vertical direction. * @since 8 */ /** * Sets the alignment format of the subassembly in the vertical direction. * @form * @since 9 */ justifyContent(value: FlexAlign): ColumnAttribute;
在学会了Flex之后,在看这个代码是不是豁然开朗?这不就是变种的简化版本Flex吗。我们只管填充内容,接下来的变化,直接交给alignItems
和justifyContent
属性帮我们完成就行了。
为了加深理解,看一个我实现过程中的代码片段。
Row({ space: 5 }) { Row() { Image(this.discoverCellEntity.icon) .width(22) .height(22) .margin({ left: 16 }) Text(this.discoverCellEntity.title) .fontWeight(FontWeight.Regular) .fontSize(16) .fontColor(0x333333) .margin({ left: 12 }) Row() .width(5) .height(5) .margin({ left: 4 }) .borderRadius(2.5) .backgroundColor(0xF14400) .visibility(this.discoverCellEntity.hasNew ? Visibility.Visible : Visibility.Hidden) } Row() { Image(commonDataViewModel.getUserAvatar()) .width(35) .height(35) .objectFit(ImageFit.Cover) .borderRadius(4) .visibility(this.discoverCellEntity.hasAvatar ? Visibility.Visible : Visibility.Hidden) Image($r('app.media.ic_right_arrow')) .width(22) .height(22) .margin({ right: 12 }) } .justifyContent(FlexAlign.Center) .height('100%') .onClick(() => { }) } .justifyContent(FlexAlign.SpaceBetween) .width('100%') .height(60) .backgroundColor(0xFFFFFF)
上面的代码,帮我们实现了一个cell效果。是不是很简单,瞬间理解了,有没有。
这个布局被命名为Relative
,但是我更觉得应该命名为ConstraintLayout
,不能说完全相似,只能说是一模一样。
Column
和Row
布局在绘制过程中,简单界面还好,但是如果负责的界面的话,会出现无数的Column
和Row
之间的魔鬼嵌套。导致代码层级无限深,阅读代码造成困难,修改更是地狱级别。这个时候RelativeContainer
的优势就出来了,使用它可以将布局进行层级平铺,通过布局间的依赖关系控制,实现整体的界面布局。
这是鸿蒙开发者官网上的文档地址: RelativeContainer
上面的话,不知道你看懂了没有。下面我使用下面的图,进行一个说明。
如果我们要实现上面的效果,可以先写五个Row().width(100).height(100)
元素,设置不同颜色之后,放置在RelativeContainer
容器中。
上下左右四个角的元素,我们分析发现,其实我们要把他们定位到正确位置,只需要依赖父容器的上下左右位置即可。比如左上的大红色
=>上(top)是和父容器上(top)对其的,左边是和父容器的左边对其的。就很容器写出如下的代码
.alignRules({
top: {anchor: "__container__", align: VerticalAlign.Top},
left: {anchor: "__container__", align: HorizontalAlign.Start}
})
当运行代码,你会发现确实和和想象中一样,左上的大红色固定到了指定位置了。其余的左下、右上、右下也是类似的。
剩下中间的这个元素,我们分析,发现和父容器都没有任何关系。但是和四周的四个元素是有依赖关系的。中间元素左上=>左上元素右下
、中间元素右上=>右上元素左下
以此类推。不难写出代码。
.alignRules({
top: {anchor: "row1", align: VerticalAlign.Bottom},
left: {anchor: "row1", align: HorizontalAlign.End},
right: {anchor: "row2", align: HorizontalAlign.Start}
})
夜已深,今天就到这里了,谢谢你的阅读。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。