Flutter筆記(四):PageView-Flutter中的ViewPager

PageView

使用PageView的三種方式

  PageView({
    Key key,
    this.scrollDirection = Axis.horizontal,  //方向
    this.reverse = false,  //是否和閱讀方向一樣的滾動(dòng),比如中文的閱讀習(xí)慣系從左往右
    PageController controller,  //控制器
    this.physics,  //頁面視圖如何響應(yīng)用戶輸入
    this.pageSnapping = true,  //使用自定義滾動(dòng)時(shí)禁止頁面捕捉
    this.onPageChanged,  //頁面切換回調(diào)
    List<Widget> children = const <Widget>[],    //頁面(組件)列表,頁面?zhèn)€數(shù)等于長度
    this.dragStartBehavior = DragStartBehavior.start,  //拖拽行為
  })

后面兩種方式去除重復(fù)數(shù)據(jù)

  PageView.builder({
    //...
    @required IndexedWidgetBuilder itemBuilder,  //創(chuàng)建item,根據(jù)回調(diào)index返回不同頁面
    int itemCount,  //item數(shù)量
    //...
  })

第三種是自定義模式

  PageView.custom({
    //...
    @required this.childrenDelegate,  //自定義模式接受一個(gè)子頁面委托對(duì)象
    //...
  })

這里主要以PageView.builder介紹一下PageView的使用

1、使用

//組件使用
PageView.builder(
  itemBuilder: (context, index) {
  return Center(
    child: _getPageByIndex(index),  //每個(gè)頁面展示的組件
  );
  },
  itemCount: 4, //頁面數(shù)量
  onPageChanged: _onPageChange, //頁面切換
  controller: _pageController, //控制器
)
//返回每個(gè)頁面子組件
StatefulWidget _getPageByIndex(int index) {
  switch (index) {
    case 0:
      return HomePage();
    case 1:
      return CategoryPage();
    case 2:
      return MeiZiPage();
    case 3:
      return AccountPage();
    default:
      return HomePage();
  }
}

2、關(guān)于controller

  PageController({
    this.initialPage = 0,    //初始化選擇頁面
    this.keepPage = true,    //是否保持已經(jīng)渲染過得頁面
    this.viewportFraction = 1.0,  //每個(gè)頁面應(yīng)占用的視口部分。 0~1之間
  })

在是使用PageView的時(shí)候會(huì)包含一個(gè)默認(rèn)的控制器

var _pageController = PageController(initialPage: 0);

控制器跳轉(zhuǎn)有4個(gè)已有的方法

  • animateToPage:帶動(dòng)畫跳轉(zhuǎn)
  • jumpToPage:直接改變當(dāng)前頁面無動(dòng)畫
  • nextPage:下一頁
  • previousPage:上一頁

來先看看jumpToPage的效果

_pageController.jumpToPage(_selectedIndex);
jumpToPage

再看看animateToPage的效果,ps:切換時(shí)間500ms,切換效果Curves.easeInOut

_pageController.animateToPage(_selectedIndex,
          duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
animateToPage

3、PageController的viewportFraction

每個(gè)頁面應(yīng)占用的視口部分。 0~1之間,比如設(shè)置為0.8可以得到以下效果,直接上圖是最好的解釋。再加點(diǎn)自動(dòng)播放,循環(huán)播放之類的就是一個(gè)很nice的banner,但是這里只做demo演示,講解以下這個(gè)屬性,一般在flutter中banner不這樣做,這樣會(huì)有很多問題,比如拖拽時(shí)停止自動(dòng),pageView嵌套等問題。Flutter的概念里一切都是組件,banner組件我推薦輪子flutter_swiper

var _pageController = PageController(initialPage: 1, viewportFraction: 0.8);
viewportFraction: 0.8

4、配合BottomNavigationBar使用

關(guān)于BottomNavigationBar的使用可以參考我之前的
Flutter筆記(一):BottomNavigationBar常見問題
PageView和BottomNavigationBar聯(lián)動(dòng)的完整代碼如下

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;
  var _pageController = PageController(initialPage: 0);

  void _incrementCounter() {
    setState(() {
      _selectedIndex++;
    });
  }

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    if (_pageController.hasClients) {
      _pageController.animateToPage(_selectedIndex,
          duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
//      _pageController.jumpToPage(_selectedIndex);
    }
  }

  void _onPageChange(int index) {
    print("_onPageChange");
    setState(() {
      _selectedIndex = index;
    });
  }

  StatefulWidget _getPageByIndex(int index) {
    switch (index) {
      case 0:
        return HomePage();
      case 1:
        return CategoryPage();
      case 2:
        return MeiZiPage();
      case 3:
        return AccountPage();
      default:
        return HomePage();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
          child: AppBar(
            backgroundColor: Colors.white,
            brightness: Brightness.light,
            title: Center(
              child: Text(
                "FlutterDemo",
              ),
            ),
          ),
          preferredSize: Size(double.infinity, 60)),
      body: PageView.builder(
        itemBuilder: (context, index) {
          return Center(
            child: _getPageByIndex(index),  //每個(gè)頁面展示的組件
          );
        },
        itemCount: 4, //頁面數(shù)量
        onPageChanged: _onPageChange, //頁面切換
        controller: _pageController, //控制器
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
      bottomNavigationBar: new BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconhome), title: new Text("首頁")),
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconcategory), title: new Text("分類")),
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconpic), title: new Text("妹子")),
          BottomNavigationBarItem(
              icon: new Icon(IconFont.iconaccount), title: new Text("我的")),
        ],
        selectedItemColor: Color(0xFF4CAF50),
        unselectedItemColor: Color(0xff666666),
        type: BottomNavigationBarType.fixed,
        showUnselectedLabels: true,
        onTap: _onItemTapped,
        currentIndex: _selectedIndex,
        selectedFontSize: 12.0,
      ),
    );
  }
}

完整代碼

https://github.com/leiyun1993/FlutterDemo-GankIO

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容