1、HarmonyOS 自定義對話框自動關閉的問題?
啟動頁做了個隱私協議彈窗,autoCancel為false。UI中使用 Text() ContainerSpan() Span()組件,設置了點擊事件,點擊后使用router.pushUrl()的方法跳轉到協議頁面。點擊時,對話框消失了同時頁面進行了跳轉。點擊事件中沒有調用close操作。
使用Stack組件模擬實現Dialog的效果,參考下以下demo:
import router from '@ohos.router';@Entry
@Component
struct First {@State textValue: string = 'Hello World'// 顯隱控制設置為不占用@State visible: Visibility = Visibility.Nonebuild() {// 使用stack可以實現假的dialog覆蓋原頁面上面Stack() {Row() {// 初始頁面Column() {Text('Hello World').fontSize(50).fontWeight(FontWeight.Bold)// 觸發dialog的地方Button('click').onClick(() => {console.log("hit me!")if (this.visible == Visibility.Visible) {this.visible = Visibility.None} else {this.visible = Visibility.Visible}}).backgroundColor(0x777474).fontColor(0x000000)}.width('100%')}.height('100%').backgroundColor(0x885555)//這里開始是構造彈窗效果主要需要修改的地方,首先是加了一個半透明灰色的蒙層效果Text('').onClick(() => {if (this.visible == Visibility.Visible) {this.visible = Visibility.None} else {this.visible = Visibility.Visible}}).width('100%').height('100%')// 透明度可以自己調節.opacity(0.16).backgroundColor(0x000000).visibility(this.visible)Column() {// 這個可以調節對話框效果,柵格布局,xs,sm,md,lg分別為四種規格// 下面的breakpoints是用來區別當前屬于哪個類型的斷點// gridRow里的柵格數量為總數,gridCol里的就是偏移和假Dialog所占據的柵格數GridRow({columns:{xs:1 ,sm: 4, md: 8, lg: 12},breakpoints: { value: ["400vp", "600vp", "800vp"],reference: BreakpointsReference.WindowSize },}){GridCol({span:{xs:1 ,sm: 2, md: 4, lg: 8},offset:{xs:0 ,sm: 1, md: 2, lg: 2}}){// 這里放的就是原Dialog里的column里的東西,稍微改改應該就可以用了Column() {Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%').onChange((value: string) => {this.textValue = value})Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 })Flex({ justifyContent: FlexAlign.SpaceAround }) {Button('cancel').onClick(() => {if (this.visible == Visibility.Visible) {this.visible = Visibility.None} else {this.visible = Visibility.Visible}}).backgroundColor(0xffffff).fontColor(Color.Black)Button('jump').onClick(() => {router.pushUrl({url: 'pages/Second'})}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: 10 })}.backgroundColor(0xffffff).visibility(this.visible).clip(true).borderRadius(20)}}}.width('95%')//設置彈窗寬度}}
}
2、HarmonyOS WaterFlow嵌套問題?
WaterFlow嵌套在父List控件中(利用的懶加載LazyForEach獲取的數據,cachedCount設置的是5) 若WaterFlow的數據有100條當List滑動到WaterFlow的時候,這100條數據對應的WaterFlowItem 都會加載出來(觸發了onAppear()),如果數據過多,如增長到1000條,這樣是否會導致列表卡頓呢?是否有其他方法控制 預加載的WaterFlowItem的數量呢?
數據過多是不會導致列表卡頓的,關于控制預加載的WaterFlowItem數量問題 可以參考此鏈接,其中有詳細介紹:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/performance/waterflow_optimization.md
3、HarmonyOS setWindowSystemBarProperties修改狀態欄顏色?
調用系統api setWindowSystemBarProperties修改狀態欄顏色 , APP上滑動,狀態欄還會是當前app設置的顏色,這種有修改狀態欄顏色的需求,是調用系統api,還是自己寫組件
可以設置下窗口為全屏布局,不去設置setWindowSystemBarProperties
mainWindowClass.setWindowLayoutFullScreen(true, (err: BusinessError) => {let errCode: number = err.code;if (errCode) {console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));return;}console.info('Succeeded in setting the window layout to full-screen mode.');
});
4、HarmonyOS 仿AppBarLayout吸附使用Scroll滾動到頂時出現抖動問題?
通過onScroll移動scroll上層的組件,實現吸附效果,在滾動到頂部的場景下出現抖動問題,使用onWillScroll,onDidScroll問題更明顯
出現抖動是因為回到頂層使用了動畫,然后Text沒有動畫效果,才會出現這樣,這個目前吸頂的效果不建議在scroll的時候margin,可以參考下這個demo:
enum ScrollPosition {start,center,end
}class ItemClass {content: string = '';color: Color = Color.White;
}@Entry
@Component
struct NestedScrollDemo {@State listPosition: number = ScrollPosition.start; // 0代表滾動到List頂部,1代表中間值,2代表滾動到List底部。@State scrollPosition: number = ScrollPosition.start; // 0代表滾動到頁面頂部,1代表中間值,2代表滾動到頁面底部。@State showTitle: boolean = false;@State currentYOffset: number = 0;private arr: ItemClass[] = [];private colorArr: Color[] = [Color.White, Color.Blue, Color.Brown, Color.Green, Color.Gray];private scrollerForScroll: Scroller = new Scroller();private scrollerForList: Scroller = new Scroller();private scrollerForTitle: Scroller = new Scroller();@State currentIndex: number = 0;aboutToAppear() {for (let i = 0; i < 6; i++) {let data: ItemClass = {content: i.toString(),color: this.colorArr[i % 5]}this.arr.push(data);}}@BuildermyBuilder() {Row() {List({ space: 2, initialIndex: 0, scroller: this.scrollerForTitle }) {ForEach(this.arr, (item: ItemClass, index) => {ListItem() {Column() {Text(item.content);Divider().color('#000000').strokeWidth(5).visibility(index == this.currentIndex ? Visibility.Visible : Visibility.Hidden)}.width('25%').height(50).onClick(() => {this.scrollerForList.scrollToIndex(index)this.scrollerForScroll.scrollEdge(Edge.Bottom)})}})}.listDirection(Axis.Horizontal).scrollBar(BarState.Off)}.backgroundColor('#ffe2d0d0').alignItems(VerticalAlign.Center)}build() {Stack({ alignContent: Alignment.Top }) {Scroll(this.scrollerForScroll) {Column() {Image($r('app.media.app_icon')).width("100%").height("40%")this.myBuilder();List({ space: 10, scroller: this.scrollerForList }) {ForEach(this.arr, (item: ItemClass, index) => {ListItem() {Column() {Text(item.content)//添加其他內容}.width('100%').height(500).backgroundColor(item.color)}.width("100%").height(500).onVisibleAreaChange([0.8], (isVisible) => {if (isVisible) {this.currentIndex = index;this.scrollerForTitle.scrollToIndex(this.currentIndex);}})}, (item: ItemClass) => item.content)}.padding({ left: 10, right: 10 }).width("100%").edgeEffect(EdgeEffect.None).scrollBar(BarState.Off).onReachStart(() => {this.listPosition = ScrollPosition.start}).onReachEnd(() => {this.listPosition = ScrollPosition.end}).onScrollFrameBegin((offset: number, state: ScrollState) => {// 滑動到列表中間時if (!((this.listPosition == ScrollPosition.start && offset < 0)|| (this.listPosition == ScrollPosition.end && offset > 0))) {this.listPosition = ScrollPosition.center}// 如果頁面已滾動到底部,列表不在頂部或列表有正向偏移量if (this.scrollPosition == ScrollPosition.end&& (this.listPosition != ScrollPosition.start || offset > 0)) {return { offsetRemain: offset };} else {this.scrollerForScroll.scrollBy(0, offset)return { offsetRemain: 0 };}}).width("100%").height("calc(100% - 50vp)").backgroundColor('#F1F3F5')}}.scrollBar(BarState.Off).width("100%").height("100%").onScroll((xOffset: number, yOffset: number) => {this.currentYOffset = this.scrollerForScroll.currentOffset().yOffset;// 非(頁面在頂部或頁面在底部),則頁面在中間if (!((this.scrollPosition == ScrollPosition.start && yOffset < 0)|| (this.scrollPosition == ScrollPosition.end && yOffset > 0))) {this.scrollPosition = ScrollPosition.center}}).onScrollEdge((side: Edge) => {if (side == Edge.Top) {// 頁面在頂部this.scrollPosition = ScrollPosition.start} else if (side == Edge.Bottom) {// 頁面在底部this.scrollPosition = ScrollPosition.end}}).onScrollFrameBegin(offset => {if (this.scrollPosition == ScrollPosition.end) {return { offsetRemain: 0 };} else {return { offsetRemain: offset };}})}.width('100%').height('100%').backgroundColor(0xDCDCDC)}
}
5、HarmonyOS Grid上下滑動的動效和需求的差距很大?
Grid上下滑動的動效和需求的差距很大
參考DEMO:
@Entry
@Component
export struct Page240605101412064_temp {weekDatas: string[] = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];// private startDay: Date = new Date(2024, 4, 1) // 當前顯示的月份的第一天data: Array<CalendaEntity> = [];@State gridTop: number = 0@State blankTop: number = 0private endBlankY: number = 0private endGridY: number = 0private isStart: boolean = trueprivate scroller: Scroller = new Scroller()private today: Date = new Date()private startDay: Date = new Date(this.today.getFullYear(), this.today.getMonth(), 1)aboutToAppear(): void {const monthDataWithWeekday = this.calcDatas(this.startDay)monthDataWithWeekday.forEach(item => {console.log("日期是》》》》》》》" + item.year, ' ', item.month, ' ', item.day, ' ', item.weekday);});}calcDatas(startDate: Date): Array<CalendaEntity> {const endDate = new Date(startDate.getFullYear(), startDate.getMonth() + 1, 0);let currentDate = new Date(startDate);while (currentDate <= endDate) {const weekday = currentDate.getDay();const weekdayNames = [0, 1, 2, 3, 4, 5, 6];const weekdayStr = weekdayNames[weekday];let year = currentDate.getFullYear()let month = currentDate.getMonth() + 1let day = currentDate.getDate().toString()if (day === this.today.getDate().toString()) {day = '今';}this.data.push({year,month,day,weekday: weekdayStr});currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() + 1)}if (this.data.length !== 0) {let firstWeek = this.data[0].weekday;let tempData: Array<CalendaEntity> = [];while (firstWeek > 0) {tempData.push(new CalendaEntity());firstWeek--;}this.data = tempData.concat(this.data);let lastWeek = this.data[this.data.length - 1].weekday;while (lastWeek < 6) {this.data.push(new CalendaEntity())lastWeek++;}}return this.data;}build() {Column() {Row() {ForEach(this.weekDatas, (item: string) => {Text(item).textAlign(TextAlign.Center).fontColor('#9E9E9E').fontSize(14).layoutWeight(1)})}// .backgroundColor().alignItems(VerticalAlign.Center).height(60)Scroll(this.scroller) {Column() {Grid() {ForEach(this.data, (item: CalendaEntity) => {GridItem() {Stack() {Image("").backgroundColor('#35cfba').borderRadius(100).width(34).height(34).visibility((item.day === "0" || item.day !== '今') ? Visibility.Hidden : Visibility.Visible)Column() {Text(item.day === "0" ? " " : item.day).fontSize(14).fontColor(Color.Gray).width('14%').textAlign(TextAlign.Center)Text().backgroundColor(Color.Red).width(4).height(4).borderRadius(50).visibility(item.day === "0" ? Visibility.Hidden : Visibility.Visible)}}}.onClick(() => {console.log("dddddddddd");})})}.rowsGap(20)// .columnsGap(10).backgroundColor('#fff').margin({ top: this.gridTop }).onAreaChange((oldValue: Area, newValue: Area) => {console.log('h', newValue.height)// h 304})Blank().layoutWeight(1).backgroundColor(Color.Gray).margin({ top: this.blankTop })}.height('calc(100% + 560vp)')}.height('100%').scrollBar(BarState.Off).onReachStart(() => {this.isStart = true}).onScrollFrameBegin((offset: number, state: ScrollState) => {console.log('offset', offset)if (this.isStart) {return { offsetRemain: 0 }}if (!this.scroller.currentOffset().yOffset) {this.isStart = false}return { offsetRemain: offset }}).parallelGesture(PanGesture({ direction: PanDirection.Vertical, distance: 1 }).onActionStart((event: GestureEvent) => {console.info('Pan start')}).onActionUpdate((event: GestureEvent) => {console.log('event.offsetY', event.offsetY)console.log('this.isStart', this.isStart)if (event && this.isStart) {if (this.blankTop == 0) {if (this.endGridY == 0) {this.gridTop = this.endGridY + event.offsetY < -(304 / 6 * 2) ? -(304 / 6 * 2) :this.endGridY + event.offsetY > 0 ? 0 : this.endGridY + event.offsetYconsole.log('this.gridTop', this.gridTop)} else {this.gridTop = this.endBlankY + this.endGridY + event.offsetY < -(304 / 6 * 2) ? -(304 / 6 * 2) :this.endBlankY + this.endGridY + event.offsetY > 0 ? 0 :this.endBlankY + this.endGridY + event.offsetYconsole.log('this.gridTop', this.gridTop)}}if (this.gridTop == -(304 / 6 * 2)) {if (this.endBlankY == 0) {this.blankTop =this.endBlankY + event.offsetY + (304 / 6 * 2) < -(304 / 6 * 3) ? -(304 / 6 * 3) :this.endBlankY + event.offsetY + (304 / 6 * 2) > 0 ? 0 :this.endBlankY + event.offsetY + (304 / 6 * 2)console.log('this.blankTop', this.blankTop)} else {this.blankTop =this.endBlankY + event.offsetY < -(304 / 6 * 3) ? -(304 / 6 * 3) :this.endBlankY + event.offsetY > 0 ? 0 :this.endBlankY + event.offsetYconsole.log('this.blankTop', this.blankTop)}}}}).onActionEnd((event: GestureEvent) => {this.endBlankY = this.blankTopthis.endGridY = this.gridTopconsole.log('this.endBlankY', this.endBlankY)console.log('this.endGridY', this.endGridY)}))}.width('100%')// .height(330)}
}export class CalendaEntity {year: number = 0;month: number = 0;day: string = "0";weekday: number = -1;
}export enum OptMode {WEEK = "week",MONTH = "month",
}