-->

Практическое применение Sliver’ов для создания современного UI

Hola, Amigos! На связи Саша Чаплыгин, Flutter-dev агентства продуктовой разработки Amiga и соавтор телеграм-канала Flutter. Много


Мы уже касались темы Sliver'ов, а сегодня я предлагаю погрузиться в практику. В нашей текущей работе над приложением для сети пекарен, где множество интересных задач и вопросов интерфейса, я активно применяю Sliver'ы и другие виджеты. Давайте рассмотрим, как эти техники могут преобразить создание современного пользовательского интерфейса.

(Silvers на практике)

Используем Stack для эффекта перекрытия карточки. Для этого применяем DraggableScrollableSheet:

Stack(

 children: [

   Padding(

     padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),

     child: CreateProfileCard(state.pageState),

   ),

   DraggableScrollableSheet(

     initialChildSize: 379 / 640,

     minChildSize: 379 / 640,

     maxChildSize: 1,

     builder: (context, scrollController) {

       return Container(

         decoration: BoxDecoration(

           color: AppColors.white,

           borderRadius: const BorderRadius.vertical(top: Radius.circular(30)),

         ),

         padding: const EdgeInsets.fromLTRB(16, 6, 16, 0),

         child: Column(

           children: [

             Padding(

               padding: const EdgeInsets.only(bottom: 15.0),

               child: SvgPicture.asset(AppConstants.icons + 'holder.svg'),

             ),

             Expanded(

               child: CustomScrollView(

                 controller: scrollController,

                 slivers: [...],

               ),

             ),

           ],

         ),

       );

     },

   ),

В DraggableScrollableSheet передаем скролл контроллер в наш CustomScroollView для использования Sliver’ов:

Для таких элементов UI используем SliverToBoxAdapter:

SliverToBoxAdapter(

 child: Padding(

   padding: const EdgeInsets.only(top: 8.0),

   child: MainBanners(state.pageState),

 ),

), // элемент CustomScrollView


class MainBanners extends StatelessWidget {

 const MainBanners(this.pageState, {Key? key}) : super(key: key);


 final MainPageState pageState;


 @override

 Widget build(BuildContext context) {

   return Container(

     height: 120,

     child: Column(

       mainAxisSize: MainAxisSize.min,

       children: [

         Expanded(

           child: CarouselSlider(

             options: CarouselOptions(

               autoPlay: true,

               height: 88,

               viewportFraction: 1.025,

             ),

             items: List.generate(

               5,

               (index) => InkWell(

                 onTap: () {},

                 child: Container(

                   width: MediaQuery.of(context).size.width,

                   margin: const EdgeInsets.symmetric(horizontal: 5),

                   decoration: BoxDecoration(

                       borderRadius: const BorderRadius.all(Radius.circular(16)), color: setColor.elementAt(index)),

                 ),

               ),

             ),

           ),

         ),

         Row(

           mainAxisAlignment: MainAxisAlignment.center,

           children: List.generate(

               5,

               (index) => InkWell(

                     onTap: () {},

                     child: Container(

                       width: 16.0,

                       height: 6.0,

                       margin: const EdgeInsets.symmetric(

                         vertical: 12.0,

                         horizontal: 4.0,

                       ),

                       decoration: BoxDecoration(

                         borderRadius: const BorderRadius.all(Radius.circular(4)),

                         color: Theme.of(context).primaryColor.withOpacity(0.5),

                       ),

                     ),

                   )).toList(),

         ),

       ],

     ),

   );

 }

}

SliverToBoxAdapter(

 child: Padding(

   padding: const EdgeInsets.only(top: 28.0, bottom: 8),

   child: Row(

     mainAxisAlignment: MainAxisAlignment.spaceBetween,

     children: [

       Text(

         'НОВИНКИ',

         style: Theme.of(context)

             .textTheme

             .headlineLarge

             ?.copyWith(color: AppColors.black),

       ),

       Row(

         children: [

           Text(

             'все',

             style: Theme.of(context)

                 .textTheme

                 .bodyLarge

                 ?.copyWith(color: AppColors.black),

           ),

           const SizedBox(width: 4),

           SvgPicture.asset(AppConstants.icons + 'deep_arrow.svg'),

         ],

       ),

     ],

   ),

 ),

),

А для прокручиваемых списков используем SliverList и SliverGrid:

SliverGrid.builder(

 gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(

   crossAxisCount: 2,

   childAspectRatio: 160 / 208,

   crossAxisSpacing: 8,

   mainAxisSpacing: 8,

 ),

 itemCount: 4,

 itemBuilder: (context, index) => Container(

   padding: const EdgeInsets.only(bottom: 8),

   decoration: const BoxDecoration(

     borderRadius: BorderRadius.all(Radius.circular(8)),

     color: AppColors.white,

     boxShadow: [

       BoxShadow(

         color: Color.fromRGBO(0, 0, 0, 0.1),

         blurRadius: 6,

       ),

       BoxShadow(

         color: Color.fromRGBO(0, 0, 0, 0.15),

         blurRadius: 2,

       ),

     ],

   ),

   child: Column(

     children: [

       Container(

         height: 120,

         decoration: const BoxDecoration(

           color: Colors.red,

           borderRadius: BorderRadius.all(Radius.circular(8)),

         ),

       )

     ],

   ),

 ),

),

Slivers во Flutter представляют собой мощный инструмент для создания гибких и эффективных UI. Они позволяют легко реагировать на действия пользователя, работать с большими объемами данных и создавать привлекательные анимированные макеты.

  

Смело используйте Slivers для улучшения UI/UX в ваших приложениях на Flutter, и пользователи скажут вам спасибо!


Подписывайтесь на наш авторский телеграм-канал Flutter. Много, который мы ведем командой мобильных разработчиков. Рассказываем про свой личный опыт и делимся советами от софт-скиллов до технических знаний. Будем рады новым участникам!

Хотите связаться с владельцами компании напрямую?
Константин Франгуриди
Константин Франгуриди
Account director

НАПИСАТЬ

Дмитрий Тарасов
Дмитрий Тарасов
СЕО

НАПИСАТЬ