<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【擁抱鴻蒙】HarmonyOS之構建一個自定義彈框

      ?

      ?

      彈窗是一種模態窗口,通常用來展示用戶當前需要的或用戶必須關注的信息或操作。在UI開發中,彈框是重要且不可忽視的組件。

      HarmonyOS內置了多種系統彈框,分別有AlertDialog 、TextPickerDialog 、DatePickerDialog以及TimePickerDialog等。

      ?

      本文將詳細介紹系統彈框的封裝和使用,并著重展現自定義彈框的實現。

      ?

      ?

      系統彈框

      AlertDialog

      AlertDialog是警告彈窗,一般由App主動彈出,用于警告和確認用戶的操作行為,需用戶手動點擊操作按鈕來取消或進行下一步。

      ?

      AlertDialog的實現

      如下圖中的“刪除聯系人”彈框,一個AlertDialog包含標題、內容和操作區三個部分組成,操作區包含兩個按鈕,我們可以在按鈕的點擊事件里添加對應響應邏輯。

      ?
      3001

      ?

      以上彈框的實現代碼如下:

      ?

      
      AlertDialog.show(
      
            {
      
              title: '刪除聯系人', // 標題
      
              message: '是否需要刪除所選聯系人?', // 內容
      
              autoCancel: false, // 點擊遮障層時,是否關閉彈窗。
      
              alignment: DialogAlignment.Bottom, // 彈窗在豎直方向的對齊方式
      
              offset: { dx: 0, dy: -20 }, // 彈窗相對alignment位置的偏移量
      
              primaryButton: {
      
                value: '取消',
      
                action: () => {
      
                  console.info('Callback when the first button is clicked');
      
                }
      
              },
      
              secondaryButton: {
      
                value: '刪除',
      
                fontColor: '#D94838',
      
                action: () => {
      
                  console.info('Callback when the second button is clicked');
      
                }
      
              },
      
              cancel: () => { // 點擊遮障層關閉dialog時的回調
      
                console.info('Closed callbacks');
      
              }
      
            }
      
          )
      
        })
      
      

      ?

      AlertDialog的封裝

      我們可以對AlertDialog進行封裝,作為工具類調用。

      ?

      
      export class CommonUtils {
      
      /\*\*
      
         \* Common alert dialog
      
         \* @param title 標題
      
         \* @param msg 提示信息
      
         \* @param context 需要保存狀態的UIAbility所對應的context
      
         \* @param primaryCallback 第一個按鈕點擊事件的回調
      
         \* @param secondCallback 第二個按鈕點擊事件的回調
      
         \*/
      
        commonAlertDialog(title:ResourceStr, msg: ResourceStr, context: common.UIAbilityContext, primaryCallback: Function, secondCallback: Function) {
      
          AlertDialog.show({
      
            title: title,
      
            message: msg,
      
            alignment: DialogAlignment.Bottom,
      
            offset: {
      
              dx: 0,
      
              dy: CommonConstants.DY\_OFFSET
      
            },
      
            primaryButton: {
      
              value: $r('app.string.cancel\_button'),
      
              action: () => {
      
                primaryCallback();
      
              }
      
            },
      
            secondaryButton: {
      
              value: $r('app.string.definite\_button'),
      
              action: () => {
      
                context.terminateSelf()
      
                secondCallback();
      
              }
      
            }
      
          });
      
        }
      
      }
      
      

      這里創建了CommonUtils的工具類,把標題、提示信息作為創建自定義彈框的參數,按鈕的點擊事件可在回調里分別實現。

      ?

      有了這種封裝,我們就能很容易地在App里調用一個風格統一的AlertDialog彈框了。

      ?

      
      CommonUtils.commonAlertDialog("提示", "是否退出登錄", context, () => {
      
        // 取消
      
        
      
      }, () => {
      
        // 確認
      
        
      
      });
      
      

      ?

      TextPickerDialog

      這是一種文本滑動選擇彈窗,一般用于從多個選項中單選內容,再將用戶所選的內容返回給調用方。

      如下圖所示,這里實現了一個選擇“足球主隊”的彈窗,用戶上下滑動滑塊再點擊“確認”就可以完成選擇。

      3002

      TextPickerDialog的實現

      ?

      
      @Entry
      
      @Component
      
      struct TextPickerDialogDemo {
      
        @State select: number = 2;
      
        private fruits: string[] = ['巴塞羅那', '曼城', '利物浦', '邁阿密國際', '拜仁慕尼黑', '多特蒙德', 'AC米蘭', '那不勒斯'];
      
      ?
      
        build() {
      
          Column() {
      
            Button('TextPickerDialog')
      
              .margin(20)
      
              .onClick(() => {
      
                TextPickerDialog.show({
      
                  range: this.fruits, // 設置文本選擇器的選擇范圍
      
                  selected: this.select, // 設置初始選中項的索引值。
      
                  onAccept: (value: TextPickerResult) => { // 點擊彈窗中的“確定”按鈕時觸發該回調。
      
                    // 設置select為按下確定按鈕時候的選中項index,這樣當彈窗再次彈出時顯示選中的是上一次確定的選項
      
                    this.select = value.index;
      
                    console.info("TextPickerDialog:onAccept()" + JSON.stringify(value));
      
                  },
      
                  onCancel: () => { // 點擊彈窗中的“取消”按鈕時觸發該回調。
      
                    console.info("TextPickerDialog:onCancel()");
      
                  },
      
                  onChange: (value: TextPickerResult) => { // 滑動彈窗中的選擇器使當前選中項改變時觸發該回調。
      
                    console.info('TextPickerDialog:onChange()' + JSON.stringify(value));
      
                  }
      
                })
      
              })
      
          }
      
          .width('100%')
      
        }
      
      }
      
      

      ?

      TextPickerDialog的封裝

      ?

      我們可以將選項作為參數進行TextPickerDialog的封裝,并提供用戶確認選項的回調。

      這里的range的類型為:string[] | string[][] | Resource | TextPickerRangeContent[] | TextCascadePickerRangeContent[],提供了多種數據源類型,我們一般使用Resource方便多語言適配。

      ?

      
      export class CommonUtils {
      
        /\*\*
      
         \* Text picker dialog
      
         \* @param items 選項
      
         \* @param textCallback 選中返回
      
         \*/
      
        textPickerDialog(items: Resource, textCallback: Function) {
      
          if (this.isEmpty(items)) {
      
            Logger.error(CommonConstants.TAG\_COMMON\_UTILS, 'item is null')
      
            return;
      
          }
      
      ?
      
          TextPickerDialog.show({
      
            range: items,
      
            canLoop: false,
      
            selected: 0,
      
            onAccept: (result: TextPickerResult) => {
      
              textCallback(result.value);
      
            },
      
            onCancel: () => {
      
              Logger.info(CommonConstants.TAG\_COMMON\_UTILS, 'TextPickerDialog canceled')
      
            }
      
          });
      
        }
      
      }
      
      

      ?

      對工具類中的TextPickerDialog的調用如下:

      ?

      
      CommonUtils.textPickerDialog($r('app.strarray.club\_array'), (selectedValue: string) => {
      
                  this.club = selectedValue;
      
                })
      
              }
      
      

      ?

      這里的app.strarray.club\_array指向resources中的配置文件stringarray.json5,其內容如下:

      ?

      
      {
      
          "strarray": [
      
              {
      
                  "name": "club\_array",
      
                  "value": [
      
                      {
      
                          "value": "巴塞羅那"
      
                      },
      
                      {
      
                          "value": "曼城"
      
                      },
      
                      {
      
                          "value": "利物浦"
      
                      },
      
                      {
      
                          "value": "邁阿密國際"
      
                      },
      
                      {
      
                          "value": "拜仁慕尼黑"
      
                      },
      
                      {
      
                          "value": "AC米蘭"
      
                      },
      
                      {
      
                          "value": "多特蒙德"
      
                      },
      
                      {
      
                          "value": "阿賈克斯"
      
                      }
      
                  ]
      
              }
      
          ]
      
      }
      
      

      ?

      DatePickerDialog

      DatePickerDialog是日期選擇器彈框,用于選擇特定格式的日期,并返回給調用方。

      ?
      3003

      ?

      ?

      ?

      DatePickerDialog的實現

      以“出生日期”選擇器彈框為例,我們通過如下代碼可以實現:

      ?

      
      let selectedDate = new Date('1949-10-1');
      
      DatePickerDialog.show({
      
                  start: new Date('1900-1-1'), // 設置選擇器的起始日期
      
                  end: new Date('2000-12-31'), // 設置選擇器的結束日期
      
                  selected: selectedDate, // 設置當前選中的日期
      
                  lunar: false,
      
                  onDateAccept: (value: Date) => { // 點擊彈窗中的“確定”按鈕時觸發該回調
      
                    // 通過Date的setFullYear方法設置按下確定按鈕時的日期,這樣當彈窗再次彈出時顯示選中的是上一次確定的日期
      
                    selectedDate.setFullYear(value.getFullYear(), value.getMonth() + 1, value.getDate())
      
                    console.info('DatePickerDialog:onDateAccept()' + JSON.stringify(value))
      
                  },
      
                  onCancel: () => { // 點擊彈窗中的“取消”按鈕時觸發該回調
      
                    console.info('DatePickerDialog:onCancel()')
      
                  },
      
                  onDateChange: (value: Date) => { // 滑動彈窗中的滑動選擇器使當前選中項改變時觸發該回調
      
                    console.info('DatePickerDialog:onDateChange()' + JSON.stringify(value))
      
                  }
      
                })
      
              })
      
      

      ?

      DatePickerDialog的封裝

      ?

      日期選擇器包含起始日期、截止日期和默認選中日期三個參數,我們只需對用戶確認選擇后的回調里響應即可。

      ?

      
      export class CommonUtils {
      
        /\*\*
      
         \* Date picker dialog
      
         \* @param dateCallback 確認選中日期回調
      
         \*/
      
        datePickerDialog(dateCallback: Function) {
      
          DatePickerDialog.show({
      
            start: new Date(CommonConstants.START\_TIME),
      
            end: new Date(),
      
            selected: new Date(CommonConstants.SELECT\_TIME),
      
            lunar: false,
      
            onDateAccept: (value: Date) => {
      
              let year: number = value.getFullYear();
      
              let month: number = value.getMonth() + 1;
      
              let day: number = value.getDate();
      
              let selectedDate: string = `${year}${CommonConstants.DATE\_YEAR}`+`${month}${CommonConstants.DATE\_MONTH}`+`${day}${CommonConstants.DATE\_DAY}`;
      
              dateCallback(selectedDate);
      
            }
      
          });
      
        }
      
      }
      
      

      ?

      基于以上封裝,datePickerDialog的調用可以簡單地實現如下:

      ?

      
      CommonUtils.datePickerDialog((dateValue: string) => {
      
          this.birthdate = dateValue;
      
      })
      
      

      ?

      自定義彈框

      除了系統彈框,還可以對彈框進行自定義。自定義彈框更加靈活,適用于更多的業務場景。

      ?

      這里,我們實現一個包含多選器的自定義彈框,其實現效果如下圖所示。

      不難看出,這個彈框由標題、選擇列表和按鈕操作區構成。

      ?

      自定義彈框需要使用裝飾器@CustomDialog

      我們創建一個名為CustomDialogWidget的struct,并添加三個屬性。

      ?

      * items是數據源;

      * selectedContent是選中結果拼接而成的字符串;

      * controller是自定義彈框的控制器,其類型為CustomDialogController

      ?

      
      export default struct CustomDialogWidget {
      
        @State items: Array<CustomItem> = [];
      
        @Link selectedContent: string;
      
        private controller?: CustomDialogController;
      
      }
      
      

      ?

      在組件的aboutToAppear()中實現數據源的獲取,使用到resmgr.ResourceManagergetStringArrayValue方法。

      ?

      
      aboutToAppear(): void {
      
          let context: Context = getContext(this);
      
          if (CommonUtils.isEmpty(context) || CommonUtils.isEmpty(context.resourceManager)) {
      
            Logger.error(CommonConstants.TAG\_CUSTOM, 'context or resourceManager is null');
      
            return;
      
          }
      
      ?
      
          let manager = context.resourceManager;
      
          manager.getStringArrayValue($r('app.strarray.hobbies\_data').id, (error, hobbyArray) => {
      
            if (!CommonUtils.isEmpty(error)) {
      
              Logger.error(CommonConstants.TAG\_CUSTOM, 'error = ' + JSON.stringify(error));
      
            } else {
      
              hobbyArray.forEach((itemTitle: string) => {
      
                let item = new CustomItem();
      
                item.title = itemTitle;
      
                item.isChecked = false;
      
                this.items.push(item);
      
      ?
      
                Logger.info(item.title);
      
              });
      
            }
      
          });
      
        }
      
      

      ?

      然后在Build()中實現其界面的搭建:

      ?

      
        build() {
      
          Column() {
      
            // 標題
      
            Text($r('app.string.title\_hobbies'))
      
              .fontSize($r('app.float.title\_hobbies\_size'))
      
              .fontColor($r('app.color.custom\_color'))
      
              .lineHeight($r('app.float.title\_line\_height'))
      
              .fontWeight(CommonConstants.BIGGER)
      
              .alignSelf(ItemAlign.Start)
      
              .margin({ left: $r('app.float.title\_left\_distance') })
      
      ?
      
            // 選項列表
      
            List() {
      
             ForEach(this.items, (item: CustomItem) => {
      
               ListItem() {
      
                Row() {
      
                  Text(item.title)
      
                    .fontSize($r('app.float.label\_size'))
      
                    .fontColor($r('app.color.custom\_color'))
      
                    .layoutWeight(CommonConstants.WEIGHT\_ONE)
      
                    .textAlign(TextAlign.Start)
      
                    .fontWeight(CommonConstants.BIGGER)
      
                    .margin({ left: $r('app.float.label\_left\_distance') })
      
                  Toggle({ type: ToggleType.Checkbox, isOn: false })
      
                    .onChange((isCheck) => {
      
                      item.isChecked = isCheck;
      
                    })
      
                    .width($r('app.float.toggle\_size'))
      
                    .height($r('app.float.toggle\_size'))
      
                    .margin({ right: $r('app.float.toggle\_right\_distance') })
      
                }
      
               }
      
               .height($r('app.float.options\_height'))
      
               .margin({
      
                 top: $r('app.float.options\_top\_distance'),
      
                 bottom:$r('app.float.options\_bottom\_distance')
      
               })
      
             }, (item: CustomItem) => JSON.stringify(item.title))
      
            }
      
            .margin({
      
              top: $r('app.float.list\_top\_distance'),
      
              bottom: $r('app.float.list\_bottom\_distance')
      
            })
      
            .divider({
      
              strokeWidth: $r('app.float.divider\_height'),
      
              color: $r('app.color.divider\_color')
      
            })
      
            .listDirection(Axis.Vertical)
      
            .edgeEffect(EdgeEffect.None)
      
            .width(CommonConstants.FULL\_WIDTH)
      
            .height($r('app.float.options\_list\_height'))
      
      ?
      
            // 操作按鈕
      
            Row() {
      
              Button($r('app.string.cancel\_button'))
      
                .dialogButtonStyle()
      
                .onClick(() => {
      
                  this.controller?.close();
      
                })
      
      ?
      
              Blank()
      
                .backgroundColor($r('app.color.custom\_blank\_color'))
      
                .width($r('app.float.blank\_width'))
      
                .opacity($r('app.float.blank\_opacity'))
      
                .height($r('app.float.blank\_height'))
      
      ?
      
              Button($r('app.string.definite\_button'))
      
                .dialogButtonStyle()
      
                .onClick(() => {
      
                  this.setSelectedItems(this.items);
      
                  this.controller?.close();
      
                })
      
            }
      
          }
      
        }
      
      

      ?

      在確定按鈕的回調中,我們調用setSelectedItems(),其實現如下:

      ?

      
        setSelectedItems(items: CustomItem[]) {
      
          if (CommonUtils.isEmpty(items)) {
      
            Logger.error(CommonConstants.TAG\_HOME, "Items is empty")
      
            return;
      
          }
      
      ?
      
          let selectedText: string = items.filter((isCheckedItem: CustomItem) => isCheckedItem?.isChecked)
      
            .map<string>((checkedItem: CustomItem) => {
      
              return checkedItem.title!;
      
            })
      
            .join(CommonConstants.COMMA);
      
      ?
      
          if (!CommonUtils.isEmpty(selectedText)) {
      
            this.selectedContent = selectedText;
      
          }
      
        }
      
      }
      
      

      ?

      這里我們還用到了組件的屬性擴展方法封裝(用于提取重復的屬性代碼進行復用):

      ?

      
      @Extend(Button)
      
      function dialogButtonStyle() {
      
        .fontSize($r('app.float.button\_text\_size'))
      
        .fontColor(Color.Blue)
      
        .layoutWeight(CommonConstants.WEIGHT\_ONE)
      
        .height($r('app.float.button\_height'))
      
        .backgroundColor(Color.White)
      
      }
      
      

      ?

      自定義彈框的調用

      ?

      自定義彈框的調用基于CustomDialogController,將CustomDialogWidget作為它的參數builder即可實現控制器調出我們預期的自定義彈框。

      ?

      
      @State birthdate: string = '';
      
      @State sex: string = '';
      
      @State hobbies: string = '';
      
      private sexArray: Resource = $r('app.strarray.sex\_array');
      
      ?
      
      customDialogController: CustomDialogController = new CustomDialogController({
      
          builder: CustomDialogWidget({
      
            selectedContent: this.hobbies
      
          }),
      
          alignment: DialogAlignment.Bottom,
      
          customStyle: true,
      
          offset: {
      
            dx: 0,
      
            dy: CommonConstants.DY\_OFFSET
      
          }
      
        });
      
      

      ?

      以上,我們總結了HarmonyOS系統彈框和自定義彈框的實現、封裝及調用。

      ?

      我是鄭知魚??,歡迎大家討論與指教。

      如果你覺得有所收獲,也請點贊????收藏??關注??我吧~~

      具體代碼見:customDialog

      ?

      參考:<HarmonyOS第一課>構建更加豐富的頁面

      posted @ 2025-05-28 12:05  鄭知魚  閱讀(87)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品天干天干综合网| 久久亚洲欧美日本精品| 福利一区二区视频在线| 久久婷婷五月综合色和啪| 国产中文字幕精品视频| 成人嫩草研究院久久久精品| 久久精品国产福利一区二区| 精品亚洲国产成人| 超碰人人超碰人人| 搜索| 久久亚洲国产五月综合网| 岛国中文字幕一区二区| 夜夜躁狠狠躁日日躁视频| 亚洲爆乳少妇无码激情| 蜜臀午夜一区二区在线播放| 呻吟国产av久久一区二区| 欧美日韩精品一区二区三区高清视频| 精品久久久久无码| 国产精品午夜福利合集| 激情影院内射美女| 色天使亚洲综合一区二区| 日本不卡不二三区在线看| 东京热无码国产精品| 亚洲成av人片无码天堂下载| 人妻无码中文字幕| 农村熟女大胆露脸自拍| 绥中县| 九月婷婷人人澡人人添人人爽| 国产网友愉拍精品视频手机| 欧美性受xxxx黑人猛交| 亚洲天堂激情av在线| 少妇高潮喷水正在播放| 久久久天堂国产精品女人| 中文字幕丰满伦子无码ab| 日韩人妻无码一区二区三区99| 伊人久久精品久久亚洲一区| 免费无码午夜理论电影| 国产一级av在线播放| 久久99精品久久久久麻豆| 视频一区二区三区四区不卡| 精品日韩人妻中文字幕|