diff --git a/docs/widget/regular/listview/index.md b/docs/widget/regular/listview/index.md new file mode 100644 index 0000000..af268c8 --- /dev/null +++ b/docs/widget/regular/listview/index.md @@ -0,0 +1 @@ +## **ListView** \ No newline at end of file diff --git a/docs/widget/scrollview/customscrollview/index.md b/docs/widget/scrollview/customscrollview/index.md new file mode 100644 index 0000000..30e47a2 --- /dev/null +++ b/docs/widget/scrollview/customscrollview/index.md @@ -0,0 +1,59 @@ +## **CustomScrollView** + +> 一个使用slivers创建自定义的滚动效果的ScrollView + +### 构造方法 +``` +CustomScrollView({ + Key key, + Axis scrollDirection = Axis.vertical, + bool reverse = false, + ScrollController controller, + bool primary, + ScrollPhysics physics, + bool shrinkWrap = false, + Key center, + double anchor = 0.0, + double cacheExtent, + this.slivers = const [], + int semanticChildCount, + DragStartBehavior dragStartBehavior = DragStartBehavior.start, +}) +``` + +### 属性介绍 +> viewportBuilder:显示滚动组件的属性,实例CustomScrollView/SingleChildScrollView实现不同的滚动效果。 +- CustomScrollView: 实现随滚动条,appbar向上移动效果 +- SingleChildScrollView:参考SingleChildScrollView + +### CustomScrollView +> CustomScrollView:结合slivers使用,常用小组件为SliverAppBar, SliverGrid,SliverFixedExtentList +> SliverAppBar: 滚动标题头小组件 + ```dart + SliverAppBar({ + Key key, + this.leading, + this.automaticallyImplyLeading = true, + this.title, + this.actions, + this.flexibleSpace, + this.bottom, + this.elevation, + this.forceElevated = false, + this.backgroundColor, + this.brightness, + this.iconTheme, + this.textTheme, + this.primary = true, + this.centerTitle, + this.titleSpacing = NavigationToolbar.kMiddleSpacing, + this.expandedHeight, + this.floating = false, + this.pinned = false, + this.snap = false, + }) + + ``` +- pinned: 默认为false, 非滚动至顶部时,标题头始终处于隐藏,当true时,标题头始终显示,但不会显示flexibleSpace内容 +- floating: 默认为false,当为true时,下拉会显示appbar,但不会自动展开flexibleSpace的内容 +- snap: 默认为false,当floating为true, 当前才能为true,向下拉时,会自动显示flexibleSpace的内容 \ No newline at end of file diff --git a/docs/widget/scrollview/listview/index.md b/docs/widget/scrollview/listview/index.md index e69de29..18ac862 100644 --- a/docs/widget/scrollview/listview/index.md +++ b/docs/widget/scrollview/listview/index.md @@ -0,0 +1 @@ +## **ListView** \ No newline at end of file diff --git a/docs/widget/scrollview/scrollable/index.md b/docs/widget/scrollview/scrollable/index.md index 3efaa55..d293af5 100644 --- a/docs/widget/scrollview/scrollable/index.md +++ b/docs/widget/scrollview/scrollable/index.md @@ -1,7 +1,6 @@ -## **GridView** +## **Scrollable** -> -Scrollable是一个可滚动的组件,ListView、GridView都会间接使用到该组件。 +> 实现了可滚动widget的交互模型,但不包含UI显示相关的逻辑 ### 构造方法 ``` @@ -15,4 +14,9 @@ Scrollable({ int semanticChildCount, DragStartBehavior dragStartBehavior: DragStartBehavior.down }) -``` \ No newline at end of file +``` + +### 属性介绍 +> viewportBuilder:显示滚动组件的属性,实例CustomScrollView/SingleChildScrollView实现不同的滚动效果。 +- CustomScrollView: 实现随滚动条,appbar向上移动效果,具体参考CustomScrollView +- SingleChildScrollView:具体参考SingleChildScrollView \ No newline at end of file diff --git a/docs/widget/scrollview/singlechildscrollview/index.md b/docs/widget/scrollview/singlechildscrollview/index.md new file mode 100644 index 0000000..359da31 --- /dev/null +++ b/docs/widget/scrollview/singlechildscrollview/index.md @@ -0,0 +1,43 @@ +## **SingleChildScrollView** +> 当组件内容超出可视范围或高度时,可增加SingleChildScrollView,通过滚动解决问题 + +### 构造函数 + +``` +SingleChildScrollView({ + Key key, + this.scrollDirection = Axis.vertical, + this.reverse = false, + this.padding, + bool primary, + this.physics, + this.controller, + this.child, + this.dragStartBehavior = DragStartBehavior.down, +}); +``` + +### 属性介绍 +> 滚动参数很多同等gridview介绍。 + +### 用例 +> 在固定容器超出屏幕高度则滚动显示 +``` + Container( + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.blue, + ), + ), + height: 100, + child: SingleChildScrollView( + child: Text( + '这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。', + style: TextStyle( + color: Colors.blue, + ), + ), + ), + ) +``` diff --git a/lib/components/widgetComp.dart b/lib/components/widgetComp.dart index 91d1cce..ff08200 100644 --- a/lib/components/widgetComp.dart +++ b/lib/components/widgetComp.dart @@ -91,7 +91,8 @@ class IndexState extends State { }); } - openPage(context, model, String url) async { + openPage(context, model) async { + String url = this.mdUrl; // 加载页面 if (model.config.state.isPro) { FluroRouter.router.navigateTo(context, @@ -124,7 +125,7 @@ class IndexState extends State { Icons.code, ), onPressed: () async { - this.openPage(context, model, this.mdUrl); + this.openPage(context, model); }, ), IconButton( diff --git a/lib/page/component/index.dart b/lib/page/component/index.dart index 355ae61..3d93bc7 100644 --- a/lib/page/component/index.dart +++ b/lib/page/component/index.dart @@ -12,102 +12,105 @@ class Index extends StatefulWidget { _IndexState createState() => _IndexState(model: this.model); } -class _IndexState extends State { +class _IndexState extends State { final MainStateModel model; - List mapList = []; - int index; + List _mapList = []; + int _isExpandedIndex = -1; + _IndexState({Key key, this.model}); @override initState() { super.initState(); - this.mapList = WidgetRoot.getAllWidgets(); + this._mapList = WidgetRoot.getAllWidgets(); } - /** - * 渲染折叠板 - */ - Widget renderExpanel(MainStateModel model, widgetsItem) { + renderPanel(model, widgetsItem, index) { String nameSpaces = widgetsItem.nameSpaces; List _tmpWidgetList = widgetsItem.widgetList; - return Container( - margin: EdgeInsets.only(bottom: 10), - child: ExpansionTile( - title: Text( - widgetsItem.typeName, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - leading: Icon( - IconData( - widgetsItem.code ?? 58353, - fontFamily: 'MaterialIcons', - matchTextDirection: true, + return ExpansionPanel( + headerBuilder: (context, flag) { + return Container( + padding: EdgeInsets.all(10), + child: ListTile( + leading: Icon( + IconData( + widgetsItem.code, + fontFamily: 'MaterialIcons', + matchTextDirection: true, + ), + ), + title: Text('${widgetsItem.typeName}'), ), - // color: Color(AppTheme.mainColor), + ); + }, + body: Container( + decoration: BoxDecoration( + color: Color(AppTheme.thirdColor), ), - backgroundColor: Colors.white, - children: [ - GridView.count( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - childAspectRatio: 1, - crossAxisCount: 3, - children: List.generate( - _tmpWidgetList.length, - (index) { - return Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - width: .1, - ), + padding: EdgeInsets.all(10), + child: GridView.count( + shrinkWrap: true, + physics: ScrollPhysics(), + crossAxisCount: 3, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + children: List.generate(_tmpWidgetList.length, (index) { + return RaisedButton( + color: Color(AppTheme.secondColor), + splashColor: Color(AppTheme.mainColor), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon( + IconData( + _tmpWidgetList[index].code, + fontFamily: 'MaterialIcons', + matchTextDirection: true, ), + color: Color(AppTheme.mainColor), + size: 48, ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - iconSize: 48, - icon: Icon( - IconData( - _tmpWidgetList[index].code ?? 59101, - fontFamily: 'MaterialIcons', - matchTextDirection: true, - ), - color: Color(AppTheme.mainColor), - ), - onPressed: () { - FluroRouter.router.navigateTo( - context, - nameSpaces + _tmpWidgetList[index].title, - ); - }, - ), - Text( - _tmpWidgetList[index].title, - ), - ], - ), + Text( + '${_tmpWidgetList[index].title}', + overflow: TextOverflow.ellipsis, + ) + ], + ), + onPressed: () { + FluroRouter.router.navigateTo( + context, + nameSpaces + _tmpWidgetList[index].title, ); }, - ), - ), - ], + ); + }), + ), ), + isExpanded: _isExpandedIndex == index, ); } Widget build(BuildContext context) { return SingleChildScrollView( physics: BouncingScrollPhysics(), - padding: EdgeInsets.all(10), - child: Column( - children: List.generate(mapList.length, (_index) { - return renderExpanel(model, mapList[_index]); - }), +// padding: EdgeInsets.all(10), + child: ExpansionPanelList( + children: List.generate( + _mapList.length, + (_index) { + return renderPanel(model, _mapList[_index], _index); + }, + ), + expansionCallback: (index, flag) { + if (flag) { + index = -1; + } + setState(() { + this._isExpandedIndex = index; + }); + }, ), ); } diff --git a/lib/page/home.dart b/lib/page/home.dart index 7f545a9..9b8b5ad 100644 --- a/lib/page/home.dart +++ b/lib/page/home.dart @@ -2,20 +2,18 @@ import 'package:flutter/material.dart'; import 'package:efox_flutter/lang/application.dart'; import 'package:efox_flutter/lang/app_translations.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -// -import 'package:efox_flutter/store/store.dart' show Store, MainStateModel; +import 'package:efox_flutter/store/store.dart' show Store; import 'package:efox_flutter/components/header.dart' as Header; import 'component/index.dart' as TabIndex; import 'mine/index.dart' as MyIndex; -import 'package:efox_flutter/config/theme.dart' show AppTheme; class Index extends StatefulWidget { @override _IndexState createState() => new _IndexState(); } -class _IndexState extends State with SingleTickerProviderStateMixin { +class _IndexState extends State { int _currentIndex = 0; PageController _pageController; @@ -31,55 +29,6 @@ class _IndexState extends State with SingleTickerProviderStateMixin { super.dispose(); } - //::TODO 保留到下个版本 考虑去掉 - Widget menu(MainStateModel model) { - return Container( - decoration: BoxDecoration( - border: Border( - top: BorderSide( - width: .1, - color: Color(AppTheme.greyColor), - ), - ), - ), - child: TabBar( - indicator: BoxDecoration( - border: Border( - bottom: BorderSide( - width: .2, - color: Color(AppTheme.mainColor), - ), - ), - ), - labelColor: Color(AppTheme.mainColor), - unselectedLabelColor: Color(AppTheme.greyColor), - indicatorSize: TabBarIndicatorSize.tab, - indicatorColor: Color(AppTheme.secondColor), - labelStyle: TextStyle( - color: Colors.green, - fontWeight: FontWeight.w700, - fontSize: 16, - ), - tabs: [ - Tab( - text: AppTranslations.of(context).t('title_component'), - icon: Icon( - Icons.dashboard, - size: 28, - ), - ), - Tab( - text: AppTranslations.of(context).t('title_my'), - icon: Icon( - Icons.person_outline, - size: 28, - ), - ), - ], - ), - ); - } - Widget _bottomNavigationBar(model) { AppTranslations lang = AppTranslations.of(context); return BottomNavigationBar( @@ -103,7 +52,6 @@ class _IndexState extends State with SingleTickerProviderStateMixin { PopupMenuButton( icon: Icon( Icons.more_vert, - // color: Color(AppTheme.textColor), ), onSelected: (local) { Application().onLocaleChanged(Locale(local)); @@ -138,23 +86,6 @@ class _IndexState extends State with SingleTickerProviderStateMixin { AppTranslations lang = AppTranslations.of(context); return Store.connect( builder: (context, child, model) { - /* return DefaultTabController( - initialIndex: 0, - length: 2, - child: Scaffold( - appBar: AppBar( - title: Header.Index(lang.t('title')), - actions: appBarActions(model), - ), - bottomNavigationBar: menu(model), - body: TabBarView( - children: [ - TabIndex.Index(model: model), - MyIndex.Index(model: model), - ], - ), - ), - ); */ return Scaffold( appBar: AppBar( title: Header.Index(lang.t('title')), diff --git a/lib/widget/regular/index.dart b/lib/widget/regular/index.dart index 583bd7e..afe041d 100644 --- a/lib/widget/regular/index.dart +++ b/lib/widget/regular/index.dart @@ -12,6 +12,7 @@ import 'wrap/index.dart' as Wrap; import 'table/index.dart' as Table; import 'flow/index.dart' as Flow; import 'stack/index.dart' as Stack; +import 'listview/index.dart' as ListView; const nameSpaces = '/regular_'; @@ -80,6 +81,11 @@ List widgets = [ widget: Stack.Index(), code: 57795, // settings_system_daydream title: Stack.Index.title + ), + ItemInfo( + widget: ListView.Index(), + code: 60236, // spa + title: ListView.Index.title ) ]; diff --git a/lib/widget/regular/listview/demo.dart b/lib/widget/regular/listview/demo.dart new file mode 100644 index 0000000..1415c66 --- /dev/null +++ b/lib/widget/regular/listview/demo.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class Index extends StatefulWidget { + @override + _IndexState createState() => _IndexState(); +} + +class _IndexState extends State { + List listview = [ + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c3e1d90c.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c40f3bc2.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c4406144.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c46823f8.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c48c73d0.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c4b4dc2f.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c51a2a45.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-14/5c65107a0ee05.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-14/5c65108043791.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-14/5c651084373de.jpg' + ]; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('ListView'),), + body: ListView( + scrollDirection: Axis.vertical, + children: List.generate(10, (index) { + return ListTile( + title: Text('title $index'), + subtitle: Text('subtitle $index'), + leading: CircleAvatar( + backgroundImage: NetworkImage(listview[index]), + ), + trailing: Icon(Icons.arrow_right), + ); + }), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widget/regular/listview/demo_builder.dart b/lib/widget/regular/listview/demo_builder.dart new file mode 100644 index 0000000..3f55044 --- /dev/null +++ b/lib/widget/regular/listview/demo_builder.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class Index extends StatefulWidget { + @override + _IndexState createState() => _IndexState(); +} + +class _IndexState extends State { + List listview = [ + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c3e1d90c.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c40f3bc2.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c4406144.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c46823f8.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c48c73d0.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c4b4dc2f.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-15/5c664c51a2a45.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-14/5c65107a0ee05.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-14/5c65108043791.jpg', + 'http://pic1.win4000.com/wallpaper/2019-02-14/5c651084373de.jpg' + ]; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('ListView.Builder'),), + body: ListView.builder( + itemCount: listview.length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text('title $index'), + subtitle: Text('subtitle $index'), + leading: CircleAvatar( + backgroundImage: NetworkImage(listview[index]), + ), + trailing: Icon(Icons.arrow_right), + ); + }, + ) + ); + } +} \ No newline at end of file diff --git a/lib/widget/regular/listview/index.dart b/lib/widget/regular/listview/index.dart new file mode 100644 index 0000000..e7f44be --- /dev/null +++ b/lib/widget/regular/listview/index.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:efox_flutter/components/widgetComp.dart' as WidgetComp; +import 'demo.dart' as Demo; +import 'demo_builder.dart' as DemoBuilder; + +class Index extends StatefulWidget { + static String title = 'ListView'; + static String originCodeUrl = ''; + static String mdUrl = 'docs/widget/regular/listview/index.md'; + @override + _IndexState createState() => _IndexState(); +} + +class _IndexState extends State { + @override + Widget build(BuildContext context) { + return WidgetComp.Index( + title: Index.title, + originCodeUrl: Index.originCodeUrl, + mdUrl: Index.mdUrl, + demoChild: [ + Demo.Index(), + DemoBuilder.Index() + ], + ); + } +} \ No newline at end of file diff --git a/lib/widget/scrollview/customscrollview/demo_custom_scrollview.dart b/lib/widget/scrollview/customscrollview/demo_custom_scrollview.dart new file mode 100644 index 0000000..08b29ad --- /dev/null +++ b/lib/widget/scrollview/customscrollview/demo_custom_scrollview.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; + +class Index extends StatefulWidget { + @override + State createState() => _IndexState(); +} + +class _IndexState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scrollable( + axisDirection: AxisDirection.left, + controller: ScrollController(), + viewportBuilder: (context, offset) { + return CustomScrollView( + slivers: [ + SliverAppBar( + snap: false, + // 当floating为true,当前才能为true,向下拉时,会自动显示flexibleSpace的内容 + pinned: false, + // 当pinned为true时,一直显示标题,但不显示flexibleSpace的内容 + expandedHeight: 250.0, + title: Text('this title'), + flexibleSpace: FlexibleSpaceBar( + title: Text( + '这里的标题会随着滚动向上移),', + style: TextStyle(fontSize: 14), + ), + background: Image.network( + 'http://h.hiphotos.baidu.com/image/h%3D300/sign=f0c08716c6fcc3ceabc0cf33a244d6b7/cefc1e178a82b901fd40c8077d8da9773912ef11.jpg', + fit: BoxFit.fill, + ), + ), + floating: false, // 当为true时,会先显示appbar再显示flexibleSpace的内容 + ), + SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 200.0, + mainAxisSpacing: 10.0, + crossAxisSpacing: 10.0, + childAspectRatio: 4.0, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.teal[100 * (index % 9)], + child: Text('grid item $index'), + ); + }, + childCount: 10, + ), + ), + SliverFixedExtentList( + itemExtent: 50.0, + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.lightBlue[100 * (index % 9)], + child: Text('list item $index'), + ); + }, childCount: 10), + ), + ], + ); + }); + } +} diff --git a/lib/widget/scrollview/customscrollview/demo_custom_scrollview_floaing_snap.dart b/lib/widget/scrollview/customscrollview/demo_custom_scrollview_floaing_snap.dart new file mode 100644 index 0000000..d9eb573 --- /dev/null +++ b/lib/widget/scrollview/customscrollview/demo_custom_scrollview_floaing_snap.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class Index extends StatefulWidget { + @override + State createState() => _IndexState(); +} + +class _IndexState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scrollable( + axisDirection: AxisDirection.left, + controller: ScrollController(), + viewportBuilder: (context, offset) { + return CustomScrollView( + slivers: [ + SliverAppBar( + snap: true, // 当floating为true,当前才能为true,向下拉时,会自动显示flexibleSpace的内容 + pinned: false, // 当pinned为true时,一直显示标题,但不显示flexibleSpace的内容 + expandedHeight: 250.0, + title: Text('floating=true, snap=true'), + flexibleSpace: FlexibleSpaceBar( + title: Text( + '下拉时,会直接flexibleSpace的内容', + style: TextStyle(fontSize: 14), + ), + background: Image.network( + 'http://h.hiphotos.baidu.com/image/h%3D300/sign=f0c08716c6fcc3ceabc0cf33a244d6b7/cefc1e178a82b901fd40c8077d8da9773912ef11.jpg', + fit: BoxFit.fill, + ), + ), + floating: true, // 当为true时,会先显示appbar再显示flexibleSpace的内容 + ), + SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 200.0, + mainAxisSpacing: 10.0, + crossAxisSpacing: 10.0, + childAspectRatio: 4.0, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.teal[100 * (index % 9)], + child: Text('grid item $index'), + ); + }, + childCount: 10, + ), + ), + SliverFixedExtentList( + itemExtent: 50.0, + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.lightBlue[100 * (index % 9)], + child: Text('list item $index'), + ); + }, childCount: 10), + ), + ], + ); + }); + } +} diff --git a/lib/widget/scrollview/scrollable/demo_custom_scrollview.dart b/lib/widget/scrollview/customscrollview/demo_custom_scrollview_floating.dart similarity index 56% rename from lib/widget/scrollview/scrollable/demo_custom_scrollview.dart rename to lib/widget/scrollview/customscrollview/demo_custom_scrollview_floating.dart index 139ac7d..9c46069 100644 --- a/lib/widget/scrollview/scrollable/demo_custom_scrollview.dart +++ b/lib/widget/scrollview/customscrollview/demo_custom_scrollview_floating.dart @@ -20,11 +20,21 @@ class _IndexState extends State { return CustomScrollView( slivers: [ SliverAppBar( - pinned: true, + snap: false, // 当floating为true,当前才能为true,向下拉时,会自动显示flexibleSpace的内容 + pinned: false, // 当pinned为true时,一直显示标题,但不显示flexibleSpace的内容 expandedHeight: 250.0, + title: Text('floating=true'), flexibleSpace: FlexibleSpaceBar( - title: Text('这里的标题会随着滚动向移'), + title: Text( + '下拉时,显示标题头', + style: TextStyle(fontSize: 14), + ), + background: Image.network( + 'http://h.hiphotos.baidu.com/image/h%3D300/sign=f0c08716c6fcc3ceabc0cf33a244d6b7/cefc1e178a82b901fd40c8077d8da9773912ef11.jpg', + fit: BoxFit.fill, + ), ), + floating: true, // 当为true时,会先显示appbar再显示flexibleSpace的内容 ), SliverGrid( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( @@ -41,25 +51,22 @@ class _IndexState extends State { child: Text('grid item $index'), ); }, - childCount: 20, + childCount: 10, ), ), SliverFixedExtentList( itemExtent: 50.0, delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return Container( - alignment: Alignment.center, - color: Colors.lightBlue[100 * (index % 9)], - child: Text('list item $index'), - ); - }, - childCount: 20 - ), + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.lightBlue[100 * (index % 9)], + child: Text('list item $index'), + ); + }, childCount: 10), ), ], ); - }, - ); + }); } } diff --git a/lib/widget/scrollview/customscrollview/demo_custom_scrollview_pinned.dart b/lib/widget/scrollview/customscrollview/demo_custom_scrollview_pinned.dart new file mode 100644 index 0000000..b983aec --- /dev/null +++ b/lib/widget/scrollview/customscrollview/demo_custom_scrollview_pinned.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class Index extends StatefulWidget { + @override + State createState() => _IndexState(); +} + +class _IndexState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scrollable( + axisDirection: AxisDirection.left, + controller: ScrollController(), + viewportBuilder: (context, offset) { + return CustomScrollView( + slivers: [ + SliverAppBar( + snap: false, // 当floating为true,当前才能为true,向下拉时,会自动显示flexibleSpace的内容 + pinned: true, // 当pinned为true时,一直显示标题,但不显示flexibleSpace的内容 + expandedHeight: 250.0, + title: Text('pinned=true'), + flexibleSpace: FlexibleSpaceBar( + title: Text( + '当pinned为true时,一直显示标题),', + style: TextStyle(fontSize: 14), + ), + background: Image.network( + 'http://h.hiphotos.baidu.com/image/h%3D300/sign=f0c08716c6fcc3ceabc0cf33a244d6b7/cefc1e178a82b901fd40c8077d8da9773912ef11.jpg', + fit: BoxFit.fill, + ), + ), + floating: false, // 当为true时,会先显示appbar再显示flexibleSpace的内容 + ), + SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 200.0, + mainAxisSpacing: 10.0, + crossAxisSpacing: 10.0, + childAspectRatio: 4.0, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.teal[100 * (index % 9)], + child: Text('grid item $index'), + ); + }, + childCount: 10, + ), + ), + SliverFixedExtentList( + itemExtent: 50.0, + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + color: Colors.lightBlue[100 * (index % 9)], + child: Text('list item $index'), + ); + }, childCount: 10), + ), + ], + ); + }); + } +} diff --git a/lib/widget/scrollview/customscrollview/index.dart b/lib/widget/scrollview/customscrollview/index.dart new file mode 100644 index 0000000..d8768c7 --- /dev/null +++ b/lib/widget/scrollview/customscrollview/index.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:efox_flutter/components/widgetComp.dart' as WidgetComp; +import 'demo_custom_scrollview.dart' as DemoCustomScrollview; +import 'demo_custom_scrollview_pinned.dart' as DemoCustomScrollviewPinned; +import 'demo_custom_scrollview_floating.dart' as DemoCustomScrollviewFloating; +import 'demo_custom_scrollview_floaing_snap.dart' as DemoCustomScrollviewFloatingSnap; + +class Index extends StatefulWidget { + static String title = 'CustomScrollView'; + static String mdUrl = 'docs/widget/scrollview/customscrollview/index.md'; + static String originCodeUrl = 'https://docs.flutter.io/flutter/widgets/Scrollable-class.html'; + + @override + _IndexState createState() => new _IndexState(); +} + +class _IndexState extends State { + @override + Widget build(BuildContext context) { + return WidgetComp.Index( + title: Index.title, + originCodeUrl: Index.originCodeUrl, + mdUrl: Index.mdUrl, + demoChild: [ + DemoCustomScrollview.Index(), + DemoCustomScrollviewPinned.Index(), + DemoCustomScrollviewFloating.Index(), + DemoCustomScrollviewFloatingSnap.Index(), + ] + ); + } +} diff --git a/lib/widget/scrollview/index.dart b/lib/widget/scrollview/index.dart index bd262a9..555123a 100644 --- a/lib/widget/scrollview/index.dart +++ b/lib/widget/scrollview/index.dart @@ -2,13 +2,15 @@ import 'package:efox_flutter/store/objects/widget_info.dart'; import 'gridview/index.dart' as gridview; import 'listview/index.dart' as listview; import 'scrollable/index.dart' as scrollable; +import 'customscrollview/index.dart' as customscrollview; +import 'singlechildscrollview/index.dart' as singlechildscrollview; const nameSpaces = '/scrollview_'; List widgets = [ ItemInfo( widget: gridview.Index(), - code: 59632, // view_module + code: 58348, // grid_on title: gridview.Index.title, ), ItemInfo( @@ -18,8 +20,18 @@ List widgets = [ ), ItemInfo( widget: scrollable.Index(), - code: 59631, // view_list + code: 57920, // format_line_spacing title: scrollable.Index.title, + ), + ItemInfo( + widget: customscrollview.Index(), + code: 57908, // format_align_center + title: customscrollview.Index.title, + ), + ItemInfo( + widget: singlechildscrollview.Index(), + code: 57909, // format_align_justify + title: singlechildscrollview.Index.title, ) ]; diff --git a/lib/widget/scrollview/scrollable/demo.dart b/lib/widget/scrollview/scrollable/demo.dart index 33e543b..9f900eb 100644 --- a/lib/widget/scrollview/scrollable/demo.dart +++ b/lib/widget/scrollview/scrollable/demo.dart @@ -14,25 +14,26 @@ class _IndexState extends State { @override Widget build(BuildContext context) { return Scaffold( + appBar: AppBar( + title: Text('Scrollable实现滚动'), + ), body: Scrollable( + axisDirection: AxisDirection.right, viewportBuilder: (context, offset) { - return Scrollable( - axisDirection: AxisDirection.right, - viewportBuilder: (context, offset) { - return SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.max, - children: List.generate(20, (index) { - return RaisedButton( - child: Text('index $index'), - onPressed: () { - print('$offset'); - }, - ); - }), - ), - ); - }, + return SingleChildScrollView( + child: Column( + children: List.generate( + 20, + (index) { + return RaisedButton( + child: Text('index $index'), + onPressed: () { + print('$offset'); + }, + ); + }, + ).toList(), + ), ); }, ), diff --git a/lib/widget/scrollview/scrollable/index.dart b/lib/widget/scrollview/scrollable/index.dart index ca64a32..cbd81b8 100644 --- a/lib/widget/scrollview/scrollable/index.dart +++ b/lib/widget/scrollview/scrollable/index.dart @@ -15,12 +15,12 @@ class _IndexState extends State { @override Widget build(BuildContext context) { return WidgetComp.Index( - title: Index.title, - originCodeUrl: Index.originCodeUrl, - mdUrl: Index.mdUrl, - demoChild: [ - Demo.Index(), - ] + title: Index.title, + originCodeUrl: Index.originCodeUrl, + mdUrl: Index.mdUrl, + demoChild: [ + Demo.Index(), + ] ); } } diff --git a/lib/widget/scrollview/singlechildscrollview/demo_single_child_scrollview.dart b/lib/widget/scrollview/singlechildscrollview/demo_single_child_scrollview.dart new file mode 100644 index 0000000..e9022a1 --- /dev/null +++ b/lib/widget/scrollview/singlechildscrollview/demo_single_child_scrollview.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +class Index extends StatefulWidget { + @override + State createState() => _IndexState(); +} + +class _IndexState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('SingleChildScrollView'), + ), + body: Column( + children: [ + Divider(), + Container( + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.blue, + ), + ), + height: 100, + child: SingleChildScrollView( + child: Text( + '这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。这里是高度100,增加SingleChildScrollView, 内容超过时可滚动。', + style: TextStyle( + color: Colors.blue, + ), + ), + ), + ), + Divider(), + Container( + decoration: BoxDecoration( + border: Border.all( + width: 1, + color: Colors.blue, + ), + ), + height: 100, + child: Text( + '这里是高度100,没有滚动时,内容会超过100边界,这里是高度100,没有滚动时,内容会超过100边界,这里是高度100,没有滚动时,内容会超过100边界,这里是高度100,没有滚动时,内容会超过100边界,这里是高度100,没有滚动时,内容会超过100边界', + ), + ), + ], + ), + ); + } +} diff --git a/lib/widget/scrollview/singlechildscrollview/demo_single_child_scrollview_overflow.dart b/lib/widget/scrollview/singlechildscrollview/demo_single_child_scrollview_overflow.dart new file mode 100644 index 0000000..420211a --- /dev/null +++ b/lib/widget/scrollview/singlechildscrollview/demo_single_child_scrollview_overflow.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; + +class Index extends StatefulWidget { + @override + State createState() => _IndexState(); +} + +class _IndexState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('SingleChildScrollView'), + ), + body: LayoutBuilder( + builder: (BuildContext context, BoxConstraints viewportConstraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: 300, +// minHeight: viewportConstraints.maxHeight, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + // A fixed-height child. + color: Colors.yellow, + height: 80.0, + width: viewportConstraints.maxWidth, + child: Text('外层定义一个ConstrainedBox,最小高度300。也可以通过LayoutBuilder拿到最大的宽高来定义滚动区域',), + ), + Container( + // Another fixed-height child. + color: Colors.green, + height: 80.0, + width: viewportConstraints.maxWidth, + child: Text('Container根据自定义的高度,加上MainAxisAlignment.spaceAround平均分布在300高的容器中。',), + ), + Container( + // Another fixed-height child. + color: Colors.blue, + height: 80.0, + width: viewportConstraints.maxWidth, + child: Text('当内容多时,会自动滚动',), + ), + Container( + // Another fixed-height child. + color: Colors.purple, + height: 80.0, + width: viewportConstraints.maxWidth, + child: Text('Container根据自定义的高度,加上MainAxisAlignment.spaceAround平均分布在300高的容器中。',), + ), + Container( + // Another fixed-height child. + color: Colors.indigo, + height: 80.0, + width: viewportConstraints.maxWidth, + child: Text('当内容多时,会自动滚动',), + ), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/widget/scrollview/singlechildscrollview/index.dart b/lib/widget/scrollview/singlechildscrollview/index.dart new file mode 100644 index 0000000..89b5d3d --- /dev/null +++ b/lib/widget/scrollview/singlechildscrollview/index.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:efox_flutter/components/widgetComp.dart' as WidgetComp; +import 'demo_single_child_scrollview.dart' as DemoSingleChildScrollview; +import 'demo_single_child_scrollview_overflow.dart' as DemoSingleChildScrollviewOverflow; + +class Index extends StatefulWidget { + static String title = 'SingleChildScrollview'; + static String mdUrl = 'docs/widget/scrollview/singlechildscrollview/index.md'; + static String originCodeUrl = 'https://docs.flutter.io/flutter/widgets/SingleChildScrollView-class.html'; + + @override + _IndexState createState() => new _IndexState(); +} + +class _IndexState extends State { + @override + Widget build(BuildContext context) { + return WidgetComp.Index( + title: Index.title, + originCodeUrl: Index.originCodeUrl, + mdUrl: Index.mdUrl, + demoChild: [ + DemoSingleChildScrollview.Index(), + DemoSingleChildScrollviewOverflow.Index(), + ] + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 490cd9f..72bb066 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,7 +58,10 @@ flutter: assets: - locale/ - docs/widget/scrollview/gridview/ + - docs/widget/scrollview/listview/ - docs/widget/scrollview/scrollable/ + - docs/widget/scrollview/customscrollview/ + - docs/widget/scrollview/singlechildscrollview/ - docs/widget/regular/row/ - docs/widget/regular/column/ - docs/widget/regular/container/ @@ -72,6 +75,7 @@ flutter: - docs/widget/regular/table/ - docs/widget/regular/flow/ - docs/widget/regular/stack/ + - docs/widget/regular/listview/ - docs/widget/navigator/appbar/ - docs/widget/navigator/scaffold/ # An image asset can refer to one or more resolution-specific "variants", see