Flutter - Скользящий
Slidable в приложении можно использовать для выполнения широкого круга задач, просто проведя пальцем вправо или влево по плитке. Это не только делает пользовательский интерфейс очень удобным для пользователя, но и экономит много времени при выполнении тривиальных задач, которые, если их выполнять другими способами, могут быть беспокойными и избыточными для проектирования. В этой статье мы рассмотрим процесс разработки слайдера для вашего приложения.
Здесь мы создадим простое приложение с плитками, которое при смахивании слева направо архивирует плитку, а при смахивании справа налево удаляет плитку. Для этого выполните следующие действия:
- Добавьте flutter_slidable зависимость к файлу pubspec.yaml.
- Импортировать зависимость в файл main.dart
- Создайте StatelessWidget, чтобы дать приложению структуру
- Используйте StateFulWidget, чтобы добавить домашнюю страницу в приложение
- Используйте SlidableCntroller для настройки действий слайда
- Используйте FloatingActionButton для назначения действий кнопкам, созданным при перемещении плитки
- Используйте WidgetBuilder для создания плиток на домашней странице
Давайте подробно обсудим шаги.
Добавление зависимости:
Вы можете импортировать flutter_slidable зависимости в файле pubspec.yaml , как показано ниже:
Импорт зависимости:
Чтобы импортировать зависимость в файл main.dart, используйте следующее:
import 'package: flutter_slidable / flutter_slidable.dart';
Создание структуры приложения:
Используйте StatelessWidget, чтобы дать приложению простую структуру, как показано ниже:
Дротик
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Slidable ' , theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'GeeksForGeeks' ), ); } } |
Создание домашней страницы:
Используйте StatefulWidget, чтобы настроить домашнюю страницу для приложения, которое в будущем будет содержать плитки, которые можно перемещать в любом направлении для выполнения назначенных им задач, как показано ниже:
Дротик
class MyHomePage extends StatefulWidget { MyHomePage({Key key, this .title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { SlidableController slidableController; final List<_HomeItem> items = List.generate( 20, (i) => _HomeItem( i, 'Slide Bar $i' , _getSubtitle(i), _getAvatarColor(i), ), ); |
Оформление слайдов:
Используйте SlidableController, чтобы настроить слайды для приложения. Это можно сделать с помощью конструктора Slidable или конструктора Slidable.builder . Приложение, которое мы создаем, состоит из 4 основных компонентов:
- Действия со слайдом
- Виджет панели действий слайда
- Соотношение экстента между экстентом действия слайда и экстентом элемента.
- Ребенок
Для создания выдвижной конструкции используйте следующее:
Дротик
Slidable( actionPane: SlidableDrawerActionPane(), actionExtentRatio: 0.25, child: Container( color: Colors.white, child: ListTile( leading: CircleAvatar( backgroundColor: Colors.indigoAccent, child: Text( '$3' ), foregroundColor: Colors.white, ), title: Text( 'Tile $3' ), subtitle: Text( 'SlidableDrawerDelegate' ), ), ), actions: <Widget>[ IconSlideAction( caption: 'Archive' , color: Colors.blue, icon: Icons.archive, onTap: () => _showSnackBar( 'Archive' ), ), IconSlideAction( caption: 'Share' , color: Colors.indigo, icon: Icons.share, onTap: () => _showSnackBar( 'Share' ), ), ], secondaryActions: <Widget>[ IconSlideAction( caption: 'More' , color: Colors.black45, icon: Icons.more_horiz, onTap: () => _showSnackBar( 'More' ), ), IconSlideAction( caption: 'Delete' , color: Colors.red, icon: Icons. delete , onTap: () => _showSnackBar( 'Delete' ), ), ], ); |
Назначение действий:
Когда слайды будут перемещены , появится кнопка FloatingActionButton в зависимости от направления слайда. В обоих случаях каждому смахиванию будут назначены два действия:
- Для слайдов слева направо:
- Архивная плитка
- Поделиться плиткой
- Для слайда справа налево:
- Удалить плитку
- Более
Для простоты мы назначим действия только кнопке «Архивировать плитку» и удалим кнопку плитки, которая будет архивировать и удалять плитку соответственно. Для этого используйте следующее:
Дротик
@ protected void initState() { slidableController = SlidableController( onSlideAnimationChanged: handleSlideAnimationChanged, onSlideIsOpenChanged: handleSlideIsOpenChanged, ); super.initState(); } Animation< double > _rotationAnimation; Color _fabColor = Colors.blue; void handleSlideAnimationChanged(Animation< double > slideAnimation) { setState(() { _rotationAnimation = slideAnimation; }); } void handleSlideIsOpenChanged( bool isOpen) { setState(() { _fabColor = isOpen ? Colors.green : Colors.blue; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), backgroundColor: Colors.green, ), body: Center( child: OrientationBuilder( builder: (context, orientation) => _buildList( context, orientation == Orientation.portrait ? Axis.vertical : Axis.horizontal), ), ), floatingActionButton: FloatingActionButton( backgroundColor: _fabColor, onPressed: null, child: _rotationAnimation == null ? Icon(Icons.add) : RotationTransition( turns: _rotationAnimation, child: Icon(Icons.add), ), ), ); } Widget _buildList(BuildContext context, Axis direction) { return ListView.builder( scrollDirection: direction, itemBuilder: (context, index) { final Axis slidableDirection = direction == Axis.horizontal ? Axis.vertical : Axis.horizontal; var item = items[index]; if (item.index < 8) { return _getSlidableWithLists(context, index, slidableDirection); } else { return _getSlidableWithDelegates(context, index, slidableDirection); } }, itemCount: items.length, ); } Widget _getSlidableWithLists( BuildContext context, int index, Axis direction) { final _HomeItem item = items[index]; return Slidable( key: Key(item.title), controller: slidableController, direction: direction, dismissal: SlidableDismissal( child: SlidableDrawerDismissal(), onDismissed: (actionType) { _showSnackBar( context, actionType == SlideActionType.primary ? 'Dismiss Archive' : 'Dismiss Delete' ); setState(() { items.removeAt(index); }); }, ), actionPane: _getActionPane(item.index), actionExtentRatio: 0.25, child: direction == Axis.horizontal ? VerticalListItem(items[index]) : HorizontalListItem(items[index]), actions: <Widget>[ IconSlideAction( caption: 'Archive' , color: Colors.blue, icon: Icons.archive, onTap: () => _showSnackBar(context, 'Archive' ), ), IconSlideAction( caption: 'Share' , color: Colors.indigo, icon: Icons.share, onTap: () => _showSnackBar(context, 'Share' ), ), ], secondaryActions: <Widget>[ Container( height: 800, color: Colors.green, child: Text( 'a' ), ), IconSlideAction( caption: 'More' , color: Colors.grey.shade200, icon: Icons.more_horiz, onTap: () => _showSnackBar(context, 'More' ), closeOnTap: false , ), IconSlideAction( caption: 'Delete' , color: Colors.red, icon: Icons. delete , onTap: () => _showSnackBar(context, 'Delete' ), ), ], ); } |
Полный исходный код:
Дротик
import 'package:flutter/material.dart' ; import 'package:flutter_slidable/flutter_slidable.dart' ; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Slidable ' , theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'GeeksForGeeks' ), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this .title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { SlidableController slidableController; final List<_HomeItem> items = List.generate( 20, (i) => _HomeItem( i, 'Slide Bar $i' , _getSubtitle(i), _getAvatarColor(i), ), ); @ protected void initState() { slidableController = SlidableController( onSlideAnimationChanged: handleSlideAnimationChanged, onSlideIsOpenChanged: handleSlideIsOpenChanged, ); super.initState(); } Animation< double > _rotationAnimation; Color _fabColor = Colors.blue; void handleSlideAnimationChanged(Animation< double > slideAnimation) { setState(() { _rotationAnimation = slideAnimation; }); } void handleSlideIsOpenChanged( bool isOpen) { setState(() { _fabColor = isOpen ? Colors.green : Colors.blue; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), backgroundColor: Colors.green, ), body: Center( child: OrientationBuilder( builder: (context, orientation) => _buildList( context, orientation == Orientation.portrait ? Axis.vertical : Axis.horizontal), ), ), floatingActionButton: FloatingActionButton( backgroundColor: _fabColor, onPressed: null, child: _rotationAnimation == null ? Icon(Icons.add) : RotationTransition( turns: _rotationAnimation, child: Icon(Icons.add), ), ), ); } Widget _buildList(BuildContext context, Axis direction) { return ListView.builder( scrollDirection: direction, itemBuilder: (context, index) { final Axis slidableDirection = direction == Axis.horizontal ? Axis.vertical : Axis.horizontal; var item = items[index]; if (item.index < 8) { return _getSlidableWithLists(context, index, slidableDirection); } else { return _getSlidableWithDelegates(context, index, slidableDirection); } }, itemCount: items.length, ); } Widget _getSlidableWithLists( BuildContext context, int index, Axis direction) { final _HomeItem item = items[index]; //final int t = index; return Slidable( key: Key(item.title), controller: slidableController, direction: direction, dismissal: SlidableDismissal( child: SlidableDrawerDismissal(), onDismissed: (actionType) { _showSnackBar( context, actionType == SlideActionType.primary ? 'Dismiss Archive' : 'Dismiss Delete' ); setState(() { items.removeAt(index); }); }, ), actionPane: _getActionPane(item.index), actionExtentRatio: 0.25, child: direction == Axis.horizontal ? VerticalListItem(items[index]) : HorizontalListItem(items[index]), actions: <Widget>[ IconSlideAction( caption: 'Archive' , color: Colors.blue, icon: Icons.archive, onTap: () => _showSnackBar(context, 'Archive' ), ), IconSlideAction( caption: 'Share' , color: Colors.indigo, icon: Icons.share, onTap: () => _showSnackBar(context, 'Share' ), ), ], secondaryActions: <Widget>[ Container( height: 800, color: Colors.green, child: Text( 'a' ), ), IconSlideAction( caption: 'More' , color: Colors.grey.shade200, icon: Icons.more_horiz, onTap: () => _showSnackBar(context, 'More' ), closeOnTap: false , ), IconSlideAction( caption: 'Delete' , color: Colors.red, icon: Icons. delete , onTap: () => _showSnackBar(context, 'Delete' ), ), ], ); } Widget _getSlidableWithDelegates( BuildContext context, int index, Axis direction) { final _HomeItem item = items[index]; return Slidable.builder( key: Key(item.title), controller: slidableController, direction: direction, dismissal: SlidableDismissal( child: SlidableDrawerDismissal(), closeOnCanceled: true , onWillDismiss: (item.index != 10) ? null : (actionType) { return showDialog< bool >( context: context, builder: (context) { return AlertDialog( title: Text( 'Delete' ), content: Text( 'Item will be deleted' ), actions: <Widget>[ FlatButton( child: Text( 'Cancel' ), onPressed: () => Navigator.of(context).pop( false ), ), FlatButton( child: Text( 'Ok' ), onPressed: () => Navigator.of(context).pop( true ), РЕКОМЕНДУЕМЫЕ СТАТЬИ |