ArkTSにおけるSwiper(カルーセル)コンポーネントの実装ガイド

モバイルアプリケーションのホーム画面におけるバナーや、プロモーション広告、ギャラリー表示などで頻繁に利用されるのが、左右や上下にスライドしてコンテンツを切り替える「カルーセル」UIです。ArkTSでは、これを実現するために標準でSwiperコンポーネントが提供されています。Swiperは、複数の子コンポーネントを保持し、ユーザーのジェスチャーや自動切り替えによって表示を遷移させる強力なコンテナコンポーネントです。

Swiperの基本構成

Swiperはコンテナとして機能するため、その中に配置された各コンポーネントが「1ページ」として扱われます。最もシンプルな実装は以下の通りです。

Swiper() {
  Column() {
    Text('ページ 1')
  }.backgroundColor(0xEDF2F7).width('100%').height(200)

  Column() {
    Text('ページ 2')
  }.backgroundColor(0xE2E8F0).width('100%').height(200)

  Column() {
    Text('ページ 3')
  }.backgroundColor(0xCBD5E0).width('100%').height(200)
}

各ページに一貫したサイズ(幅・高さ)を指定することで、視覚的に整ったスライド効果を得ることができます。

主要なプロパティと動作設定

1. ループ再生設定 (loop)

loopプロパティは、最後のページからスワイプした際に最初のページに戻るかどうかを制御します。

  • true (デフォルト): 無限ループ。シームレスなバナー体験に適しています。
  • false: 終端で停止。チュートリアル画面や特定の順序があるコンテンツに適しています。

2. 表示マージンの調整 (prevMargin / nextMargin)

前後のページを一部だけ表示させたい場合に有効です。これにより、ユーザーに「他にもコンテンツがある」ことを視覚的に伝えることができます。

Swiper() {
  // コンテンツ
}
.prevMargin(24)
.nextMargin(24)
.width('100%')
.height(180)

実践的な活用パターン

標準的な画像バナー

フルワイドの画像を表示する場合、ImageFit.Coverを組み合わせてアスペクト比を維持しつつ領域を埋めるのが一般的です。

@Component
struct BannerView {
  private imgList: string[] = ['img_01', 'img_02', 'img_03']

  build() {
    Swiper() {
      ForEach(this.imgList, (item: string) => {
        Image($r(`app.media.${item}`))
          .objectFit(ImageFit.Cover)
          .width('100%')
          .height('100%')
          .borderRadius(8)
      })
    }
    .autoPlay(true)
    .interval(4000)
    .duration(500)
  }
}

カスタムインジケータの実装

標準のインジケータ(ドット)を非表示にし、独自のデザインやロジックで現在の位置を表示する方法です。

@Entry
@Component
struct CustomSwiper {
  @State activePos: number = 0
  private dataCount: number = 4

  build() {
    Column() {
      Stack({ alignContent: Alignment.Bottom }) {
        Swiper() {
          ForEach([1, 2, 3, 4], (num: number) => {
            Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
              Text(`内容 ${num}`).fontSize(24)
            }
            .backgroundColor(0xF7FAFC)
            .width('100%')
            .height(200)
          })
        }
        .indicator(false) // 標準インジケータを無効化
        .onChange((index: number) => {
          this.activePos = index
        })

        // カスタムドット
        Row({ space: 8 }) {
          ForEach([0, 1, 2, 3], (idx: number) => {
            Circle({ width: 8, height: 8 })
              .fill(this.activePos === idx ? 0x3182CE : 0xE2E8F0)
          })
        }.margin({ bottom: 12 })
      }
    }
  }
}

開発時の注意点とベストプラクティス

1. 高さの決定方法

Swiper自体に高さを指定しない場合、子コンポーネントのサイズに基づいて自動計算されます。しかし、レイアウトのガタつきを防ぐため、バナーなどの用途では原則として固定の高さを定義することを推奨します。

2. ジェスチャーの競合回避

SwiperをScrollコンテナの中に配置する場合、スワイプ操作が競合し、意図した通りにスライドできないことがあります。この場合、スクロール方向の制御や、タッチイベントの優先順位を考慮した設計が必要です。

3. イベントリスナーの活用

onChangeイベントを利用することで、現在のページ番号に基づいたデータの遅延読み込み(プリフェッチ)や、特定のページが表示された際のアナリティクス送信などを実行できます。

まとめ

Swiperは単なるアニメーション部品ではなく、効率的に情報を提示するための「スライド可能なコンテナ」です。ループ設定、マージン調整、そして状態管理(State)との組み合わせを理解することで、ユーザー体験の高いインターフェースを構築できるようになります。

タグ: HarmonyOS ArkTS Swiper UI-design mobile-development

11月4日 11:00 投稿