用 Flutter 實現 PageView 指示器

本篇用一個PageView的實例來加深印象,而且在以後的專欄裏,咱們會深化這個示例,作成一個支持上下左右無限滑動的圖片Banner,而且教你如何把他作成Dart library而且開放給其餘人使用。 bash

一.無限滑動的PageView

在實現PageView指示器以前,我們須要先實現一個PageView。在Flutter中實現一個PageView很簡單。less

class BannerGalleryWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return BannerGalleryWidgetState();
  }
}

class BannerGalleryWidgetState extends State<BannerGalleryWidget> {
  final PageController controller = PageController(initialPage: 200);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
        height: 250.0,
        child: Container(
          color: Colors.grey,
          child: PageView.builder(
            controller: controller,
            itemBuilder: (context, index) {
              return new Center(
                child: new Text('頁面 ${index}'),
              );
            },
          ),
        ));
  }
}
複製代碼

以上代碼會得出這樣一個界面。稍微解釋一下代碼:ide

/// 指定一個控制器,用來控制PageView的滑動,以及初始位置在第200頁
/// 主要爲了實現「無限循環」
final PageController controller = PageController(initialPage: 200);

/// 一個固定大小的容器,這裏指定了他的高爲250
SizedBox(height: 250.0)
/// 一個容器,用來設定背景顏色爲灰色
Container(color: Colors.grey)
/// 主角PageView,文字居中顯示當前的索引。
PageView.builder(
            controller: controller,
            itemBuilder: (context, index) {
              return new Center(
                child: new Text('頁面 ${index}'),
              );},),
複製代碼

二.實現一個指示器

有了無限滑動的PageView以後,我們再來關聯一個指示器:佈局

class Indicator extends StatelessWidget {
  Indicator({
    this.controller,
    this.itemCount: 0,
  }) : assert(controller != null);

  /// PageView的控制器
  final PageController controller;

  /// 指示器的個數
  final int itemCount;

  /// 普通的顏色
  final Color normalColor = Colors.blue;

  /// 選中的顏色
  final Color selectedColor = Colors.red;

  /// 點的大小
  final double size = 8.0;

  /// 點的間距
  final double spacing = 4.0;

  /// 點的Widget
  Widget _buildIndicator(
      int index, int pageCount, double dotSize, double spacing) {
    // 是不是當前頁面被選中
    bool isCurrentPageSelected = index ==
        (controller.page != null ? controller.page.round() % pageCount : 0);

    return new Container(
      height: size,
      width: size + (2 * spacing),
      child: new Center(
        child: new Material(
          color: isCurrentPageSelected ? selectedColor : normalColor,
          type: MaterialType.circle,
          child: new Container(
            width: dotSize,
            height: dotSize,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: new List<Widget>.generate(itemCount, (int index) {
        return _buildIndicator(index, itemCount, size, spacing);
      }),
    );
  }
}
複製代碼

這段代碼比較簡單,在build()方法裏面構建了一個橫向的List。 List的Item是一個固定大小的圓點,選中是一種顏色,沒有選中是另外一種顏色。ui

三.關聯PageView和指示器

class BannerGalleryWidgetState2 extends State<BannerGalleryWidget2> {
  final PageController controller = PageController(initialPage: 200);

  void _pageChanged(int index) {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SizedBox(
            height: 150.0,
            child: Container(
              color: Colors.grey,
              child: PageView.builder(
                onPageChanged: _pageChanged,
                controller: controller,
                itemBuilder: (context, index) {
                  return new Center(
                    child: new Text('頁面 ${index}'),
                  );
                },
              ),
            )),
        Indicator(
          controller: controller,
          itemCount: 5,
        ),
      ],
    );
  }
}
複製代碼

把佈局容器改一下,用一個列包裹PageView和Indicator,給PageView加一個onPageChanged,檢查當頁面修改的時候setState()刷新UI就行了。this

四.總結 至此,無限滑動的PageView指示器已經完成了,雖然看起來和專欄一開始的示例圖片有點小小的差異,可是至少需求實現了。可是如今這個指示器還比較傻,好比選中以後纔會變色,並且不會放大顯示。在以後的專欄裏我教你們如何完善這個指示器以及提供整個工程的完整代碼,敬請期待。spa

相關文章
相關標籤/搜索