Вопрос или проблема
вставьте описание изображения здесьНаписание собственных учебных заметок по 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 для управления состоянием. Давайте подробнее рассмотрим, как ваш подход реализован и какие улучшения можно внести.
Ваш код
Ваш код выглядит достаточно хорошо, и структура также правильная. Вот несколько комментариев и улучшений, которые могут помочь вам:
-
Использование
AnimatedPositioned
: Это правильный выбор для создания анимационного эффекта. Вам удалось правильно настроить позицию слайдера в зависимости от выбранного элемента. -
Управление состоянием: Ваш контроллер
HomeController
использует реактивные переменные (obs
), что идеально подходит для использования с GetX. Это позволяет автоматически обновлять пользовательский интерфейс при изменении состояния. -
Метод
_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)),
],
),
);
}
}
Дополнительно
-
Настройка маршрутов: Убедитесь, что ваши маршруты настроены правильно в главном файле приложения, чтобы навигация работала без проблем.
-
Тестирование: После внедрения изменений протестируйте функционал на разных устройствах, чтобы определить, как анимация и навигация работают в реальных условиях.
-
Тема приложения: Поскольку цвета панелей и иконок жестко закодированы, подумайте о том, чтобы использовать темы для управления стилями, чтобы ваше приложение оставалось однородным и легко настраиваемым.
Заключение
Ваше решение по созданию анимационного слайдера для нижней панели выглядит многообещающе. Следуя этим рекомендациям и оптимизациям, вы сможете улучшить его функциональность и производительность. Если у вас есть дальнейшие вопросы или вы ищете альтернативные методы, не стесняйтесь задавать их. Удачи в разработке!