【每日学点HarmonyOS Next知识】图片拖动、动画放大、列表高度、返回键监听、分割线颜色

1、HarmonyOS image 组件的图片可以随意拖动?

mage组件默认拖拽效果,draggable设置为true时,组件可拖拽,参考以下文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/image-V5

HarmonyOS中Image组件默认支持长按触发拖拽事件。具体来说,Image组件的拖拽能力是通过设置组件的draggable属性来实现的。通常情况下,Text、TextInput、TextArea、Hyperlink、Image和RichEditor组件的draggable属性是默认为true的,这意味着这些组件可以被长按并拖拽。可以通过自定义image相关组件,实现部分把draggable关了

2、HarmonyOS 换成model后动画放大实现不了?

listitem内容为object,不能直接用 ==判断当前item,可以改用index确定当前点击的item,修改如下:(其他案例参考:https://gitee.com/harmonyos-cases/cases/tree/master/CommonAppDevelopment/feature/listexchange)

复制代码
import curves from '@ohos.curves';
@Entry
@Component
struct model {
  @State private arr: titleStrModel[] = []
  @State dragItem: titleStrModel = new titleStrModel()
  @State scaleItem: titleStrModel = new titleStrModel()
  @State neighborItem: titleStrModel = new titleStrModel()
  @State selectedIndex:number = -1
  @State neighborScale: number = -1
  private dragRefOffset: number = 0
  @State offsetX: number = 0
  @State offsetY: number = 0
  private ITEM_INTV: number = 120
  aboutToAppear(): void {
    const d = new titleStrModel()
    d.name = 'wewewe'
    const b = new titleStrModel()
    b.name = 'adadad'
    const h = new titleStrModel()
    h.name = 'dfdfdf'
    this.arr.push(d)
    this.arr.push(b)
    this.arr.push(h)
  }

  //根据当前index确定item是否缩放
  scaleSelect(item: titleStrModel):void {
    this.selectedIndex = this.arr.indexOf(item)
    this.arr[this.selectedIndex].scale = 1.05
  }
  itemMove(index: number, newIndex: number): void {
    let tmp = this.arr.splice(index, 1)
    this.arr.splice(newIndex, 0, tmp[0])
  }
  build() {
    Stack() {
      List({ space: 20, initialIndex: 0 }) {
        ForEach(this.arr, (item: titleStrModel) => {
          ListItem() {
            Row() {
              Text('' + item.name)
                .width('100%')
                .height(100)
                .fontSize(16)
                .textAlign(TextAlign.Center)
                .borderRadius(10)
                .backgroundColor(0xFFFFFF)
              Image($r('app.media.app_icon'))
                .width(100)
                .height(100)
            }
            .shadow(this.scaleItem.name == item.name ? { radius: 70, color:Color.Blue, offsetX: 0, offsetY: 0 } :
              { radius: 0, color: Color.Blue, offsetX: 0, offsetY: 0 })
            .animation({ curve: Curve.Sharp, duration: 300 })
          }
          .margin({ left: 12, right: 12 })
          .scale({ x: item.scale, y: item.scale })
          .zIndex(this.dragItem.name == item.name ? 1 : 0)
          .translate(this.dragItem.name == item.name ? { y: this.offsetY } : { y: 0 })
          .gesture(

            //以下组合手势为顺序识别,当长按手势事件未正常触发时则不会触发拖动手势事件
            GestureGroup(GestureMode.Sequence,
              LongPressGesture({ repeat: true })
                .onAction((event?: GestureEvent) => {
                  animateTo({ curve: Curve.Friction, duration: 300 }, () => {
                    this.scaleItem = item
                    this.scaleSelect(item)
                  })
                })
                .onActionEnd(() => {
                  animateTo({ curve: Curve.Friction, duration: 300 }, () => {
                    this.scaleItem = new titleStrModel()
                  })
                }),
              PanGesture({ fingers: 1, direction: null, distance: 0 })
                .onActionStart(() => {
                  this.dragItem = item
                  this.dragRefOffset = 0
                })
                .onActionUpdate((event: GestureEvent) => {
                  this.offsetY = event.offsetY - this.dragRefOffset
                  // console.log('Y:' + this.offsetY.toString())
                  this.neighborItem = new titleStrModel()
                  let index = this.arr.indexOf(item)
                  let curveValue = curves.initCurve(Curve.Sharp)
                  let value: number = 0
                  //根据位移计算相邻项的缩放
                  if (this.offsetY < 0) {
                    value = curveValue.interpolate(-this.offsetY / this.ITEM_INTV)
                    this.neighborItem = this.arr[index-1]
                    this.neighborScale = 1 - value / 20;
                    console.log('neighborScale:' + this.neighborScale.toString())
                  } else if (this.offsetY > 0) {
                    value = curveValue.interpolate(this.offsetY / this.ITEM_INTV)
                    this.neighborItem = this.arr[index+1]
                    this.neighborScale = 1 - value / 20;
                  }
                  //根据位移交换排序
                  if (this.offsetY > this.ITEM_INTV / 2) {
                    animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
                      this.offsetY -= this.ITEM_INTV
                      this.dragRefOffset += this.ITEM_INTV
                      this.itemMove(index, index + 1)
                    })
                  } else if (this.offsetY < -this.ITEM_INTV / 2) {
                    animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
                      this.offsetY += this.ITEM_INTV
                      this.dragRefOffset -= this.ITEM_INTV
                      this.itemMove(index, index - 1)
                    })
                  }
                })
                .onActionEnd((event: GestureEvent) => {
                  animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
                    this.dragItem = new titleStrModel()
                    this.neighborItem = new titleStrModel()
                    //动画结束将缩放还原
                    this.arr[this.arr.indexOf(this.scaleItem)].scale = 1
                  })
                  animateTo({
                    curve: curves.interpolatingSpring(14, 1, 170, 17), delay: 150
                  }, () => {
                    this.scaleItem = new titleStrModel()
                  })
                })
            )
              .onCancel(() => {
                animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => {
                  this.dragItem = new titleStrModel()
                  this.neighborItem = new titleStrModel()
                })
                animateTo({
                  curve: curves.interpolatingSpring(14, 1, 170, 17), delay: 150
                }, () => {
                  this.scaleItem = new titleStrModel()
                })
              })
          )
        })
      }
    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
  }
}
class titleStrModel {
  name:string = ''
  scale:number = 1 //增加scale属性, 每个item都有对应的scale值
}
3、HarmonyOS 为什么List的高度设置100% 还是显示不全?

问题是解决了(方法:子控件Column,List都加上layoutWeight(1)),有点疑惑,想请教一下:

  1. 为什么外部用了layoutWeight(1) 内部所有的Column与List也要用layoutWeight(1) 想知道原理
  2. 外部我已经计算高度了(TNAppUIData.getPageHeight())为什么Tabs我不用layoutWeight(1)还是占满屏幕的剩余高度,我计算给的高度不起作用?

问题1:父容器尺寸确定时,设置了layoutWeight属性的子元素与兄弟元素占主轴尺寸按照权重进行分配,前提是父容器尺寸确定。比如共有三个元素且都用了layoutWeight(1),它们按照"1:1:1"的比例均分父容器主轴方向的空间。与.width('33%')、.width('34%')、.width('33%')效果相同。

问题2:tabs是默认占满屏幕的

4、HarmonyOS 物理返回键监听?

customdialog弹窗打开时,按物理返回键,希望不关闭弹窗

可以使用onBackPress当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-custom-component-lifecycle-V5#onbackpress

onBackPress?(): void | boolean

当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理。

复制代码
// xxx.ets
@Entry
@Component
struct IndexComponent {
  @State textColor: Color = Color.Black;

  onPageShow() {
    this.textColor = Color.Blue;
    console.info('IndexComponent onPageShow');
  }

  onPageHide() {
    this.textColor = Color.Transparent;
    console.info('IndexComponent onPageHide');
  }

  onBackPress() {
    this.textColor = Color.Red;
    console.info('IndexComponent onBackPress');
  }

  build() {
    Column() {
      Text('Hello World')
        .fontColor(this.textColor)
        .fontSize(30)
        .margin(30)
    }.width('100%')
  }
}
5、HarmonyOS list divider中startmargin前面的颜色怎么和listitem保持一致?

目前使用list的divider属性并不能满足你想实现的效果,可以自定义实现分隔线效果,参考如下代码:

复制代码
build() {

  Row(){
    List(){
      ListItem(){
        Flex({direction:FlexDirection.Column,justifyContent:FlexAlign.SpaceBetween}){
          Text('test')
          Divider()
            .color(Color.Red)
              // .height(15)
            .strokeWidth(5)
            .margin({left:50})
        }
      }.backgroundColor(Color.Blue)
      .height(100)
      ListItem(){
        Flex({direction:FlexDirection.Column,justifyContent:FlexAlign.SpaceBetween}){
          Text('test')
          Divider()
            .color(Color.Red)
            .strokeWidth(5)
            .margin({left:50,bottom:0})
        }


      }.backgroundColor(Color.Orange)
      .height(100)
      ListItem(){
        Flex({direction:FlexDirection.Column,justifyContent:FlexAlign.SpaceBetween}){
          Text('test')
          Divider()
            .color(Color.Red)
            .strokeWidth(5)
            .margin({left:50})
        }


      }.backgroundColor(Color.Yellow)
      .height(100)
    }

    // .divider({strokeWidth:5,color:Color.Red,startMargin:50})
    .width('100%').height('100%')
    .backgroundColor(Color.Gray)
  }
}
相关推荐
小小小小小星2 小时前
鸿蒙开发之ArkUI框架进阶:从声明式范式到跨端实战
harmonyos·arkui
鸿蒙小灰2 小时前
鸿蒙开发对象字面量类型标注的问题
harmonyos
鸿蒙先行者2 小时前
鸿蒙Next不再兼容安卓APK,开发者该如何应对?
harmonyos
YF云飞5 小时前
.NET 在鸿蒙系统(HarmonyOS Next)上的适配探索与实践
华为·.net·harmonyos
Quarkn9 小时前
鸿蒙原生应用ArkUI之自定义List下拉刷新动效
list·harmonyos·arkts·鸿蒙·arkui
AlbertZein10 小时前
HarmonyOS5 凭什么学鸿蒙 —— Context详解
harmonyos
whysqwhw18 小时前
鸿蒙音频播放方式总结
harmonyos
whysqwhw18 小时前
鸿蒙音频录制方式总结
harmonyos
zhanshuo20 小时前
HarmonyOS 实战:用 @Observed + @ObjectLink 玩转多组件实时数据更新
harmonyos
zhanshuo20 小时前
鸿蒙任务调度机制深度解析:优先级、时间片、多核与分布式的流畅秘密
harmonyos