gpt4 book ai didi

Flutter - 从页面修改 AppBar

转载 作者:IT王子 更新时间:2023-10-29 06:59:33 25 4
gpt4 key购买 nike

所以我有一个包含多个页面的 Flutter 应用程序,这是通过 PageView 完成的。在此页面 View 之前,我创建了我的 AppBar,因此它始终位于应用程序的顶部,并且在页面之间滚动时不会显示动画。然后我想在其中一个页面上创建一个底部应用栏,但为此我需要访问应用栏元素,但我不知道如何执行此操作。

这是主类,我试图在其上编辑应用栏的页面是 PlanPage

final GoogleSignIn googleSignIn = GoogleSignIn();
final FirebaseAuth auth = FirebaseAuth.instance;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '',
home: _handleCurrentScreen()
);
}

Widget _handleCurrentScreen() {
return StreamBuilder<FirebaseUser>(
stream: auth.onAuthStateChanged,
builder: (BuildContext context, snapshot) {
print(snapshot);
if (snapshot.connectionState == ConnectionState.waiting) {
return SplashPage();
} else {
if (snapshot.hasData) {
return Home();
}
return LoginPage();
}
}
);
}
}

class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomeState();
}
}

class HomeState extends State<Home> {
PageController _pageController;

PreferredSizeWidget bottomBar;

int _page = 0;


@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: bottomBar,
),
body: PageView(
children: [
Container(
child: SafeArea(
child: RecipesPage()
),
),
Container(
child: SafeArea(
child: PlanPage()
),
),
Container(
child: SafeArea(
child: ShoppingListPage()
),
),
Container(
child: SafeArea(
child: ExplorePage()
),
),
],

/// Specify the page controller
controller: _pageController,
onPageChanged: onPageChanged
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.book),
title: Text('Recipes')
),
BottomNavigationBarItem(
icon: Icon(Icons.event),
title: Text('Plan')
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart),
title: Text('Shopping List')
),
BottomNavigationBarItem(
icon: Icon(Icons.public),
title: Text("Explore"),
),
],
onTap: navigationTapped,
currentIndex: _page,
),

);
}

void onPageChanged(int page){
setState((){
this._page = page;
});
}

void setBottomAppBar(PreferredSizeWidget appBar) {
this.bottomBar = appBar;
print("setBottomAppBar: "+ appBar.toString());
}

/// Called when the user presses on of the
/// [BottomNavigationBarItem] with corresponding
/// page index
void navigationTapped(int page){

// Animating to the page.
// You can use whatever duration and curve you like
_pageController.animateToPage(
page,
duration: const Duration(milliseconds: 300),
curve: Curves.ease
);
}

@override
void initState() {
super.initState();
initializeDateFormatting();

_pageController = PageController();
}

@override
void dispose(){
super.dispose();
_pageController.dispose();
}
}

PlanPage 类如下所示

class PlanPage extends StatefulWidget {
var homeState;

PlanPage(this.homeState);

@override
State<StatefulWidget> createState() {
return _PlanState(homeState);
}

}

class _PlanState extends State<PlanPage> with AutomaticKeepAliveClientMixin<PlanPage>, SingleTickerProviderStateMixin {
var homeState;
TabController _tabController;

_PlanState(this.homeState);

@override
bool get wantKeepAlive => true;

@override
Widget build(BuildContext context) {
//homeState.setBottomAppBar(_buildTabBar());

return Scaffold(
appBar: AppBar(
bottom: _buildTabBar(),
),
body: TabBarView(
controller: _tabController,
children: Plan.now().days.map((day) {
return ListView.builder(
itemCount: MealType.values.length,
itemBuilder: (BuildContext context, int index){
var mealType = MealType.values[index];
return Column(
children: <Widget>[
Text(
mealType.toString().substring(mealType.toString().indexOf('.')+1),
style: TextStyle(
//decoration: TextDecoration.underline,
fontSize: 30.0,
fontWeight: FontWeight.bold
),
),
Column(
children: day.meals.where((meal) => meal.mealType == mealType).map((meal) {
return RecipeCard(meal.recipe);
}).toList(),
)

],
);
}
);
}).toList(),
)
);
}

Widget _buildTabBar() {
return TabBar(
controller: _tabController,
isScrollable: true,
tabs: List.generate(Plan.now().days.length,(index) {
return Tab(
child: Column(
children: <Widget>[
Text(DateFormat.E().format(Plan.now().days[index].day)),
Text(DateFormat('d/M').format(Plan.now().days[index].day)),
],
),
);
}, growable: true),
);
}

@override
void initState() {
super.initState();

_tabController = new TabController(
length: Plan.now().days.length,
vsync: this,
initialIndex: 1
);
}
}

不管它现在的工作方式如何,它都会显示 2 个应用程序栏。[ 1

最佳答案

通常,拥有两个嵌套的可滚​​动区域并不是最佳做法。两个嵌套的脚手架也是如此。

也就是说,您可以监听页面更改 (_pageController.addListener(listener) ) 以更新 page 状态属性,并构建不同的 AppBar。 bottom(在 Home 小部件中,因此您可以删除 PlanPage 中的 Scaffold),具体取决于用户正在查看的页面。

-编辑-

在您的 Home 小部件中,您可以像这样向 _pageController 添加一个监听器:

void initState() {
super.initState();
_pageController = PageController()
..addListener(() {
setState(() {});
});
}

每次用户在您的 PageView 中滚动时都重建您的小部件。使用空函数调用 setState 可能看起来令人困惑,但它只是允许您在 _pageController.page 更改时重建小部件,这不是默认行为。您还可以拥有一个 page 状态属性并在 setState 调用中更新它以反射(reflect) _pageController.page 属性,但结果将是一样。

通过这种方式,您可以根据 _pageController.page 构建不同的 AppBar.bottom:

// in your build function

final bottomAppBar = _pageController.page == 2 ? TabBar(...) : null;

final appBar = AppBar(
bottom: bottomAppBar,
...
);

return Scaffold(
appBar: appBar,
...
);

关于Flutter - 从页面修改 AppBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53461043/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com