快应用sample与各家厂商的差异对比

160 阅读6分钟

鸿蒙的示例官网:developer.huawei.com/consumer/cn…

鸿蒙的示例官网代码仓库:gitee.com/harmonyos_s…

安卓的示例官网:developer.android.com/samples?hl=…

安卓的示例官网代码仓库:github.com/android

安卓的之前的api demo 仓库:github.com/THEONE10211…

苹果的示例官网:developer.apple.com/library/arc…

苹果的示例仓库:github.com/bqlin/Apple…

快应用sample与鸿蒙的sample(HarmonyOS_Samples)对比

1,组件之间的对比

鸿蒙的sample侧重把多个组件组合在一起应用到真实的开发场景中来,也同时凸显出组件的大部分属性和方法的在这个示例中的的应用,写出一个相对完整的示例工程展示给到开发者学习。

鸿蒙具体的代码展示和图片如下:

/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ListDataConstants } from '../constants/ListDataConstants';
import { CommonConstants } from '../constants/CommonConstants';
import { BreakpointType } from '../utils/BreakpointType';

@Component
export struct AdaptiveTabCenteringIndex {
  @StorageLink('breakPoint') breakPoint: string = CommonConstants.BREAK_POINT_SM;
  @Consume('pageInfos') pageInfos: NavPathStack;
  @State tabIndexSelected: number = 0;

  build() {
    NavDestination() {
      Column() {
        Row() {
          Image($r('app.media.icon_back'))
            .width($r('app.float.image_width'))
            .height($r('app.float.image_height'))
            .onClick(() => {
              this.pageInfos.pop();
            })
        }
        .width(CommonConstants.FULL_WIDTH_PERCENT)
        .margin({
          left: $r('app.float.back_margin_left'),
          top: $r('app.float.back_margin_top')
        })
        .justifyContent(FlexAlign.Start)

        Column() {
          Row() {
            Column() {
              List({
                space: new BreakpointType(CommonConstants.TAB_PADDING_SM, CommonConstants.TAB_PADDING_MD,
                  CommonConstants.TAB_PADDING_LG).getValue(this.breakPoint)
              }) {
                ForEach(ListDataConstants.RECOMMENDATION_TAB_LIST, (item: string, index: number) => {
                  ListItem() {
                    Column() {
                      Text(item)
                        .fontSize($r('app.float.font_size_16'))
                        .fontWeight(CommonConstants.FONT_WEIGHT_500)
                        .fontColor(this.tabIndexSelected === index ? $r('app.color.red') : $r('app.color.black'))
                        .height($r('app.float.text_height'))
                        .focusable(true)
                        .groupDefaultFocus(index === 0 ? true : false)
                    }
                  }
                  .margin({
                    top: $r('app.float.recommendation_margin_top'),
                    bottom: $r('app.float.recommendation_margin_bottom')
                  })
                  .border({
                    width: {
                      bottom: this.tabIndexSelected === index ?
                      $r('app.float.bottom_width_2') : $r('app.float.bottom_width_0')
                    },
                    color: {
                      bottom: this.tabIndexSelected === index ? $r('app.color.red') : ''
                    },
                    style: {
                      bottom: BorderStyle.Solid
                    }
                  })
                  .onClick(() => {
                    this.tabIndexSelected = index;
                  })
                }, (item: string, index: number) => index + JSON.stringify(item))
              }
              .scrollBar(BarState.Off)
              .listDirection(Axis.Horizontal)
            }
            .width($r('app.float.width_296'))
            .height($r('app.float.height_56'))
            .backgroundColor($r('app.color.adaptive_tab_background'))
            .justifyContent(FlexAlign.Center)
            .alignItems(HorizontalAlign.Center)
            .layoutWeight(CommonConstants.COMMON_FAL_1)
          }
          .height($r('app.float.height_56'))
          .width(CommonConstants.FULL_WIDTH_PERCENT)
        }
        .height(CommonConstants.NINETY_PERCENT)
        .justifyContent(FlexAlign.Center)
      }
    }
    .hideTitleBar(true)
  }
}

/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ListDataConstants } from '../constants/ListDataConstants';
import { CommonConstants } from '../constants/CommonConstants';
import { BreakpointType } from '../utils/BreakpointType';

@Component
export struct DoubleTabAdaptiveCenteringIndex {
  @StorageLink('breakPoint') breakPoint: string = CommonConstants.BREAK_POINT_SM;
  @Consume('pageInfos') pageInfos: NavPathStack;
  @State tabIndexSelected: number = 0;
  @State tabIndexSelected2: number = 0;

  build() {
    NavDestination() {
      Column() {
        Row() {
          Image($r('app.media.icon_back'))
            .width($r('app.float.image_width'))
            .height($r('app.float.image_height'))
            .onClick(() => {
              this.pageInfos.pop();
            })
        }
        .width(CommonConstants.FULL_WIDTH_PERCENT)
        .margin({
          left: $r('app.float.back_margin_left'),
          top: $r('app.float.back_margin_top')
        })
        .justifyContent(FlexAlign.Start)

        Column() {
          Row() {
            Column() {
              List({
                space: new BreakpointType(CommonConstants.DOUBLE_TAB_PADDING_SM, CommonConstants.DOUBLE_TAB_PADDING_MD1,
                  CommonConstants.DOUBLE_TAB_PADDING_LG1).getValue(this.breakPoint)
              }) {
                ForEach(ListDataConstants.STOCK_OPTIONS_LIST1, (item: string, index: number) => {
                  ListItem() {
                    Column() {
                      Text(item)
                        .fontSize($r('app.float.font_size_16'))
                        .fontWeight(CommonConstants.FONT_WEIGHT_500)
                        .fontColor(this.tabIndexSelected === index ? $r('app.color.red') : $r('app.color.black'))
                        .height($r('app.float.text_height'))
                        .width($r('app.float.text_width'))
                        .focusable(true)
                        .groupDefaultFocus(index === 0 ? true : false)
                    }
                  }
                  .margin({ top: $r('app.float.stock_options_margin') })
                  .border({
                    width: {
                      bottom: this.tabIndexSelected === index ?
                      $r('app.float.bottom_width_2') : $r('app.float.bottom_width_0')
                    },
                    color: {
                      bottom: this.tabIndexSelected === index ? $r('app.color.red') : ''
                    },
                    style: {
                      bottom: BorderStyle.Solid
                    }
                  })
                  .onClick(() => {
                    this.tabIndexSelected = index;
                  })
                }, (item: string, index: number) => index + JSON.stringify(item))

                ListItem() {
                  Image($r('app.media.ic_public_more'))
                    .width($r('app.float.image_width'))
                    .height($r('app.float.image_height'))
                }
                .margin({ top: $r('app.float.more_margin_top') })
                .visibility(this.breakPoint === CommonConstants.BREAK_POINT_LG ? Visibility.Visible : Visibility.Hidden)
              }
              .scrollBar(BarState.Off)
              .listDirection(Axis.Horizontal)
            }
            .width($r('app.float.width_296'))
            .height($r('app.float.height_56'))
            .margin({ left: $r('app.float.stock_column_margin') })
            .justifyContent(FlexAlign.Center)
            .alignItems(HorizontalAlign.Center)
            .layoutWeight(CommonConstants.COMMON_FAL_1)

            Image($r('app.media.ic_public_more'))
              .width($r('app.float.image_width'))
              .height($r('app.float.image_height'))
              .margin({
                left: $r('app.float.more_margin_left'),
                right: $r('app.float.more_margin_right')
              })
              .visibility(this.breakPoint === CommonConstants.BREAK_POINT_LG ? Visibility.Hidden : Visibility.Visible)
          }
          .height($r('app.float.height_56'))
          .width(CommonConstants.FULL_WIDTH_PERCENT)

          Row() {
            Column() {
              List({
                space: new BreakpointType(CommonConstants.DOUBLE_TAB_PADDING_SM, CommonConstants.DOUBLE_TAB_PADDING_MD2,
                  CommonConstants.DOUBLE_TAB_PADDING_LG2).getValue(this.breakPoint)
              }) {
                ForEach(ListDataConstants.STOCK_OPTIONS_LIST2, (item: string, index: number) => {
                  ListItem() {
                    Column() {
                      Text(item)
                        .fontSize($r('app.float.font_size_14'))
                        .fontWeight(CommonConstants.FONT_WEIGHT_500)
                        .fontColor(
                          this.tabIndexSelected2 === index ? $r('app.color.selected_text_color') : $r('app.color.black')
                        )
                        .margin({
                          top: $r('app.float.text_margin_top_and_bottom'),
                          bottom: $r('app.float.text_margin_top_and_bottom'),
                          left: $r('app.float.text_margin_left_and_right'),
                          right: $r('app.float.text_margin_left_and_right')
                        })
                        .textAlign(TextAlign.Center)
                        .focusable(true)
                        .groupDefaultFocus(index === 0 ? true : false)
                    }
                  }
                  .backgroundColor(
                    this.tabIndexSelected2 === index ? $r('app.color.selected_text_background') :
                    $r('app.color.text_background')
                  )
                  .border({ radius: CommonConstants.BORDER_RADIUS })
                  .onClick(() => {
                    this.tabIndexSelected2 = index;
                  })
                }, (item: string, index: number) => index + JSON.stringify(item))
              }
              .scrollBar(BarState.Off)
              .listDirection(Axis.Horizontal)
            }
            .width($r('app.float.width_296'))
            .height($r('app.float.height_56'))
            .justifyContent(FlexAlign.Center)
            .alignItems(HorizontalAlign.Center)
            .layoutWeight(CommonConstants.COMMON_FAL_1)
          }
          .height($r('app.float.height_56'))
          .width(CommonConstants.FULL_WIDTH_PERCENT)
        }
        .height(CommonConstants.NINETY_PERCENT)
        .justifyContent(FlexAlign.Center)
      }
    }
    .hideTitleBar(true)
  }
}

/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ListDataConstants } from '../constants/ListDataConstants';
import { CommonConstants } from '../constants/CommonConstants';

@Component
export struct TableAdaptiveExtensionIndex {
  @StorageLink('breakPoint') breakPoint: string = CommonConstants.BREAK_POINT_SM;
  @Consume('pageInfos') pageInfos: NavPathStack;
  @State tabIndexSelected: number = 0;

  @Builder
  Item(item: string, index: number, color: string) {
    Row() {
      Text(item)
        .fontSize($r('app.float.font_size_14'))
        .fontWeight(CommonConstants.FONT_WEIGHT_500)
        .fontColor(color === CommonConstants.GRAY_FONT_FLAG ? (index > 0 ? Color.Gray : Color.Black) :
          ((index === 2 || index === 3) ? Color.Red : Color.Black))
        .height($r('app.float.text_height'))
    }
    .flexShrink(CommonConstants.COMMON_FAL_1)
  }

  build() {
    NavDestination() {
      Column() {
        Row() {
          Image($r('app.media.icon_back'))
            .width($r('app.float.image_width'))
            .height($r('app.float.image_height'))
            .onClick(() => {
              this.pageInfos.pop();
            })
        }
        .width(CommonConstants.FULL_WIDTH_PERCENT)
        .margin({
          left: $r('app.float.back_margin_left'),
          top: $r('app.float.back_margin_top')
        })
        .justifyContent(FlexAlign.Start)

        Row() {
          if (this.breakPoint === CommonConstants.BREAK_POINT_LG) {
            Column() {
              // Left Placeholder Area
            }
            .width(CommonConstants.FIFTY_PERCENT)
            .height(CommonConstants.FULL_WIDTH_PERCENT)
            .border({
              width: { right: 1 },
              color: { right: Color.Gray },
              style: { right: BorderStyle.Solid }
            })
          }
          Column() {
            Row() {
              Column() {
                Row() {
                  ForEach(ListDataConstants.INDICATOR_NAME_LIST, (item: string, index: number) => {
                    Column() {
                      Row() {
                        Text(item)
                          .fontSize($r('app.float.font_size_14'))
                          .fontWeight(CommonConstants.FONT_WEIGHT_500)
                          .fontColor(Color.Black)
                          .height($r('app.float.text_height'))
                        Image(index > 0 ? $r('app.media.ic_public_right') : $r('app.media.ic_public_info'))
                          .width($r('app.float.icon_size'))
                          .height($r('app.float.icon_size'))
                      }

                      if (index > 0) {
                        Text('60**39')
                          .fontSize(CommonConstants.TEXT_FONT_SIZE)
                          .fontWeight(CommonConstants.FONT_WEIGHT_500)
                          .fontColor($r('app.color.text_font_color'))
                          .height($r('app.float.text_height'))
                      }
                    }
                    .flexShrink(CommonConstants.COMMON_FAL_1)
                    .width(index === 0 ? $r('app.float.indicator_name_width') : 'auto')
                    .alignItems(HorizontalAlign.Start)

                    if (index < 3) {
                      Blank()
                    }

                  }, (item: string, index: number) => index + JSON.stringify(item))
                }
                .height($r('app.float.indicator_name_height'))
                .width(CommonConstants.FULL_WIDTH_PERCENT)
                .justifyContent(FlexAlign.SpaceBetween)

                Divider()
                  .color($r('app.color.text_font_color'))

                Row() {
                  Column() {
                    ForEach(ListDataConstants.INDICATOR_NAME_COLUMN, (item: string, index: number) => {
                      this.Item(item, index, CommonConstants.GRAY_FONT_FLAG)
                    }, (item: string, index: number) => index + JSON.stringify(item))
                  }
                  .alignItems(HorizontalAlign.Start)

                  Blank()

                  Column() {
                    ForEach(ListDataConstants.STOCK_INDEX_DATA1, (item: string, index: number) => {
                      this.Item(item, index, CommonConstants.RED_FONT_FLAG)
                    }, (item: string, index: number) => index + JSON.stringify(item))
                  }
                  .width($r('app.float.stock_data_width'))
                  .alignItems(HorizontalAlign.End)

                  Blank()

                  Column() {
                    ForEach(ListDataConstants.STOCK_INDEX_DATA2, (item: string, index: number) => {
                      this.Item(item, index, CommonConstants.RED_FONT_FLAG)
                    }, (item: string, index: number) => index + JSON.stringify(item))
                  }
                  .width($r('app.float.stock_data_width'))
                  .alignItems(HorizontalAlign.End)

                  Blank()

                  Column() {
                    ForEach(ListDataConstants.STOCK_INDEX_DATA3, (item: string, index: number) => {
                      this.Item(item, index, CommonConstants.RED_FONT_FLAG)
                    }, (item: string, index: number) => index + JSON.stringify(item))
                  }
                  .width($r('app.float.stock_data_width'))
                  .alignItems(HorizontalAlign.End)
                }
                .width(CommonConstants.FULL_WIDTH_PERCENT)
                .margin({ top: $r('app.float.indicator_name_margin') })
              }
            }
          }
          .height(CommonConstants.EIGHTY_PERCENT)
          .width(this.breakPoint === CommonConstants.BREAK_POINT_LG ?
          CommonConstants.FIFTY_PERCENT : CommonConstants.FULL_WIDTH_PERCENT)
          .justifyContent(this.breakPoint === CommonConstants.BREAK_POINT_LG ? FlexAlign.End : FlexAlign.Center)
          .padding({
            left: $r('app.float.stock_data_margin'),
            right: $r('app.float.stock_data_margin')
          })
        }
        .width(CommonConstants.FULL_WIDTH_PERCENT)
      }
    }
    .hideTitleBar(true)
  }
}



/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { CommonConstants } from '../constants/CommonConstants';
import { ListDataConstants } from '../constants/ListDataConstants';
import { AdaptiveTabCenteringIndex } from './AdaptiveTabCenteringIndex';
import { TableAdaptiveExtensionIndex } from './TableAdaptiveExtensionIndex';
import { DoubleTabAdaptiveCenteringIndex } from './DoubleTabAdaptiveCenteringIndex';

class DirectoryItem {
  title: ResourceStr = '';
  uri: string = '';
  id: string = '';
}

@Entry
@Component
struct Index {
  @StorageLink('breakPoint') breakPoint: string = CommonConstants.BREAK_POINT_SM;
  @Provide('pageInfos') pageInfos : NavPathStack = new NavPathStack();
  private title: string | Resource = $r('app.string.title');
  private directory: DirectoryItem[] = [
    {
      title: $r('app.string.tab_adaptive'),
      uri: ListDataConstants.TAB_ADAPTIVE_URI,
      id: 'AdaptiveTabCenteringIndex'
    },
    {
      title: $r('app.string.table_adaptive'),
      uri: ListDataConstants.TABLE_ADAPTIVE_URI,
      id: 'TableAdaptiveExtensionIndex'
    },
    {
      title: $r('app.string.double_tab_adaptive'),
      uri: ListDataConstants.DOUBLE_TAB_ADAPTIVE_URI,
      id: 'DoubleTabAdaptiveCenteringIndex'
    }
  ];

  @Builder PageMap(name : string){
    if(name === ListDataConstants.TAB_ADAPTIVE_URI){
      AdaptiveTabCenteringIndex()
    }else if(name === ListDataConstants.TABLE_ADAPTIVE_URI){
      TableAdaptiveExtensionIndex()
    }else{
      DoubleTabAdaptiveCenteringIndex()
    }
  }

  build() {
    GridRow({
      breakpoints: {
        value: CommonConstants.BREAK_POINTS_VALUE,
        reference: BreakpointsReference.WindowSize
      },
      columns: {
        sm: CommonConstants.COLUMN_SM,
        md: CommonConstants.COLUMN_MD,
        lg: CommonConstants.COLUMN_LG
      },
      direction: GridRowDirection.Row
    }) {
      GridCol({
        span: {
          sm: CommonConstants.COLUMN_SM,
          md: CommonConstants.COLUMN_MD,
          lg: CommonConstants.COLUMN_LG
        }
      }) {
        Column() {
          Navigation(this.pageInfos) {
            Column() {
              Text(this.title)

              ForEach(this.directory, (item: DirectoryItem) => {
                Button(item.title)
                  .id(item.id)
                  .fontSize($r('app.float.font_size'))
                  .width(CommonConstants.NINETY_PERCENT)
                  .height($r('app.float.button_height'))
                  .margin($r('app.float.button_margin'))
                  .backgroundColor($r('app.color.button_background'))
                  .onClick(() => {
                    this.pageInfos.pushPath(new NavPathInfo(item.uri,[]));
                  })
              }, (item: DirectoryItem) => JSON.stringify(item))
            }
            .width(CommonConstants.FULL_WIDTH_PERCENT)
          }
          .navDestination(this.PageMap)
          .mode(NavigationMode.Stack)
          .hideBackButton(true)
          .titleMode(NavigationTitleMode.Mini)
          .title(this.title)
        }
      }
    }
  }
}


快应用sample侧重把组件上面的样式,属性,方法写成各个具体用到的写法展示出来给开发者学习,让开发者在真实的应用场景去组合出自己所需要的完整案例,没有给出一个完整工程的真实应用示例

快应用具体的代码展示和图片如下:

<template>
  <div class="doc-page">
    <div class="page-title-wrap">
      <text class="page-title">{{ componentName }}</text>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;</text>
      <div style="flex-direction: row;" @click="clickFunction1('Setting')">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row; flex-wrap:nowrap;</text>
      <div style="flex-direction: row;flex-wrap:nowrap;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row; flex-wrap:wrap;</text>
      <div style="flex-direction: row;flex-wrap:wrap;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row-reverse; flex-wrap:nowrap;</text>
      <div style="flex-direction: row-reverse;flex-wrap:nowrap;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

   <div class="item-container">
      <text class="item-title">flex-direction: row;justify-content: flex-start;</text>
      <div style="justify-content: flex-start;width:80%;background-color:#afeeee;height:300px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;justify-content: flex-end;</text>
      <div style="justify-content: flex-end;width:80%;background-color:#afeeee;height:300px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;justify-content: center;</text>
      <div style="justify-content: center;width:80%;background-color:#afeeee;height:300px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;justify-content:space-between;</text>
      <div style="justify-content:space-between;width:80%;background-color:#afeeee;height:300px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;justify-content: space-around;</text>
      <div style="justify-content: space-around;width:80%;background-color:#afeeee;height:300px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;align-items: stretch;</text>
      <div style="align-items: stretch;width:80%;background-color:#afeeee;height:300px;">
        <text class="color-1">1</text> <text class="color-2">2</text>
        <text class="color-3">3</text>
      </div>
    </div>
  
   <div class="item-container">
      <text class="item-title">flex-direction: row;flex-wrap:wrap;align-content: flex-start;</text>
      <div style="flex-direction: row;flex-wrap:wrap;align-content: flex-start;width:80%;background-color:#afeeee;height:500px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;flex-wrap:wrap;align-content: flex-end;</text>
      <div style="flex-direction: row;flex-wrap:wrap;align-content: flex-end;width:80%;background-color:#afeeee;height:500px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;flex-wrap:wrap;align-content: center;</text>
      <div style="flex-direction: row;flex-wrap:wrap;align-content: center;width:80%;background-color:#afeeee;height:500px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

   <div class="item-container">
      <text class="item-title">flex-direction: row;flex-wrap:wrap;align-content: space-between;</text>
      <div style="flex-direction: row;flex-wrap:wrap;align-content: space-between;width:80%;background-color:#afeeee;height:500px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;flex-wrap:wrap;align-content: space-around;</text>
      <div style="flex-direction: row;flex-wrap:wrap;align-content: space-around;width:80%;background-color:#afeeee;height:500px;">
        <text class="item color-1">1</text> <text class="item color-2">2</text> <text class="item color-3">3</text><text class="item color-1">4</text>
        <text class="item color-2">5</text><text class="item color-3">6</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: row;</text>
      <div style="width:80%;background-color:#afeeee;height:300px;flex-direction: row;">
        <text class="color-1" style="align-self: auto;">align-self: auto;</text> <text class="color-2" style="align-self: stretch;">align-self: stretch;</text>
        <text class="color-3" style="align-self: flex-start;">align-self: flex-start;</text>
        <text class="color-1" style="align-self: flex-end;">align-self: flex-end;</text
        ><text class="color-2" style="align-self: center;">align-self: center;</text>
        <text class="color-3" style="align-self: baseline;">align-self: baseline;</text>
      </div>
    </div>

    <div class="item-container">
      <text class="item-title">flex-direction: column;</text>
      <div style="flex-direction: column; align-items: flex-start;">
        <text class="item color-1">1</text> <text class="item color-2">2</text>
        <text class="item color-3">3</text>
      </div>
    </div>
  </div>
</template>


<style>
@import '../Common/css/common.css';

.item-container {
  margin: 0 50px 50px 50px;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
}

.item-title {
  line-height: 100px;
  background-color: #fbf9fe;
}

.item {
  height: 150px;
  width: 150px;
  text-align: center;
}

.color-1 {
  background-color: #09ba07;
}

.color-2 {
  background-color: #f76160;
}

.color-3 {
  background-color: #0faeff;
}
</style>

<script>
import router from '@system.router'
export default {
  data: {
    componentName: 'div',
  },
  onInit() {
    this.$page.setTitleBar({ text: 'Div' })
  },
  clickFunction1(path) {
    console.log("url", path);
    router.push({
      uri: `/${path}`
    })
  }
}
</script>

2,接口之间的对比

鸿蒙的sample侧重把多个api接口组合在一起应用到真实的开发场景中来,也同时凸显出这个api的大部分属性和方法的在这个示例中的的应用,写出一个相对完整的示例工程展示给到开发者学习。

鸿蒙具体的代码展示和图片如下

/*
 * Copyright 2023. Huawei Technologies Co., Ltd. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

import { router, Prompt } from '@kit.ArkUI';
import { advertising, identifier } from '@kit.AdsKit';
import { common, abilityAccessCtrl } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import HiAdLog from '../log/HiAdLog';
import { ActionBar } from '../widgets/action-bar';
import { CustomButton } from '../widgets/custom-button';
import { RewardAdStatusHandler } from '../event/RewardAdStatusHandler';
import { InterstitialAdStatusHandler } from '../event/InterstitialAdStatusHandler';
import { AdType } from '../constant/AdType';

const TAG = 'Ads Demo-LoadAd';

/**
 * Demo UI of Petal Ads Publisher Service.
 */
@Entry
@Component
export struct LoadAd {
  private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
  private scroller: Scroller = new Scroller();
  private oaid: string = '';
  // Ad display parameters.
  private adDisplayOptions: advertising.AdDisplayOptions = {
    // Whether to mute the ad. By default, the ad is not muted.
    mute: false
  }
  // Ad configuration.
  private adOptions: advertising.AdOptions = {
    // Whether to allow ad asset download through mobile data. 0: no; 1: yes. If this parameter is not set, the advertiser's setting will be used.
    allowMobileTraffic: 0,
    // Whether you want your ad content to be treated as child-directed according to the regulations of COPPA. -1 (default value): uncertain; 0: no; 1: yes.
    tagForChildProtection: -1,
    // Whether you want the ad request to be processed in a way that is suitable for users in the European Economic Area (EEA) who are below the legal age of consent. -1 (default value): uncertain; 0: no; 1: yes.
    tagForUnderAgeOfPromise: -1,
    // Maximum ad content rating. W: aged 3 and up; PI: aged 7 and up, under parental guidance; J: teenagers aged 12 and up; A: adults aged 16 or 18 and up.
    adContentClassification: 'A'
  }
  // Roll ad configuration.
  private adOptionsPlacementAd: advertising.AdOptions = {
    // Set the roll ad display duration.
    totalDuration: 30,
    // Set the roll ad countdown text.
    placementAdCountDownDesc: encodeURI(this.context.resourceManager.getStringSync($r('app.string.ad_free_for_VIP_members')
      .id)),
    // Whether to allow ad asset download through mobile data. 0: no; 1: yes. If this parameter is not set, the advertiser's setting will be used.
    allowMobileTraffic: 0,
    // Whether you want your ad content to be treated as child-directed according to the regulations of COPPA. -1 (default value): uncertain; 0: no; 1: yes.
    tagForChildProtection: -1,
    // Whether you want the ad request to be processed in a way that is suitable for users in the European Economic Area (EEA) who are below the legal age of consent. -1 (default value): uncertain; 0: no; 1: yes.
    tagForUnderAgeOfPromise: -1,
    // Maximum ad content rating. W: aged 3 and up; PI: aged 7 and up, under parental guidance; J: teenagers aged 12 and up; A: adults aged 16 or 18 and up.
    adContentClassification: 'A'
  }
  // Rewarded ad request parameters.
  private rewardAdReqParams: advertising.AdRequestParams = {
    adId: 'testx9dtjwj8hp',
    adType: AdType.REWARD_AD,
    adCount: 1
  }
  // Native video ad request parameters.
  private nativeVideoAdReqParams: advertising.AdRequestParams = {
    adId: 'testy63txaom86',
    adType: AdType.NATIVE_AD,
    adCount: 1,
    // Custom parameters of native ads. A callback is triggered after all ad assets are downloaded.
    enableDirectReturnVideoAd: true
  }
  // Native large-image ad request parameters.
  private nativeBigImageAdReqParams: advertising.AdRequestParams = {
    adId: 'testu7m3hc4gvm',
    adType: AdType.NATIVE_AD,
    adCount: 1,
    // Custom parameters of native ads. A callback is triggered after all ad assets are downloaded.
    enableDirectReturnVideoAd: true
  }
  // Native three-image ad request parameters.
  private nativeThreeImageAdReqParams: advertising.AdRequestParams = {
    adId: 'testr6w14o0hqz',
    adType: AdType.NATIVE_AD,
    adCount: 1,
    // Custom parameters of native ads. A callback is triggered after all ad assets are downloaded.
    enableDirectReturnVideoAd: true
  }
  // Native small-image ad request parameters.
  private nativeSmallImageAdReqParams: advertising.AdRequestParams = {
    adId: 'testb65czjivt9',
    adType: AdType.NATIVE_AD,
    adCount: 1,
    // Custom parameters of native ads. A callback is triggered after all ad assets are downloaded.
    enableDirectReturnVideoAd: true
  }
  // Splash video ad request parameters.
  private splashVideoAdReqParams: advertising.AdRequestParams = {
    adId: 'testd7c5cewoj6',
    adType: AdType.SPLASH_AD,
    adCount: 1
  }
  // Splash image ad request parameters.
  private splashImageAdReqParams: advertising.AdRequestParams = {
    adId: 'testq6zq98hecj',
    adType: AdType.SPLASH_AD,
    adCount: 1
  }
  // Roll ad request parameters.
  private placementAdReqParams: advertising.AdRequestParams = {
    adId: 'testy3cglm3pj0',
    adType: AdType.PLACEMENT_AD,
    adCount: 1
  }
  // Interstitial video ad request parameters.
  private interstitialVideoAdReqParams: advertising.AdRequestParams = {
    adId: 'testb4znbuh3n2',
    adType: AdType.INTERSTITIAL_AD,
    adCount: 1
  }
  // Interstitial image ad request parameters.
  private interstitialImageAdReqParams: advertising.AdRequestParams = {
    adId: 'teste9ih9j0rc3',
    adType: AdType.INTERSTITIAL_AD,
    adCount: 1
  }
  // Banner ad request parameters.
  private bannerAdReqParams: advertising.AdRequestParams = {
    adId: 'testw6vs28auh3',
    adType: AdType.BANNER_AD,
    adCount: 1,
    adWidth: 360,
    adHeight: 57
  }

  aboutToAppear() {
    HiAdLog.i(TAG, 'Start to aboutToAppear');
    try {
      // Obtain the OAID through a promise callback.
      this.requestOAIDTrackingConsentPermissions(this.context);
    } catch (error) {
      HiAdLog.e(TAG, `Catch err, code: ${error.code}, message: ${error.message}`);
    }
  }

  build() {
    Column() {
      ActionBar({ title: $r('app.string.ads_demo_title') }).height('10%')
      Scroll(this.scroller) {
        Column() {
          // Redirect to the rewarded ad display page.
          CustomButton({
            mText: $r('app.string.request_reward_ad_btn'), mOnClick: () => {
              this.requestAd(this.rewardAdReqParams, this.adOptions);
            }
          });

          // Redirect to the native video ad display page.
          CustomButton({
            mText: $r('app.string.request_native_video_ad_btn'), mOnClick: () => {
              this.requestAd(this.nativeVideoAdReqParams, this.adOptions);
            }
          });

          // Redirect to the native large-image ad display page.
          CustomButton({
            mText: $r('app.string.request_native_big_image_ad_btn'), mOnClick: () => {
              this.requestAd(this.nativeBigImageAdReqParams, this.adOptions);
            }
          });

          // Redirect to the native small-image ad display page.
          CustomButton({
            mText: $r('app.string.request_native_small_image_ad_btn'), mOnClick: () => {
              this.requestAd(this.nativeSmallImageAdReqParams, this.adOptions);
            }
          });

          // Redirect to the native three-image ad display page.
          CustomButton({
            mText: $r('app.string.request_native_three_image_ad_btn'), mOnClick: () => {
              this.requestAd(this.nativeThreeImageAdReqParams, this.adOptions);
            }
          });

          // Redirect to the splash video ad display page.
          CustomButton({
            mText: $r('app.string.request_splash_video_ad_btn'), mOnClick: () => {
              this.requestAd(this.splashVideoAdReqParams, this.adOptions);
            }
          });

          // Redirect to the splash image ad display page.
          CustomButton({
            mText: $r('app.string.request_splash_image_ad_btn'), mOnClick: () => {
              this.requestAd(this.splashImageAdReqParams, this.adOptions);
            }
          });

          // Redirect to the roll ad display page.
          CustomButton({
            mText: $r('app.string.request_placement_ad_btn'), mOnClick: () => {
              this.requestAd(this.placementAdReqParams, this.adOptionsPlacementAd as advertising.AdOptions);
            }
          });

          // Redirect to the interstitial video ad display page.
          CustomButton({
            mText: $r('app.string.request_interstitial_video_ad_btn'), mOnClick: () => {
              this.requestAd(this.interstitialVideoAdReqParams, this.adOptions);
            }
          });

          // Redirect to the interstitial image ad display page.
          CustomButton({
            mText: $r('app.string.request_interstitial_image_ad_btn'), mOnClick: () => {
              this.requestAd(this.interstitialImageAdReqParams, this.adOptions);
            }
          });

          // Redirect to the banner ad display page.
          CustomButton({
            mText: $r('app.string.request_banner_ad_btn'), mOnClick: () => {
              routePageWithoutAds('pages/BannerAdPage', this.oaid, this.bannerAdReqParams, this.adDisplayOptions,
                this.adOptions);
            }
          });

        }.width('100%').justifyContent(FlexAlign.Center)
      }.scrollable(ScrollDirection.Vertical)
      .height('90%')
    }
    .width('100%')
    .height('100%')
  }

  private requestAd(adReqParams: advertising.AdRequestParams, adOptions: advertising.AdOptions): void {
    // Set the oaid parameter for AdRequestParams.
    adReqParams.oaid = this.oaid;
    // Ad request callback listener.
    const adLoaderListener: advertising.AdLoadListener = {
      // Called when an ad request fails.
      onAdLoadFailure: (errorCode: number, errorMsg: string) => {
        HiAdLog.e(TAG, `Failed to request ad, errorCode is: ${errorCode}, errorMsg is: ${errorMsg}`);
        Prompt.showToast({
          message: `Failed to request ad, errorCode is:  ${errorCode} , errorMsg is: ${errorMsg}`,
          duration: 1000
        });
      },
      // Called upon ad request success.
      onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
        HiAdLog.i(TAG, 'Succeeded in requesting ad!');
        // Save the requested ad content for display.
        HiAdLog.i(TAG, `ads[0].adType is : ${ads[0].adType}`);
        if (canIUse('SystemCapability.Advertising.Ads')) {
          if (ads[0].adType === AdType.REWARD_AD) {
            // Register a status listener for rewarded ads to monitor their playback status.
            new RewardAdStatusHandler().registerPPSReceiver();
            // Call the API for displaying ads.
            advertising.showAd(ads[0], this.adDisplayOptions, this.context);
          } else if (ads[0].adType === AdType.NATIVE_AD) {
            // Call the native ad display page.
            routePage('pages/NativeAdPage', ads, this.adDisplayOptions);
          } else if (ads[0].adType === AdType.SPLASH_AD) {
            // Call the splash ad display page.
            if (ads[0]?.isFullScreen === true) {
              routePage('pages/SplashFullScreenAdPage', ads, this.adDisplayOptions);
            } else {
              routePage('pages/SplashHalfScreenAdPage', ads, this.adDisplayOptions);
            }
          } else if (ads[0].adType === AdType.PLACEMENT_AD) {
            // Call the roll ad display page.
            routePage('pages/PlacementAdPage', ads, this.adDisplayOptions, this.adOptionsPlacementAd);
          } else if (ads[0].adType === AdType.INTERSTITIAL_AD) {
            // Register a status listener for interstitial ads to monitor their playback status.
            new InterstitialAdStatusHandler().registerPPSReceiver();
            // Call the API for displaying ads.
            advertising.showAd(ads[0], this.adDisplayOptions, this.context);
          } else {
            HiAdLog.w(TAG, 'error adType');
          }
        }
      }
    };
    // Create an AdLoader ad object.
    const load: advertising.AdLoader = new advertising.AdLoader(this.context);
    // Call the API for requesting ads.
    HiAdLog.i(TAG, 'request ad!');
    load.loadAd(adReqParams, adOptions, adLoaderListener);
  }

  private requestOAIDTrackingConsentPermissions(context: common.Context): void {
    // Request Activity tracking for this app from users when they access a page.
    const atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    try {
      atManager.requestPermissionsFromUser(context, ['ohos.permission.APP_TRACKING_CONSENT']).then((data) => {
        if (data.authResults[0] == 0) {
          HiAdLog.i(TAG, 'Succeeded in requesting permission');
          identifier.getOAID().then((data: string) => {
            this.oaid = data;
            HiAdLog.i(TAG, 'Succeeded in getting adsIdentifierInfo by promise');
          }).catch((error: BusinessError) => {
            HiAdLog.e(TAG, `Failed to get adsIdentifierInfo, errorCode: ${error.code}, errorMsg: ${error.message}`);
          })
        } else {
          HiAdLog.i(TAG, 'user rejected');
        }
      }).catch((err: BusinessError) => {
        HiAdLog.e(TAG, `Failed to request permission, errorCode: ${err.code}, errorMsg: ${err.message}`);
      })
    } catch (err) {
      HiAdLog.e(TAG, `catch err, errorCode: ${err.code}, errorMsg: ${err.message}`);
    }
  }
}

async function routePage(pageUri: string, ads: Array<advertising.Advertisement | null>,
  displayOptions: advertising.AdDisplayOptions, adOptions?: advertising.AdOptions) {
  let options: router.RouterOptions = {
    url: pageUri,
    params: {
      ads: ads,
      displayOptions: displayOptions,
      adOptions: adOptions
    }
  }
  try {
    HiAdLog.i(TAG, `routePage  + ${pageUri}`);
    router.pushUrl(options);
  } catch (error) {
    HiAdLog.e(TAG, `Failed to routePage callback, errorCode: ${error.code}, errorMsg: ${error.message}`);
  }
}

async function routePageWithoutAds(pageUri: string, oaid: string, adRequestParams: advertising.AdRequestParams,
  displayOptions: advertising.AdDisplayOptions, adOptions: advertising.AdOptions) {
  // Set the oaid parameter for AdRequestParams.
  adRequestParams.oaid = oaid;
  let options: router.RouterOptions = {
    url: pageUri,
    params: {
      adRequestParams: adRequestParams,
      displayOptions: displayOptions,
      adOptions: adOptions
    }
  }
  try {
    HiAdLog.i(TAG, `routePage  + ${pageUri}`);
    router.pushUrl(options);
  } catch (error) {
    HiAdLog.e(TAG, `Failed to routePage callback, errorCode: ${error.code}, errorMsg: ${error.message}`);
  }
}





/*
 * Copyright 2023. Huawei Technologies Co., Ltd. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

import { router, Prompt } from '@kit.ArkUI';
import { advertising, AutoAdComponent } from '@kit.AdsKit';
import HiAdLog from '../log/HiAdLog';
import { AdStatus } from '../event/AdStatus';

const TAG = 'Ads Demo-BannerAdPage';

@Preview
@Entry
@Component
struct BannerAdPage {
  private adParam: advertising.AdRequestParams | undefined = undefined;
  private adOptions: advertising.AdOptions | undefined = undefined;
  private displayOptions: advertising.AdDisplayOptions | undefined = undefined;
  private ratio: number = 1;
  private adWidth: number = -1;
  private adHeight: number = -1;
  @State visibilityState: Visibility = Visibility.Visible;

  aboutToAppear() {
    HiAdLog.i(TAG, `aboutToAppear`);
    const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    if (params && params.adRequestParams as advertising.AdRequestParams &&
      params.displayOptions as advertising.AdDisplayOptions && params.adOptions as advertising.AdOptions) {
      this.adParam = params.adRequestParams as advertising.AdRequestParams;
      this.displayOptions = params.displayOptions as advertising.AdDisplayOptions;
      this.adOptions = params.adOptions as advertising.AdOptions;
    } else {
      HiAdLog.i(TAG, `empty router params`);
    }

    if (this.adParam?.adWidth && typeof (this.adParam?.adWidth) == 'number' && this.adParam?.adWidth > 0) {
      this.adWidth = this.adParam?.adWidth;
    }
    HiAdLog.i(TAG, `adWidth :${this.adWidth}`);
    if (this.adParam?.adHeight && typeof (this.adParam?.adHeight) == 'number' && this.adParam?.adHeight > 0) {
      this.adHeight = this.adParam?.adHeight;
    }
    HiAdLog.i(TAG, `adHeight :${this.adHeight}`);

    if (this.adWidth > 0 && this.adHeight > 0) {
      this.ratio = this.adWidth / this.adHeight;
    }
  }

  build() {
    Stack({ alignContent: Alignment.Bottom }) {
      this.buildImageView();
      this.buildBannerView();
    }
  }

  @Builder
  buildImageView() {
    Image($r('app.media.banner_background'))
      .objectFit(ImageFit.Cover)
      .onError(() => {
        HiAdLog.e(TAG, `buildImageView image load error`);
      })
      .onComplete(() => {
        HiAdLog.i(TAG, `buildImageView image load complete`);
      })
  }

  @Builder
  buildBannerView() {
    Row() {
      AutoAdComponent({
        adParam: this.adParam,
        adOptions: this.adOptions,
        displayOptions: this.displayOptions,
        interactionListener: {
          onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
            HiAdLog.i(TAG, `status is ${status}`);
            switch (status) {
              case AdStatus.AD_OPEN:
                HiAdLog.i(TAG, `onAdOpen`);
                Prompt.showToast({
                  message: 'banner ad open',
                  duration: 1000
                });
                break;
              case AdStatus.AD_CLICKED:
                HiAdLog.i(TAG, `onAdClick`);
                Prompt.showToast({
                  message: 'banner ad click',
                  duration: 1000
                });
                break;
              case AdStatus.AD_CLOSED:
                HiAdLog.i(TAG, `onAdClose`);
                this.visibilityState = Visibility.None;
                Prompt.showToast({
                  message: 'banner ad close',
                  duration: 1000
                });
                break;
              case AdStatus.AD_LOAD:
                HiAdLog.i(TAG, `onAdLoad`);
                Prompt.showToast({
                  message: 'banner ad load',
                  duration: 1000
                });
                break;
              case AdStatus.AD_FAIL:
                HiAdLog.i(TAG, `onAdFail`);
                this.visibilityState = Visibility.None;
                Prompt.showToast({
                  message: 'banner ad fail',
                  duration: 1000
                });
                break;
            }
          }
        }
      })
    }
    .width('100%')
    .aspectRatio(this.ratio)
    .padding({ bottom: 5 })
    .visibility(this.visibilityState)
  }
}



/*
 * Copyright 2023. Huawei Technologies Co., Ltd. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

import { router, Prompt } from '@kit.ArkUI';
import { advertising, AdComponent } from '@kit.AdsKit';
import { AdStatus } from '../event/AdStatus';
import HiAdLog from '../log/HiAdLog';

const TAG = 'Ads Demo-ShowNativeAd';

@Entry
@Component
export struct ShowNativeAd {
  private ads: Array<advertising.Advertisement> = [];
  private displayOptions?: advertising.AdDisplayOptions;

  aboutToAppear() {
    HiAdLog.i(TAG, `NativeAdPage aboutToAppear`);
    const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    if (params && params.ads as Array<advertising.Advertisement> &&
      params.displayOptions as advertising.AdDisplayOptions) {
      this.ads = params.ads as Array<advertising.Advertisement>;
      this.displayOptions = params.displayOptions as advertising.AdDisplayOptions;
    } else {
      HiAdLog.i(TAG, `empty router params`);
    }
  }

  build() {
    Column() {
      // AdComponent is used to show a native ad.
      AdComponent({
        ads: this.ads, displayOptions: this.displayOptions,
        interactionListener: {
          onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
            switch (status) {
              case AdStatus.AD_OPEN:
                HiAdLog.i(TAG, `onAdOpen`);
                Prompt.showToast({
                  message: 'native ad open',
                  duration: 1000
                });
                break;
              case AdStatus.AD_CLICKED:
                HiAdLog.i(TAG, `onAdClick`);
                Prompt.showToast({
                  message: 'native ad click',
                  duration: 1000
                });
                break;
              case AdStatus.AD_CLOSED:
                HiAdLog.i(TAG, `onAdClose`);
                Prompt.showToast({
                  message: 'native ad close',
                  duration: 1000
                });
                break;
            }
          }
        }
      })
        .width('100%')
        .height('100%')
    }
    .width('100%')
    .height('100%')
  }
}



/*
 * Copyright 2023. Huawei Technologies Co., Ltd. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

import { window, router, Prompt } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { advertising, AdComponent } from '@kit.AdsKit';
import { AdStatus } from '../event/AdStatus';
import HiAdLog from '../log/HiAdLog';

const TAG = 'Ads Demo-PlacementAdPage';


@Entry
@Component
export struct PlacementAdPage {
  private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
  portrait: boolean = true;
  private ads: Array<advertising.Advertisement> = [];
  private displayOptions?: advertising.AdDisplayOptions;
  private adOptions?: advertising.AdOptions;
  // Used to render the countdown in the upper right corner.
  private countDownTxtPlaceholder: string = '%d | %s';
  @State countDownTxt: string = '';

  aboutToAppear() {
    HiAdLog.i(TAG, `PlacementAdPage aboutToAppear`);
    // Set the immersive mode.
    window.getLastWindow(this.context, (err: BusinessError, win) => {
      try {
        win.setSpecificSystemBarEnabled('navigation', false);
        win.setSpecificSystemBarEnabled('navigationIndicator', false);
      } catch (exception) {
        HiAdLog.w(TAG, `setSpecificSystemBarEnabled error`);
      }
    });
    const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    if (params && params.ads as Array<advertising.Advertisement> &&
      params.displayOptions as advertising.AdDisplayOptions) {
      this.ads = params.ads as Array<advertising.Advertisement>;
      this.displayOptions = params.displayOptions as advertising.AdDisplayOptions;
      this.adOptions = params.adOptions as advertising.AdOptions;
      this.initData();
    } else {
      HiAdLog.i(TAG, `empty router params`);
    }
  }

  build() {
    Stack({ alignContent: Alignment.TopEnd }) {
      AdComponent({
        ads: this.ads, displayOptions: this.displayOptions,
        interactionListener: {
          onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
            switch (status) {
              case AdStatus.PORTRAIT:
                HiAdLog.i(TAG, `onPortrait`);
                Prompt.showToast({
                  message: 'placement ad onPortrait',
                  duration: 1000
                });
                this.setWindowPortrait();
                break;
              case AdStatus.LANDSCAPE:
                HiAdLog.i(TAG, `onLandscape`);
                Prompt.showToast({
                  message: 'placement ad onLandscape',
                  duration: 1000
                });
                this.setWindowLandscape();
                break;
              case AdStatus.VIP_CLICKED:
                HiAdLog.i(TAG, `onVipClicked`);
                Prompt.showToast({
                  message: 'placement ad onVipClicked',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_PROGRESS:
                HiAdLog.i(TAG, `onMediaProgress`);
                Prompt.showToast({
                  message: 'placement ad onMediaProgress',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_START:
                HiAdLog.i(TAG, `onMediaStart`);
                Prompt.showToast({
                  message: 'placement ad onMediaStart',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_PAUSE:
                HiAdLog.i(TAG, `onMediaPause`);
                Prompt.showToast({
                  message: 'placement ad onMediaPause',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_STOP:
                HiAdLog.i(TAG, `onMediaStop`);
                Prompt.showToast({
                  message: 'placement ad onMediaStop',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_COMPLETE:
                HiAdLog.i(TAG, `onMediaComplete`);
                Prompt.showToast({
                  message: 'placement ad onMediaComplete',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_ERROR:
                HiAdLog.i(TAG, `onMediaError`);
                Prompt.showToast({
                  message: 'placement ad onMediaError',
                  duration: 1000
                });
                break;
              case AdStatus.MEDIA_COUNTDOWN:
                try {
                  HiAdLog.i(TAG, `onMediaCountdown`);
                  const parseData: Record<string, number> = JSON.parse(JSON.stringify(data));
                  this.updateCountDownTxt(parseData.countdownTime);
                } catch (e) {
                  HiAdLog.e(TAG, `Failed to parse data, errorCode: ${e.code}, errorMsg: ${e.message}`);
                }
                break;
            }
          }
        }
      })
        .width('100%')
        .height('100%')


      Row() {
        if (this.countDownTxt) {
          Row() {
            Text(this.countDownTxt.split('').join('\u200B'))
              .fontSize(12)
              .textAlign(TextAlign.Center)
              .maxLines(1)
              .fontColor(Color.White)
              .lineHeight(12)
              .textOverflow({ overflow: TextOverflow.Ellipsis })
              .maxLines(1)
              .backgroundColor($r('app.color.count_down_background_top'))
              .border({ radius: 25 })
              .padding({
                left: 8,
                right: 8,
                top: 6,
                bottom: 6
              })
              .onClick((event: ClickEvent) => {
                HiAdLog.i(TAG, 'OnVipClicked, do something...');
              })
          }
          .backgroundColor($r('app.color.count_down_background_botton'))
          .margin({ right: 16, top: 16 })
          .height(24)
          .constraintSize({ minWidth: 60, maxWidth: 100 })
          .border({ radius: 25 })
        }
      }
      .alignItems(VerticalAlign.Top)
      .justifyContent(FlexAlign.End)

    }.width('100%').height('100%')
  }

  /**
   * Set the screen to portrait.
   */
  private setWindowPortrait() {
    HiAdLog.i(TAG, `setWindowPortrait, portrait: ${this.portrait}`);
    if (!this.portrait) {
      window.getLastWindow(getContext(this), (err: BusinessError, win) => {
        win.setPreferredOrientation(window.Orientation.PORTRAIT);
      });
      this.portrait = true;
    } else {
      router.back();
    }
  }

  /**
   * Set the screen to landscape (forward).
   */
  private setWindowLandscape() {
    HiAdLog.i(TAG, `setWindowLandscape, portrait: ${this.portrait}`);
    if (this.portrait) {
      window.getLastWindow(getContext(this), (err: BusinessError, win) => {
        win.setPreferredOrientation(window.Orientation.LANDSCAPE);
      });
      this.portrait = false;
    }
  }

  private initData() {
    this.initCountDownText();
  }

  private initCountDownText() {
    const decodeText = this.decodeString(this.adOptions?.placementAdCountDownDesc as string);
    if (!this.isBlank(decodeText)) {
      this.countDownTxtPlaceholder = this.countDownTxtPlaceholder.replace('%s', decodeText);
    } else {
      this.countDownTxtPlaceholder = '%d';
    }
  }

  private updateCountDownTxt(leftTime: number) {
    HiAdLog.i(TAG, `showLeftTime: ${leftTime}`);
    this.countDownTxt = this.countDownTxtPlaceholder.replace('%d', leftTime + '');
  }

  private decodeString(str: string): string {
    if (!str) {
      return str;
    }

    let decodeUrl = str;
    try {
      // Prevent the decoding failure caused by the replacement of spaces with plus signs (+).
      decodeUrl = decodeURIComponent(str.replace(/\+/g, '%20'));
    } catch (e) {
      HiAdLog.e(TAG, `Failed to decodeURIComponent, errorCode: ${e.code}, errorMsg: ${e.message}`);
    }

    return decodeUrl;
  }

  private isBlank(str: string): boolean {
    if (str === null || str === undefined) {
      return true;
    }

    if (typeof str === 'string') {
      return str.trim().length === 0;
    }
    return false;
  }
}



/*
 * Copyright 2023. Huawei Technologies Co., Ltd. All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

import { router, Prompt } from '@kit.ArkUI';
import { advertising, AdComponent } from '@kit.AdsKit';
import { AdStatus } from '../event/AdStatus';
import HiAdLog from '../log/HiAdLog';

const TAG = 'Ads Demo-SplashFullScreenAdPage';

@Entry
@Component
export struct SplashFullScreenAdPage {
  private ads: Array<advertising.Advertisement> = [];
  private displayOptions?: advertising.AdDisplayOptions;

  aboutToAppear() {
    HiAdLog.i(TAG, `SplashFullScreenAdPage aboutToAppear`);
    const params: Record<string, Object> = router.getParams() as Record<string, Object>;
    if (params && params.ads as Array<advertising.Advertisement> &&
      params.displayOptions as advertising.AdDisplayOptions) {
      this.ads = params.ads as Array<advertising.Advertisement>;
      this.displayOptions = params.displayOptions as advertising.AdDisplayOptions;
    } else {
      HiAdLog.i(TAG, `empty router params`);
    }
  }

  build() {
    Column() {
      AdComponent({
        ads: this.ads, displayOptions: this.displayOptions,
        interactionListener: {
          onStatusChanged: (status: string, ad: advertising.Advertisement, data: string) => {
            switch (status) {
              case AdStatus.AD_OPEN:
                HiAdLog.i(TAG, `onAdOpen`);
                Prompt.showToast({
                  message: 'splash ad open',
                  duration: 1000
                });
                break;
              case AdStatus.AD_CLICKED:
                HiAdLog.i(TAG, `onAdClick`);
                Prompt.showToast({
                  message: 'splash ad click',
                  duration: 1000
                });
                break;
              case AdStatus.AD_CLOSED:
                HiAdLog.i(TAG, `onAdClose`);
                Prompt.showToast({
                  message: 'splash ad close',
                  duration: 1000
                });
                router.replaceUrl({
                  url: 'pages/AdsServicePage',
                })
                break;
            }
          }
        }
      })
        .width('100%')
        .height('100%')
    }
    .width('100%')
    .height('100%')
  }
}