Итак, я поискал в нескольких местах, как это должно быть реализовано, и я уверен, что упускаю что-то тривиальное, но у меня есть приложение flutter с Scaffold, тело которого является PageView. Мне нужно иметь другой FAB для некоторых страниц, и в настоящее время он настроен для атрибута floatingActionButton скаффолда, настроенного для доступа к массиву FloatingActionButtons с индексом _currentPageIndex (закрытая переменная, совместно используемая bottomNavBar и _pageController.
Это резко меняет FAB, что не является желаемым поведением.
Я пытаюсь заставить FAB анимировать (масштабировать и масштабировать), когда страница изменяется, как в спецификация материала:
Tabbed Screens When tabs are present, the FAB should briefly disappear, then >reappear when the new content moves into place. This expresses >that the FAB is not connected to any particular tab.
Я был бы признателен за любой совет о том, как реализовать его просто (я почти уверен, что упускаю что-то тривиальное). Альтернатива - вручную анимировать FAB-файлы вручную, завернув их во что-нибудь.
Вы можете попробовать использовать виджет AnimatedCrossFade примерно так:
class TestingNewWidgetState extends State<TestingNewWidget> {
int currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: AnimatedCrossFade(
crossFadeState: currentIndex == 0
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: Duration(seconds: 1),
firstChild: FloatingActionButton(
onPressed: () => null,
child: Icon(Icons.arrow_left),
backgroundColor: Colors.red,
),
secondChild: FloatingActionButton(
onPressed: () => null,
child: Icon(Icons.arrow_right),
backgroundColor: Colors.blue,
),
),
body: PageView(
onPageChanged: (index) {
setState(() {
currentIndex = index;
});
},
children: <Widget>[
Scaffold(
body: Center(
child: Text("page 1"),
),
),
Scaffold(
body: Center(
child: Text("page 2"),
),
),
],
),
);
}
}
ОБНОВИТЬ
Помните, что вы можете создать свой собственный виджет, это пример использования настраиваемого FloatingActionButton:
class TestingNewWidgetState extends State<TestingNewWidget> {
int currentIndex = 0;
@override
Widget build(BuildContext context) {
var customFabButton;
if (currentIndex == 0) {
customFabButton = CustomFabButton(
color: Colors.red,
onPressed: () => null,
icon: Icons.alarm,
);
} else if (currentIndex == 1) {
customFabButton = CustomFabButton(
color: Colors.blue,
onPressed: () => null,
icon: Icons.satellite,
);
} else {
customFabButton = CustomFabButton(
color: Colors.green,
onPressed: () => null,
icon: Icons.verified_user,
);
}
return Scaffold(
floatingActionButton: customFabButton,
body: PageView(
onPageChanged: (index) {
setState(() {
currentIndex = index;
});
},
children: <Widget>[
Scaffold(
body: Center(
child: Text("page 1"),
),
),
Scaffold(
body: Center(
child: Text("page 2"),
),
),
Scaffold(
body: Center(
child: Text("page 3"),
),
),
],
),
);
}
}
class CustomFabButton extends StatelessWidget {
final IconData icon;
final Color color;
final VoidCallback onPressed;
const CustomFabButton({Key key, this.icon, this.color, this.onPressed})
: super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onPressed,
child: AnimatedContainer(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color,
),
duration: Duration(seconds: 1),
height: 50.0,
width: 50.0,
child: Icon(icon),
),
);
}
}
Это будет между двумя FAB, но у меня есть 5 страниц, на 3 из которых есть FAB. Я мог бы переключить первого и второго потомков в зависимости от состояния, чтобы решить эту проблему, но я чувствую, что должно быть более простое решение, работающее по умолчанию. Может быть, мне нужно установить какое-то свойство на внешнем каркасе?