Đi sâu vào xem trang trong Flutter (Với chuyển tiếp tùy chỉnh)

Khám phá tiện ích PageView và tạo chuyển tiếp trang tùy chỉnh

Bài viết này là bài thứ bảy trong loạt bài viết có cái nhìn sâu sắc về các vật dụng tích hợp trong Flutter.

  1. ListView / ScrollPhysics
  2. Trường văn bản
  3. Các nút nổi
  4. Tiện ích anh hùng
  5. Chuyển đổi widget
  6. Draggable / DragTarget

Trong bài viết này, chúng ta sẽ xem PageView sau đó, tạo một vài hiệu ứng tùy chỉnh cho nó.

LƯU Ý: ListView Deep Dive là tiền thân của bài viết này. Các yếu tố được đề cập trong bài viết đó sẽ không được lặp lại vì chúng gần giống nhau. Bạn có thể đọc bài viết ListView của tôi ở đây

Khám phá các trang xem

PageView là một widget tạo các trang có thể cuộn trên màn hình. Đây có thể là một danh sách cố định của các trang hoặc một hàm xây dựng để xây dựng các trang lặp lại. PageView hoạt động tương tự như ListView theo nghĩa xây dựng các yếu tố.

Các loại PageView là:

  1. Xem trang
  2. Trang Xem.builder
  3. Trang Xem. Tùy chỉnh

PageView (Trình xây dựng mặc định)

Loại này có một danh sách cố định của trẻ em (trang) và làm cho chúng có thể cuộn được.

Xem trang (
  trẻ em:  [
    Thùng đựng hàng(
      màu: Colors.pink,
    ),
    Thùng đựng hàng(
      màu: Colors.cyan,
    ),
    Thùng đựng hàng(
      màu: Colors.deepPurple,
    ),
  ],
)

Đoạn mã trên tạo ra kết quả như sau:

Trang Xem.builder

Hàm tạo này có một hàm itemBuilder và một itemCount tương tự như ListView.builder

PageView.builder (
  itemBuilder: (bối cảnh, vị trí) {
    trả về _buildPage ();
  },
  itemCount: listItemCount, // Có thể là null
)

Giống như ListView.builder, điều này xây dựng trẻ em theo yêu cầu.

Nếu itemCount được đặt thành null (không được đặt), một danh sách các trang vô hạn có thể được tạo.

Ví dụ: mã này:

PageView.builder (
  itemBuilder: (bối cảnh, vị trí) {
    trả lại container (
      màu: vị trí% 2 == 0? Colors.pink: Colors.cyan,
    );
  },
)

Cung cấp một danh sách vô hạn các trang với màu hồng và màu lục lam xen kẽ:

Lưu ý: PageView.custom hoạt động giống như ListView.custom (Đã thảo luận trong Deep Dive trước đó) và chúng tôi sẽ không thảo luận về nó ở đây.

Sự định hướng

Tất cả các loại Chế độ xem trang có thể có các trang cuộn ngang hoặc dọc.

Xem trang (
  trẻ em:  [
    // Thêm trẻ em ở đây
  ],
  scrollDirection: Axis.vertical,
)

Đoạn mã trên cho chúng ta:

Trang

Chụp trang cho phép chúng tôi giữ trang ở giá trị trung gian. Điều này được thực hiện bằng cách tắt thuộc tính pageSnicking. Trong trường hợp này, trang sẽ không cuộn đến vị trí số nguyên và hoạt động như một ListView bình thường.

Xem trang (
  trẻ em:  [
    // Thêm trẻ em ở đây
  ],
  trangSnaps: sai,
)

Vật lý cuộn

Một PageView có thể có hành vi cuộn tùy chỉnh giống như ListViews. Chúng tôi sẽ không lặp lại các loại ScrollPhysics khác nhau vì nó được thảo luận trong ListView Deep Dive.

ScrollPhysics có thể được thay đổi bằng tham số vật lý:

Xem trang (
  trẻ em:  [
    // Thêm trẻ em ở đây
  ],
  vật lý: BouncingScrollPhysics (),
)

Kiểm soát một trang xem

Một PageView có thể được điều khiển bằng lập trình bằng cách đính kèm một Trình điều khiển trang.

// Phương thức xây dựng bên ngoài
Trình điều khiển PageContoder = PageContoder ();
// Phương thức xây dựng bên trong
Xem trang (
  bộ điều khiển: bộ điều khiển,
  trẻ em:  [
    // Thêm con
  ],
)

Vị trí cuộn, trang hiện tại, vv có thể được kiểm tra bằng bộ điều khiển.

Lưu ý: Bộ điều khiển.cienPage trả về giá trị kép. Ví dụ: khi trang đang được vuốt, giá trị sẽ tăng dần từ 1 đến 2 và không ngay lập tức chuyển sang 2.

Thêm chuyển đổi tùy chỉnh vào chế độ xem trang

Hãy cùng thảo luận về việc thêm một vài chuyển đổi tùy chỉnh vào các trang bằng Transform + PageView. Phần này sẽ sử dụng tiện ích Transform rộng rãi và tôi khuyên bạn nên đọc một trong nhiều bài viết trên widget.

Các khuyến nghị của tôi sẽ là Deep Dive tôi đã viết và bài viết WM Leler Wild Transform.

Chuyển 1

Các thiết lập

Trước tiên chúng tôi sử dụng một PageView.builder cơ bản

PageView.builder (
  bộ điều khiển: bộ điều khiển,
  itemBuilder: (bối cảnh, vị trí) {
  },
  mục: 10,
)

Bây giờ, hãy để 10 món đồ.

Chúng tôi sử dụng một Trình kiểm soát trang và một biến chứa giá trị của currentPage.

Xác định PageContoder và các biến:

Trình điều khiển PageContoder = PageContoder ();
var currentPageValue = 0,0;

Cập nhật biến khi PageView được cuộn.

điều khiển.addListener (() {
  setState (() {
    currentPageValue = control.page;
  });
});

Cuối cùng, chúng tôi xây dựng PageView.

Bây giờ, hãy để cạn kiểm tra ba điều kiện:

  1. Nếu trang là trang đang được vuốt từ
  2. Nếu trang là trang đang được vuốt sang
  3. Nếu trang là một trang tắt màn hình
PageView.builder (
  bộ điều khiển: bộ điều khiển,
  itemBuilder: (bối cảnh, vị trí) {
    if (vị trí == currentPageValue.floor ()) {
    } if if (vị trí == currentAnimationValue.floor () + 1) {
      
    } khác {
      
    }
  },
  mục: 10,
)

Bây giờ chúng tôi trả lại cùng một trang nhưng được bọc trong một tiện ích Chuyển đổi để chuyển đổi các trang của chúng tôi khi chúng tôi vuốt nó.

PageView.builder (
  bộ điều khiển: bộ điều khiển,
  itemBuilder: (bối cảnh, vị trí) {
    if (vị trí == currentPageValue.floor ()) {
      trở lại Biến đổi (
        biến đổi: Matrix4.identity () .. rotationX (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } if if (vị trí == currentPageValue.floor () + 1) {
      trở lại Biến đổi (
        biến đổi: Matrix4.identity () .. rotationX (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } khác {
      trả lại container (
        màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
        con: Trung tâm (
          con: Văn bản (
            "Trang",
            kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  mục: 10,
)

Ở đây, chúng tôi chuyển đổi trang đang được vuốt từ và trang được vuốt sang.

currentPageValue.floor () cung cấp cho chúng tôi trang bên trái và

currentPageValue.floor () cung cấp cho chúng tôi trang bên phải

Trong ví dụ này, chúng tôi xoay trang theo hướng X khi nó bị quét bởi một giá trị của currentPageValue trừ chỉ số theo các bức xạ. Bạn có thể khuếch đại hiệu ứng bằng cách nhân giá trị này.

Chúng tôi có thể điều chỉnh biến đổi này và căn chỉnh biến đổi để cung cấp cho chúng tôi nhiều loại chuyển đổi trang mới.

Chuyển 2

Cấu trúc mã tương tự, chỉ với một chuyển đổi khác nhau:

PageView.builder (
  bộ điều khiển: bộ điều khiển,
  itemBuilder: (bối cảnh, vị trí) {
    if (vị trí == currentPageValue.floor ()) {
      trở lại Biến đổi (
        biến đổi: Matrix4.identity () .. rotationY (currentPageValue - vị trí) .. rotationZ (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } if if (vị trí == currentPageValue.floor () + 1) {
      trở lại Biến đổi (
        biến đổi: Matrix4.identity () .. rotationY (currentPageValue - vị trí) .. rotationZ (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } khác {
      trả lại container (
        màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
        con: Trung tâm (
          con: Văn bản (
            "Trang",
            kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  mục: 10,
)

Ở đây, chúng ta xoay quanh cả trục Y và Z.

Chuyển 3

Đây là một loại chuyển tiếp tương tự lần trước nhưng được thêm hiệu ứng 3 chiều.

PageView.builder (
  bộ điều khiển: bộ điều khiển,
  itemBuilder: (bối cảnh, vị trí) {
    if (vị trí == currentPageValue.floor ()) {
      trở lại Biến đổi (
        biến đổi: Matrix4.identity () .. setEntry (3, 2, 0,004) .. rotationY (currentPageValue - vị trí) .. rotationZ (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } if if (vị trí == currentPageValue.floor () + 1) {
      trở lại Biến đổi (
        biến đổi: Matrix4.identity () .. setEntry (3, 2, 0,004) .. rotationY (currentPageValue - vị trí) .. rotationZ (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } khác {
      trả lại container (
        màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
        con: Trung tâm (
          con: Văn bản (
            "Trang",
            kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  mục: 10,
)

Dòng

..setEntry (3, 2, 0,004)

mang lại cho các trang hiệu ứng như 3-D.

Chuyển 4

PageView.builder (
  bộ điều khiển: bộ điều khiển,
  itemBuilder: (bối cảnh, vị trí) {
    if (vị trí == currentPageValue.floor ()) {
      trở lại Biến đổi (
        căn chỉnh: Align.center,
        biến đổi: Matrix4.identity () .. setEntry (3, 2, 0,001)
          ..rotateX (currentPageValue - vị trí)
          ..rotateY (currentPageValue - vị trí)
          ..rotateZ (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } if if (vị trí == currentPageValue.floor () + 1) {
      trở lại Biến đổi (
        căn chỉnh: Align.center,
        biến đổi: Matrix4.identity () .. setEntry (3, 2, 0,001)
          ..rotateX (currentPageValue - vị trí)
          ..rotateY (currentPageValue - vị trí)
          ..rotateZ (currentPageValue - vị trí),
        con: Container (
          màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
          con: Trung tâm (
            con: Văn bản (
              "Trang",
              kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
            ),
          ),
        ),
      );
    } khác {
      trả lại container (
        màu: vị trí% 2 == 0? Colors.blue: Colors.pink,
        con: Trung tâm (
          con: Văn bản (
            "Trang",
            kiểu: TextStyle (màu: Colors.white, fontSize: 22.0),
          ),
        ),
      );
    }
  },
  mục: 10,
)

Nhiều loại hơn có thể được tạo ra bằng cách đơn giản thay đổi góc xoay, trục, sắp xếp và dịch.

Ứng dụng demo sử dụng PageView

Để trình diễn một ứng dụng đơn giản sử dụng PageView trong Flutter, tôi đã tạo một ứng dụng ví dụ để nghiên cứu các từ cho GRE. Ứng dụng này hiển thị và cho phép người dùng lưu các từ khó nhất bằng SQLite để lưu chúng. Nó cũng có Text-To-Speech để phát âm chính từ đó.

Bạn có thể tìm thấy ứng dụng này tại đây: https://github.com/deven98/FlutterGREemme

Điều đó cho nó bài viết này! Tôi hy vọng bạn thích nó, và để lại một vài tiếng vỗ tay nếu bạn đã làm. Theo dõi tôi để biết thêm các bài viết Flutter và bình luận cho bất kỳ phản hồi nào bạn có thể có về bài viết này.

Vui lòng kiểm tra các hồ sơ và bài viết khác của tôi là tốt:

Một số bài viết khác của tôi