款式处理

1. 款式-语法(链式&枚举)

ArkTS以声明办法组合和扩展组件来描述运用程序的UI 一起还供给了基本的特点、事情和子组件装备办法,协助开发者完成运用交互逻辑。

1.款式特点

  • 特点办法以 . 链式调用的办法装备体系组件的款式和其他特点,主张每个特点办法单独写一行。
@Entry
@Component
struct Index {
  build() {
    Text('演示')
      .backgroundColor('red')
      .fontSize(50)
      .width('100%')
      .height(100)
  }
}

2.枚举值

  • 关于体系组件,ArkUI还为其特点预界说了一些枚举类型。
@Entry
@Component
struct Index {
  build() {
    Text('演示')
     .fontSize(50)
      .width('100%')
      .height(100)
      .backgroundColor(Color.Blue)
      .textAlign(TextAlign.Center)
      .fontColor(Color.White)
  }
}
  • 款式相关特点通过链式函数的办法进行设置
  • 假如类型是枚举的,通过枚举传入对应的值
2. 款式-单位 vp 和适配
  1. vp 是什么?virtual pixel
  • 屏幕密度相关像素,依据屏幕像素密度转换为屏幕物理像素,当数值不带单位时,默许单位 vp;在实践宽度为1440物理像素的屏幕上,1vp 约等于 3px(物理像素)

    鸿蒙运用开发-组件款式

  • 上图的意思是,运用这个单位在不同屏幕物理分辨率的实践尺寸一致(A设备1英寸,B设备1英寸)。

2.之前 vwremrpx 相关于屏幕宽度的单位,能够完成等比例适配,vp 能够吗?

import promptAction from '@ohos.promptAction'
@Entry
@Component
struct Index {
  build() {
    Text('演示')
      .width('100%')
      .backgroundColor('red')
      .onAreaChange((oldArea, newArea) => {
        promptAction.showToast({
          // 1. onAreaChange改动尺寸后会触发
          // 2. newArea为现在元素尺寸
          message: newArea.width.toString()
        })
      })
  }
}

我们发现:不同的设备屏幕的宽度 vp 是不一致的,那怎么适配呢?

  1. 依据官方的文档,结合自己的了解,选用:弹性布局,网格体系,栅格体系进行布局适配。

弹性 layoutWeight(flex: number)占剩下空间多少份,能够了解成CSS的 flex: 1

@Entry
@Component
struct Index {
  build() {
    Row(){
      Text('left')
        .layoutWeight(1)
        .backgroundColor('red')
      Text('right')
        .layoutWeight(2)
        .backgroundColor('green')
    }
    .width('100%')
  }
}

等比例,设置元素宽高比 aspectRatio(ratio: number)

@Entry
@Component
struct Index {
  build() {
    Text('left')
      .width('50%')
        // 宽高比例
      .aspectRatio(1)
      .backgroundColor('red')
  }
}
  • vp鸿蒙默许单位,和屏幕像素有关,终究体现视觉大小在任何设备一致
  • 鸿蒙一般以弹性 layoutWeight、网格、栅格进行布局适配,如要等比例缩放能够设置高宽比 aspectRatio
    事例→完成知乎谈论回复-谈论区域

鸿蒙运用开发-组件款式

设计稿一般是1080px:(这儿没有设计稿,供给了一些尺寸)

  • Nav
    • 左边回来按钮24vp高宽背景色彩#f5f5f5,图标12vp尺寸色彩#848484
    • 标题18vp
  • Comment
    • 头像尺寸32vp高宽,右侧距离10vp
    • 标题15vp,色彩默许
    • 内容16vp,色彩#565656
    • 底部12vp,色彩#c3c4c5
@Entry
@Component
struct Index {
  build() {
    Column(){
      // 导航
      Row(){
        Row(){
          Image($r('app.media.ic_public_arrow_left'))
            .width(16)
            .aspectRatio(1)
            // svg 图标能够运用填充色彩
            // .fillColor('red')
        }
        .width(24)
        .aspectRatio(1)
        .backgroundColor('#f5f5f5')
        .borderRadius(12)
        .justifyContent(FlexAlign.Center)
        .margin({ left: 16 })
        Text('谈论回复')
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .padding({ right: 40 })
      }
      .height(40)
      .border({ width: { bottom: 0.5 }, color: '#e4e4e4' })
      // 谈论
      Row(){
        Image($r('app.media.avatar'))
          .width(32)
          .aspectRatio(1)
          .borderRadius(16)
        Column({ space: 5 }){
          Text('周杰伦')
            .width('100%')
            .fontWeight(FontWeight.Bold)
            .fontSize(15)
          Text('大理石能雕刻出肌肉和皮肤的质感,那个时代的工匠好牛啊')
            .width('100%')
          Row(){
            Text('10-21  IP属地北京')
              .fontSize(12)
              .fontColor('#c3c4c5')
            Row({ space: 4 }){
              Image($r('app.media.ic_public_heart'))
                .width(14)
                .aspectRatio(1)
                .fillColor('#c3c4c5')
              Text('100')
                .fontSize(12)
                .fontColor('#c3c4c5')
            }
          }
          .width('100%')
          .justifyContent(FlexAlign.SpaceBetween)
        }
        .layoutWeight(1)
        .padding({ left: 10 })
      }
      .padding(15)
      .alignItems(VerticalAlign.Top)
    }
  }
}

款式-@Styles 复用

在开发进程中会出现很多代码在进行重复款式设置,@Styles 能够帮我们进行款式复用

  • 当时 @Styles 仅支撑 通用特点 和 通用事情。
  • 支撑 大局 界说和 组件内 界说,一起存在组件内掩盖大局生效。
// 大局
@Styles 
function functionName() { ... }
@Entry
@Component
sturt Index{
  // 组件内
  @Styles 
  functionName() { ... }
  build() {
    Text('Text')
      .functionName()
  }
}

事例:文字和按钮相同背景,点击+1

鸿蒙运用开发-组件款式

  • 大局
@Styles function sameStyle() {
  .backgroundColor(Color.Green)
  .onClick(() => {
    this.count++
  })
}
@Entry
@Component
struct Index {
  @State
  count: number = 10
  build() {
    Column() {
      Text(this.count.toString())
        .width(100)
        .height(50)
        .margin({ bottom: 10 })
        .textAlign(TextAlign.Center)
        .sameStyle()
      Button('+1')
        .sameStyle()
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}
  • 组件内
@Entry
@Component
struct Index {
  @State
  count: number = 10
  // 不需要 `function` 关键字,掩盖大局
  @Styles
  sameStyle (){
    .backgroundColor(Color.Pink)
    .onClick(() => {
      this.count += 10
    })
  }
  build() {
    Column() {
      Text(this.count.toString())
        .width(100)
        .height(50)
        .margin({ bottom: 10 })
        .textAlign(TextAlign.Center)
        .sameStyle()
      Button('+1')
        .sameStyle()
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

练习事例-登录表单-款式优化

鸿蒙运用开发-组件款式

import promptAction from '@ohos.promptAction'
@Entry
@Component
struct Index {
  @State
  mobile: string = ''
  @State
  code: string = ''
  @Styles
  inputStyle () {
    .border({ width: 1, color: Color.Gray })
    .layoutWeight(1)
    .margin({ left: 10, bottom: 10, top: 10 })
    .backgroundColor(Color.White)
  }
  build() {
    Column(){
      Row(){
        Text('手机号')
        TextInput({ text: this.mobile })
          .inputStyle()
          .onChange((value)=>this.mobile = value)
      }
      Row(){
        Text('验证码')
        TextInput({ text: this.code })
          .inputStyle()
          .onChange((value)=>this.code = value)
      }
      Row({ space: 15 }){
        Button('重置')
          .backgroundColor('#ccc')
          .onClick(()=>{
            this.mobile = ''
            this.code = ''
          })
        Button('登录')
          .onClick(()=>{
            if (this.mobile && this.code) {
              promptAction.showToast({ message: `${this.mobile} 登录成功` })
            } else {
              promptAction.showToast({ message: `请输入手机号或验证码` })
            }
          })
      }
    }
    .padding({ left: 15, right: 15 })
  }
}

款式-@Extends 复用

@Extend 用于扩展原生组件款式,通过传参供给更灵活的款式复用

  • 运用 @Extend 装饰器润饰的函数只能是 大局
  • 函数能够进行 传参,假如参数是状况变量,状况更新后会改写UI
  • 且参数能够是一个函数,完成复用事情且可处理不同逻辑
// 大局  原生组件                     参数
//  ↓     ↓                          ↓ 
@Extend(Text) function functionName(w: number) { 
  .width(w)
}

需求:把 Text 改成按钮款式,且绑定 click 事情履行不同逻辑

鸿蒙运用开发-组件款式

import promptAction from '@ohos.promptAction'
@Extend(Text) function myClick(color: string, cb: () => void) {
  .backgroundColor(color)
  .width(100)
  .height(50)
  .textAlign(TextAlign.Center)
  .borderRadius(25)
  .onClick(() => cb())
}
@Entry
@Component
struct Other {
  @State
  color: string = '#ccc'
  build() {
    Column({ space: 20 }) {
      Text('Text1')
        .myClick(this.color, () => {
          this.color = '#069'
        })
      Text('Text2')
        .myClick('green', () => {
          promptAction.showToast({ message: '做其他事~' })
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

款式-多态

stateStyles 是特点办法,能够依据UI内部状况来设置款式,类似于 css 伪类,但语法不同。ArkUI 供给以下四种状况:

  • focused:获焦态。

  • normal:正常态。

  • pressed:按压态。

  • disabled:不可用态。

import promptAction from '@ohos.promptAction'
// 胶囊按钮
@Extend(Text)
function capsule(){
  .height(40)
  .borderRadius(20)
  .backgroundColor(Color.Gray)
  .padding({ left: 15, right: 15 })
  .margin({ bottom: 15 })
}
@Entry
@Component
struct Index {
  @State
  disabled: boolean = false
  @State
  focused: boolean = false
  build() {
    Column() {
      // Button TextInput 默许敞开获取焦点,页面中默许第一个这样的元素获取焦点
      // Button 比较多约束,一个是默许敞开获取焦点能看,二是禁用状况下款式无法修改
      // Button('Button').focusable(false)
      Text('toggle disabled:' + this.disabled)
        .capsule()
        .onClick(()=>{
          this.disabled = !this.disabled
        })
      Text('toggle focused:' + this.focused)
        .capsule()
        .onClick(()=>{
          this.focused = !this.focused
        })
      Text('clickMe')
        .capsule()
        .enabled(!this.disabled)
        .focusable(this.focused)
        .onClick(() => {
          promptAction.showToast({ message: 'click' })
        })
        .fontColor('#fff')
        .stateStyles({
          normal: {
            .backgroundColor(Color.Blue)
          },
          focused: {
            .backgroundColor(Color.Red)
          },
          disabled: {
            .backgroundColor(Color.Black)
          },
          pressed: {
            .backgroundColor(Color.Orange)
          }
        })
    }
  }
}
  • 运用比较多的应该是 norma
    pressed 结合下的按压效果
  • enabled(true|false) 敞开|禁用focusable(true|false) 敞开获取焦点才能|封闭

留意:

  • 页面初始化的时分,默许第一个能获取焦点的元素,会自动获取焦点

关注大众号:Android老皮!!!欢迎大家来找我探讨交流