搭建开发框架 - 一个可拖拽隐藏悬浮按钮
当前需求: 一个在初始在页面固定位置的悬浮按钮容器, 可拖拽移动,X轴位置总是靠右(左),页面滚动时,可隐藏,滚动条停止后,等待1秒再出现 封装: 一个Column, 监听onTouch事件实现拖拽,暴露Controller.trigger() 来触发隐藏动画 注意: 由于ArkUI目前没有和CSS一样的全局绝对定位,组件必须放在@Entry 或稍外层的容器(和Scroll组件同
·
当前需求:
一个在初始在页面固定位置的悬浮按钮容器, 可拖拽移动,X轴位置总是靠右(左),页面滚动时,可隐藏,滚动条停止后,等待1秒再出现
封装:
一个Column, 监听onTouch事件实现拖拽,暴露Controller.trigger() 来触发隐藏动画
注意:
由于ArkUI目前没有和CSS一样的全局绝对定位,组件必须放在@Entry 或稍外层的容器(和Scroll组件同级即可)
放最后,省却设置zIndex,否则会被遮挡
先看调用方法:
import { BuiFloatArea, BuiFloatAreaController } from '../../components/bui/BuiFloatArea';
Column() {
BuiPage({
defaultPadding:false,
slot:()=>{ this.buildContent()},
onScroll:()=>{
this.buiFloatAreaController.trigger(); //滚动条滚动时,触发浮动面板隐藏
}
})
//浮动面板
BuiFloatArea({controller:this.buiFloatAreaController,slot:()=>{this.buildFloatArea()}});
}.layoutWeight(1)
@Builder buildFloatArea(){
Column() {
Text("我是浮动面板").fontSize(12).fontColor(Color.Blue)
}.width(80).height(80).backgroundColor("#cccccc90").borderRadius(40).alignSelf(ItemAlign.Center)
.justifyContent(FlexAlign.Center)
}
组件代码:
export interface BuiFloatAreaController{
/**
* 触发 隐藏
*/
trigger:()=>void
}
@Builder function empty(){}
/**
* 一个靠右(当前默认是右下角)
* 需要放到Entry上
*/
@Component
export struct BuiFloatArea{
controller:BuiFloatAreaController={} as BuiFloatAreaController
/**
* 内容区域,外部自定义
*/
@BuilderParam slot:()=>void =empty
/**
* 初始x坐标 不要超过350,你懂得
*/
@State x:number = 250
/**
* 初始y坐标 这里可以计算当前屏幕高度来动态设置
*/
@State y:number = 600
/**
* 可拖拽的最大高度,外部传吧,可传屏幕高度
*/
@State maxTop:number = 660
//以下是内部封装属性 都是需要页面响应的,所以都需要@State修饰
@State private initX:number = this.x;
@State private startX:number = 0
@State private startY:number = 0
@State private timer:number = 0
@State private duration:number = 100
@State private myWidth:number = 50
build(){
Column(){
this.slot();
}.position({
x: this.x,
y:this.y
}).constraintSize({
minWidth:50,
minHeight:50
})
.animation({
duration: this.duration,
curve:Curve.Linear
})
.onTouch((e:TouchEvent)=>{
if(!e)return;
e.stopPropagation()
let touch = e.changedTouches?.[0]
if(!touch)return;
if(e.type == TouchType.Down){ //按下
this.startX = touch.windowX
this.startY = touch.windowY
this.duration = 0 //动画速度归零,否则拖拽时感觉不跟手
}else if(e.type == TouchType.Up){ //抬起
this.startX=0;
this.startY=0;
this.x = this.initX; //让横坐标复位
this.duration = 100 //动画速度,否则复位时闪现
}else if(e.type == TouchType.Move){ //移动
let t = e.target;
let pos:Position =t.area.globalPosition;
let x = touch.windowX
let y = touch.windowY
this.x+= x-this.startX
this.y+= y-this.startY
let posX = pos.x as number
let posY = pos.y as number
let tW = t.area.width as number
let tH = t.area.height as number
if(posX<-1){ // 左边界
this.x=0
}
if(posX+tW>360){ //右边界
this.x=360-tW
}
if(posY<-1){ //上边界
this.y=0
}
if(posY+tH>this.maxTop-2){ //下边界,这里660显然不是屏幕高度, 可以根据需要设置
this.y=this.maxTop-tH
}
this.startX=x;
this.startY=y;
console.log("",this.startX,this.startY)
}
}).onAreaChange((o:Area,n:Area)=>{
this.myWidth = n.width as number
})
}
aboutToAppear(){
this.controller.trigger = ()=>{
this.x = 365+this.myWidth; //让横坐标复位
if(this.timer)clearTimeout(this.timer)
this.timer = setTimeout(()=>{
this.duration = 300
this.x = this.initX
},1000)
}
}
}
更多推荐
已为社区贡献18条内容
所有评论(0)