Создание слайд-анимации нижней панели в Flutter (MFN)

Вопрос или проблема

вставьте описание изображения здесьНаписание собственных учебных заметок по Flutter: Шаг 1

CWidget — это библиотека, которую я использую. Она выполняет ту же функцию, что и StatelessWidget.

Я искал библиотеку для анимации слайд-бара, но не смог найти ничего подходящего, поэтому решил создать свою собственную. Я использовал GetX и рад видеть, что функциональность слайда работает правильно.

// stl виджет 

class SlideBottomBar extends CWidget {
  SlideBottomBar({super.key});
  final homeController = Get.put(HomeController());

  @override
  Widget build(BuildContext context) {
    // double screenWidth = MediaQuery.of(context).size.width;
    double screenWidth = Get.width;
    // строим ширину кнопок, деля экранную ширину на количество кнопок
    double buttonWidth = (screenWidth / 4) - 17; // (margin + padding) / 2

    return Obx(
      () => CContainer(
        decoration: BoxDecoration(
          color: Colors.grey[900],
          borderRadius: BorderRadius.circular(100),
        ),
        margin: const EdgeInsets.all(24),
        padding: const EdgeInsets.all(10),
        child: Stack(
          children: [
            // Анимация слайда
            AnimatedPositioned(
              duration: const Duration(milliseconds: 100),
              curve: Curves.linear, // без остатка
              left: homeController.sliderPosition * buttonWidth,
              child: CContainer(
                width: buttonWidth,
                height: 40,
                decoration: BoxDecoration(
                  color: Colors.white, // цвет слайдера
                  borderRadius: BorderRadius.circular(100),
                ),
              ),
            ),
            CRow(
              // mainAxisAlignment: MainAxisAlignment.center,
              children: [
                _buildBottomButton(0, Icons.home, "Дом", buttonWidth),
                _buildBottomButton(1, Icons.business, "Бизнес", buttonWidth),
                _buildBottomButton(2, Icons.school, "Школа", buttonWidth),
                _buildBottomButton(3, Icons.person, "Профиль", buttonWidth),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBottomButton(
      int index, IconData icon, String label, double width) {
    return CContainer(
      onTap: () {
        if (homeController.selectedIndex == index) {
          return;
        }
        homeController.selectedIndex = index; // смена выбранного индекса
        homeController.sliderPosition = index; // смена позиции слайдера

        print(index);
        switch (index) {
          case 0:
            Get.toNamed("https://stackoverflow.com/");
            break;
          case 1:
            Get.toNamed('/b');
            break;
          case 2:
            Get.toNamed('/c');
            break;
          case 3:
            Get.toNamed('/d');
            break;
          default:
            print('Неверный индекс');
            break;
        }
      },
      width: width,
      height: 40,
      child: CRow(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(icon, color: Colors.grey),
          homeController.selectedIndex == index
              ? CText(
                  label,
                  textStyle: const TextStyle(color: Colors.grey),
                )
              : Container(),
        ],
      ),
    );
  }
}

: контроллер GetX

class HomeController extends GetxController {
  final _selectedIndex = 0.obs;
  final _sliderPosition = 0.obs;

  get selectedIndex => _selectedIndex.value;
  set selectedIndex(value) => _selectedIndex.value = value;

  get sliderPosition => _sliderPosition.value;
  set sliderPosition(value) => _sliderPosition.value = value;

  PageController pageController = PageController();

  @override
  void dispose() {
    pageController.dispose(); // освобождаем PageController
    super.dispose();
  }
}

Нечего конкретного объяснять словами, но Stack Overflow предлагает писать более длинные посты.

Если у каких-либо разработчиков есть альтернативные методы создания слайд-анимации нижнего бара, пожалуйста, оставьте комментарий к посту. Спасибо!

Ответ или решение

Создание анимации слайдера для нижней панели навигации в Flutter – это увлекательное задание, которое может улучшить пользовательский опыт вашего приложения. В вашем вопросе представлена основа для создания такого решения с использованием библиотеки GetX для управления состоянием. Давайте подробнее рассмотрим, как ваш подход реализован и какие улучшения можно внести.

Ваш код

Ваш код выглядит достаточно хорошо, и структура также правильная. Вот несколько комментариев и улучшений, которые могут помочь вам:

  1. Использование AnimatedPositioned: Это правильный выбор для создания анимационного эффекта. Вам удалось правильно настроить позицию слайдера в зависимости от выбранного элемента.

  2. Управление состоянием: Ваш контроллер HomeController использует реактивные переменные (obs), что идеально подходит для использования с GetX. Это позволяет автоматически обновлять пользовательский интерфейс при изменении состояния.

  3. Метод _buildBottomButton: Вы правильно обрабатываете нажатие кнопок и изменяете состояние, однако, вместо вызова Get.toNamed, что является навигацией, вам следует удостовериться, что соответствующие маршруты соответствуют вашим экранным страницам.

Оптимизация и улучшение кода

Вот небольшие изменения и рекомендации для вашего кода, которые могут сделать его более чистым и эффективным:

Обновленный класс SlideBottomBar

class SlideBottomBar extends CWidget {
  SlideBottomBar({super.key});
  final homeController = Get.put(HomeController());

  @override
  Widget build(BuildContext context) {
    double screenWidth = Get.width;
    double buttonWidth = (screenWidth / 4) - 17;

    return Obx(
      () => CContainer(
        decoration: BoxDecoration(
          color: Colors.grey[900],
          borderRadius: BorderRadius.circular(100),
        ),
        margin: const EdgeInsets.all(24),
        padding: const EdgeInsets.all(10),
        child: Stack(
          children: [
            AnimatedPositioned(
              duration: const Duration(milliseconds: 300),
              curve: Curves.easeInOut,
              left: homeController.sliderPosition * buttonWidth,
              child: CContainer(
                width: buttonWidth,
                height: 40,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(100),
                ),
              ),
            ),
            CRow(
              children: List.generate(4, (index) {
                return _buildBottomButton(index, buttonWidth);
              }),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBottomButton(int index, double width) {
    final iconData = [Icons.home, Icons.business, Icons.school, Icons.person];
    final labels = ["홈", "비즈니스", "학교", "프로필"];

    return CContainer(
      onTap: () {
        if (homeController.selectedIndex == index) return;

        homeController.selectedIndex = index;
        homeController.sliderPosition = index;

        switch (index) {
          case 0:
            Get.toNamed('/home');
            break;
          case 1:
            Get.toNamed('/business');
            break;
          case 2:
            Get.toNamed('/school');
            break;
          case 3:
            Get.toNamed('/profile');
            break;
          default:
            print('Invalid index');
        }
      },
      width: width,
      height: 40,
      child: CRow(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(iconData[index], color: Colors.grey),
          if (homeController.selectedIndex == index)
            CText(labels[index], textStyle: const TextStyle(color: Colors.grey)),
        ],
      ),
    );
  }
}

Дополнительно

  1. Настройка маршрутов: Убедитесь, что ваши маршруты настроены правильно в главном файле приложения, чтобы навигация работала без проблем.

  2. Тестирование: После внедрения изменений протестируйте функционал на разных устройствах, чтобы определить, как анимация и навигация работают в реальных условиях.

  3. Тема приложения: Поскольку цвета панелей и иконок жестко закодированы, подумайте о том, чтобы использовать темы для управления стилями, чтобы ваше приложение оставалось однородным и легко настраиваемым.

Заключение

Ваше решение по созданию анимационного слайдера для нижней панели выглядит многообещающе. Следуя этим рекомендациям и оптимизациям, вы сможете улучшить его функциональность и производительность. Если у вас есть дальнейшие вопросы или вы ищете альтернативные методы, не стесняйтесь задавать их. Удачи в разработке!

Оцените материал
Добавить комментарий

Капча загружается...