FlutterのPageViewの詳細(カスタムトランジションを使用)

PageViewウィジェットの調査とカスタムページ遷移の作成

この記事は、Flutterの組み込みウィジェットについて詳しく説明する一連の記事の7番目です。

  1. ListView / ScrollPhysics
  2. テキストフィールド
  3. FloatingActionButtons
  4. ヒーローウィジェット
  5. 変換ウィジェット
  6. ドラッグ可能/ドラッグターゲット

この記事では、PageViewを見て、後でカスタム効果をいくつか作成します。

注:ListView Deep Diveは、この記事の前身です。その記事で説明されている要素は、ほとんど同じなので繰り返されません。ここで私のリストビューの記事を読むことができます

PageViewsを探索する

PageViewは、画面上にスクロール可能なページを生成するウィジェットです。これは、ページの固定リストか、繰り返しページを作成するビルダー関数のいずれかです。 PageViewは、要素を構築するという意味でListViewと同様に機能します。

PageViewのタイプは次のとおりです。

  1. ページビュー
  2. PageView.builder
  3. PageView.custom

PageView(デフォルトのコンストラクター)

このタイプは、子(ページ)の固定リストを取り、それらをスクロール可能にします。

ページビュー(
  子: [
    容器(
      色:Colors.pink、
    )、
    容器(
      色:Colors.cyan、
    )、
    容器(
      色:Colors.deepPurple、
    )、
  ]、
)

上記のコードは次の結果を生成します。

PageView.builder

このコンストラクターは、itemBuilder関数とListView.builderに似たitemCountを受け取ります

PageView.builder(
  itemBuilder:(コンテキスト、位置){
    return _buildPage();
  }、
  itemCount:listItemCount、// nullも可
)

ListView.builderと同様に、これはオンデマンドで子を構築します。

itemCountがnull(設定されていない)に設定されている場合、ページの無限リストを生成できます。

たとえば、次のコード:

PageView.builder(
  itemBuilder:(コンテキスト、位置){
    コンテナを返します
      色:位置%2 == 0? Colors.pink:Colors.cyan、
    );
  }、
)

ピンクとシアンの色が交互に並んだページの無限リストを提供します。

注:PageView.customはListView.custom(以前のDeep Diveで説明)と同じように機能するため、ここでは説明しません。

オリエンテーション

すべてのタイプのページビューは、水平または垂直にスクロールするページを持つことができます。

ページビュー(
  子: [
    //ここに子を追加します
  ]、
  scrollDirection:Axis.vertical、
)

上記のコードは以下を提供します。

PageSnapping

ページスナップにより、ページを中間の値に保つことができます。これは、pageSnapping属性をオフにすることで実行されます。この場合、ページは整数位置までスクロールせず、通常のListViewのように動作します。

ページビュー(
  子: [
    //ここに子を追加します
  ]、
  pageSnapping:false、
)

ScrollPhysics

PageViewは、ListViewと同じ方法でカスタムスクロール動作を行うことができます。 ListView Deep Diveで説明されているため、異なる種類のScrollPhysicsを繰り返しません。

ScrollPhysicsは、物理パラメータを使用して変更できます。

ページビュー(
  子: [
    //ここに子を追加します
  ]、
  物理学:BouncingScrollPhysics()、
)

PageViewの制御

PageViewは、PageControllerをアタッチすることでプログラムで制御できます。

//外部ビルドメソッド
PageController controller = PageController();
//内部ビルドメソッド
ページビュー(
  コントローラー:コントローラー、
  子: [
    //子を追加します
  ]、
)

スクロール位置、現在のページなどは、コントローラーを使用して確認できます。

注:controller.currentPageはdouble値を返します。たとえば、ページがスワイプされている場合、値は1から2に徐々になり、すぐに2にジャンプしません。

PageViewsへのカスタムトランジションの追加

Transform + PageViewを使用して、ページにいくつかのカスタムトランジションを追加する方法について説明します。このパートでは、変換ウィジェットを広範囲に使用します。ウィジェットに関する複数の記事のいずれかを読むことをお勧めします。

私が推奨するのは、私が書いたディープダイブとWMレラーのトランスフォームの記事です。

移行1

セットアップ

最初に基本的なPageView.builderを使用します

PageView.builder(
  コントローラー:コントローラー、
  itemBuilder:(コンテキスト、位置){
  }、
  itemCount:10、
)

今は10個のアイテムを用意しましょう。

PageControllerと、currentPageの値を保持する変数を使用します。

PageControllerと変数の定義:

PageController controller = PageController();
var currentPageValue = 0.0;

PageViewがスクロールされるときに変数を更新します。

controller.addListener((){
  setState((){
    currentPageValue = controller.page;
  });
});

最後に、PageViewを構築します。

それでは、3つの条件を確認しましょう。

  1. ページがスワイプされているページである場合
  2. ページがスワイプされているページである場合
  3. ページが画面外のページである場合
PageView.builder(
  コントローラー:コントローラー、
  itemBuilder:(コンテキスト、位置){
    if(position == currentPageValue.floor()){
    } else if(position == currentAnimationValue.floor()+ 1){
      
    } else {
      
    }
  }、
  itemCount:10、
)

次に、同じページを返しますが、スワイプするとページを変換するために変換ウィジェットにラップされます。

PageView.builder(
  コントローラー:コントローラー、
  itemBuilder:(コンテキスト、位置){
    if(position == currentPageValue.floor()){
      Transform(
        変換:Matrix4.identity().. rotateX(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else if(position == currentPageValue.floor()+ 1){
      Transform(
        変換:Matrix4.identity().. rotateX(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else {
      コンテナを返します
        色:位置%2 == 0? Colors.blue:Colors.pink、
        子:センター(
          子:テキスト(
            "ページ"、
            スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
          )、
        )、
      );
    }
  }、
  itemCount:10、
)

ここで、スワイプされるページとスワイプされるページを変換します。

currentPageValue.floor()は左側のページを提供し、

currentPageValue.floor()は右側のページを提供します

この例では、currentPageValueの値から放射のインデックスを引いた値でスワイプされるため、ページをX方向に回転させます。この値を掛けることで、効果を増幅できます。

この変換と変換の配置を微調整して、複数のタイプの新しいページ遷移を提供できます。

移行2

変換が異なるだけの同様のコード構造:

PageView.builder(
  コントローラー:コントローラー、
  itemBuilder:(コンテキスト、位置){
    if(position == currentPageValue.floor()){
      Transform(
        変換:Matrix4.identity().. rotateY(currentPageValue-position).. rotateZ(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else if(position == currentPageValue.floor()+ 1){
      Transform(
        変換:Matrix4.identity().. rotateY(currentPageValue-position).. rotateZ(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else {
      コンテナを返します
        色:位置%2 == 0? Colors.blue:Colors.pink、
        子:センター(
          子:テキスト(
            "ページ"、
            スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
          )、
        )、
      );
    }
  }、
  itemCount:10、
)

ここでは、Y軸とZ軸の両方を中心に回転します。

移行3

これは前回同様のタイプの移行ですが、3D効果が追加されています。

PageView.builder(
  コントローラー:コントローラー、
  itemBuilder:(コンテキスト、位置){
    if(position == currentPageValue.floor()){
      Transform(
        変換:Matrix4.identity().. setEntry(3、2、0.004).. rotateY(currentPageValue-position).. rotateZ(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else if(position == currentPageValue.floor()+ 1){
      Transform(
        変換:Matrix4.identity().. setEntry(3、2、0.004).. rotateY(currentPageValue-position).. rotateZ(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else {
      コンテナを返します
        色:位置%2 == 0? Colors.blue:Colors.pink、
        子:センター(
          子:テキスト(
            "ページ"、
            スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
          )、
        )、
      );
    }
  }、
  itemCount:10、
)

この線

..setEntry(3、2、0.004)

ページに3Dのような効果を与えます。

移行4

PageView.builder(
  コントローラー:コントローラー、
  itemBuilder:(コンテキスト、位置){
    if(position == currentPageValue.floor()){
      Transform(
        アライメント:Alignment.center、
        変換:Matrix4.identity().. setEntry(3、2、0.001)
          ..rotateX(currentPageValue-位置)
          ..rotateY(currentPageValue-位置)
          ..rotateZ(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else if(position == currentPageValue.floor()+ 1){
      Transform(
        アライメント:Alignment.center、
        変換:Matrix4.identity().. setEntry(3、2、0.001)
          ..rotateX(currentPageValue-位置)
          ..rotateY(currentPageValue-位置)
          ..rotateZ(currentPageValue-position)、
        子:コンテナ(
          色:位置%2 == 0? Colors.blue:Colors.pink、
          子:センター(
            子:テキスト(
              "ページ"、
              スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
            )、
          )、
        )、
      );
    } else {
      コンテナを返します
        色:位置%2 == 0? Colors.blue:Colors.pink、
        子:センター(
          子:テキスト(
            "ページ"、
            スタイル:TextStyle(色:Colors.white、fontSize:22.0)、
          )、
        )、
      );
    }
  }、
  itemCount:10、
)

回転角度、軸、アライメント、移動を変更するだけで、さらに多くのタイプを作成できます。

PageViewを使用したデモアプリ

FlutterのPageViewを使用した簡単なアプリのデモを行うために、GREの単語を学習するサンプルアプリを作成しました。このアプリは表示され、ユーザーはSQLiteを使用して最も難しい単語を保存して保存できます。また、単語自体を発音するための音声合成もあります。

このアプリはここで見つけることができます:https://github.com/deven98/FlutterGREWords

この記事は以上です!あなたがそれを楽しんだことを願っています、そして、もしあなたがそうするなら、いくつかの拍手を残してください。 Flutterのその他の記事については私をフォローし、この記事についてフィードバックがある場合はコメントしてください。

私の他のプロフィールや記事も自由にチェックしてください。

私の他の記事のいくつか