I want to add a button to 'src/screens/home.dart' that has the same transition as the BottomNavigationBar in 'src/app.dart'. Of course, keeping the AppBar and BottomNavigationBar.
In my code, if I move from the button in home to cam Screen, it leaves app.dart. It is also plausible that the UI should be reviewed.
After that transition, I want the BottomNavigationBar icon to light up. When moving to a screen with no icons, I want all icons to be dimmed. Same as the 'app.dart _buildIcon' process.
I started learning Flutter yesterday, so if there's any weird code, please let me know. Thank you.
Edit:. I gave
HomeScreen()
aPageController
and was able to take over the AppBar and BottomBar, but the BottomBar selection is not updated.
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'src/app.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,]);
runApp(
const MyApp()
);
}
src/app.dart:
import 'package:flutter/material.dart';
import 'screens/home.dart';
import 'screens/cam.dart';
import 'screens/setting.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
//debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
splashColor: Colors.transparent,
),
home: BasePage(),
);
}
}
class BasePage extends StatefulWidget{
@override
_BasePage createState() => _BasePage();
}
class _BasePage extends State<BasePage> {
final _pageController = PageController();
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
var TabItem = {
'home':[0, Icons.home, Colors.green, HomeScreen(pageController: _pageController)],
'cam':[1, Icons.video_camera_back, Colors.lightGreen, const CamScreen()],
'setting':[2, Icons.settings, Colors.yellow, const SettingScreen()]
};
return Scaffold(
appBar: AppBar(
toolbarHeight: MediaQuery.of(context).size.height / 16,
title: Image.asset('assets/images/logo.png', width: 200, fit: BoxFit.contain,),
centerTitle: true,
),
body: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(),
children: TabItem.values.map((value) => value[3] as Widget).toList(),
),
bottomNavigationBar: SizedBox(
height: MediaQuery.of(context).size.height /8,
child:BottomNavigationBar(
currentIndex: _currentIndex,
selectedFontSize: 0,
unselectedFontSize: 0,
items: TabItem.entries.map(
(tabItem) => BottomNavigationBarItem(
icon: _buildIcon(tabItem.value[1] as IconData, tabItem.value[2]as Color, selected: _currentIndex == tabItem.value[0]),
label: tabItem.key,
),
).toList(),
onTap: (index) {
setState(() {
_currentIndex = index;
_pageController.jumpToPage(index);
});
},
type: BottomNavigationBarType.fixed,
),
),
);
}
Widget _buildIcon(IconData icon, Color color, {bool selected=false}) {
Color filteredColor = selected ? color : color.withOpacity(0.3);
return Container(
width: 60, height: 60,
decoration: BoxDecoration(shape: BoxShape.circle, color: filteredColor),
child: Icon(icon, size: 50, color: Colors.white,),
);
}
}
src/screens/home.dart:
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
final PageController pageController;
HomeScreen({super.key, required this.pageController,});
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: GestureDetector(
onTap: (){pageController.jumpToPage(1);},
child: Container(
// Omit the code here.
),
),
),
],
);
}
}
src/screens/cam.dart
import 'package:flutter/material.dart';
class CamScreen extends StatelessWidget {
const CamScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body:
const Center(child: Text('camera', style: TextStyle(fontSize: 32.0))),
);
}
}
SOLVED src/app.dart
import 'package:flutter/material.dart';
import 'screens/home.dart';
import 'screens/cam.dart';
import 'screens/setting.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
//debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
splashColor: Colors.transparent,
),
home: BasePage(),
);
}
}
class BasePage extends StatefulWidget{
@override
_BasePage createState() => _BasePage();
}
class _BasePage extends State<BasePage> {
final _pageController = PageController();
int _currentIndex = 0;
void changeIndex(index){
setState(() {
_currentIndex = index;
_pageController.jumpToPage(index);
});
}
@override
Widget build(BuildContext context) {
var TabItem = {
'home':[0, Icons.home, Colors.green, HomeScreen(pageController: _pageController, changeIndex: changeIndex,)],
'cam':[1, Icons.video_camera_back, Colors.lightGreen, const CamScreen()],
'setting':[2, Icons.settings, Colors.yellow, const SettingScreen()]
};
return Scaffold(
appBar: AppBar(
toolbarHeight: MediaQuery.of(context).size.height / 16,
title: Image.asset('assets/images/logo.png', width: 200, fit: BoxFit.contain,),
centerTitle: true,
),
body: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(),
children: TabItem.values.map((value) => value[3] as Widget).toList(),
),
bottomNavigationBar: SizedBox(
height: MediaQuery.of(context).size.height /8,
child:BottomNavigationBar(
currentIndex: _currentIndex,
selectedFontSize: 0,
unselectedFontSize: 0,
items: TabItem.entries.map(
(tabItem) => BottomNavigationBarItem(
icon: _buildIcon(tabItem.value[1] as IconData, tabItem.value[2]as Color, selected: _currentIndex == tabItem.value[0]),
label: tabItem.key,
),
).toList(),
onTap: (index) {
setState(() {
_currentIndex = index;
_pageController.jumpToPage(index);
});
},
type: BottomNavigationBarType.fixed,
),
),
);
}
Widget _buildIcon(IconData icon, Color color, {bool selected=false}) {
Color filteredColor = selected ? color : color.withOpacity(0.3);
return Container(
width: 60, height: 60,
decoration: BoxDecoration(shape: BoxShape.circle, color: filteredColor),
child: Icon(icon, size: 50, color: Colors.white,),
);
}
}
src/screens/home.dart
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
final PageController pageController;
final void Function(int) changeIndex;
const HomeScreen({super.key, required this.pageController, required this.changeIndex});
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: GestureDetector(
onTap: (){changeIndex(1);},
child: Container(
// Omit the code here.
),
),
),
],
);
}
}
Answers
It looks like you've made significant progress on your Flutter app! Let's address the issues you mentioned and make the necessary adjustments to achieve the desired behavior.
Issue 1: Transition to CamScreen
leaves app.dart
To address this issue, we need to ensure that the transition from the button in the HomeScreen
to the CamScreen
does not leave the BasePage
widget. We'll modify the changeIndex
function to handle this transition properly.
Issue 2: Updating BottomNavigationBar
selection
When transitioning between screens, you want the corresponding icon in the BottomNavigationBar
to light up. We'll update the logic to achieve this behavior.
Issue 3: Reviewing the UI
We'll review the UI and make any necessary adjustments for better usability.
Proposed Solution:
Update BasePage
widget:
class _BasePage extends State<BasePage> {
final _pageController = PageController();
int _currentIndex = 0;
void changeIndex(int index) {
setState(() {
_currentIndex = index;
_pageController.jumpToPage(index);
});
}
@override
Widget build(BuildContext context) {
var tabItems = {
'home': [0, Icons.home, Colors.green, HomeScreen(pageController: _pageController, changeIndex: changeIndex)],
'cam': [1, Icons.video_camera_back, Colors.lightGreen, const CamScreen()],
'setting': [2, Icons.settings, Colors.yellow, const SettingScreen()]
};
return Scaffold(
appBar: AppBar(
toolbarHeight: MediaQuery.of(context).size.height / 16,
title: Image.asset(
'assets/images/logo.png',
width: 200,
fit: BoxFit.contain,
),
centerTitle: true,
),
body: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(),
children: tabItems.values.map((value) => value[3] as Widget).toList(),
),
bottomNavigationBar: SizedBox(
height: MediaQuery.of(context).size.height / 8,
child: BottomNavigationBar(
currentIndex: _currentIndex,
selectedFontSize: 0,
unselectedFontSize: 0,
items: tabItems.entries.map(
(tabItem) => BottomNavigationBarItem(
icon: _buildIcon(tabItem.value[1] as IconData, tabItem.value[2] as Color, selected: _currentIndex == tabItem.value[0]),
label: tabItem.key,
),
).toList(),
onTap: (index) {
changeIndex(index);
},
type: BottomNavigationBarType.fixed,
),
),
);
}
Widget _buildIcon(IconData icon, Color color, {bool selected = false}) {
Color filteredColor = selected ? color : color.withOpacity(0.3);
return Container(
width: 60,
height: 60,
decoration: BoxDecoration(shape: BoxShape.circle, color: filteredColor),
child: Icon(
icon,
size: 50,
color: Colors.white,
),
);
}
}
Update HomeScreen
widget:
class HomeScreen extends StatelessWidget {
final PageController pageController;
final void Function(int) changeIndex;
const HomeScreen({Key? key, required this.pageController, required this.changeIndex}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: GestureDetector(
onTap: () {
changeIndex(1); // Transition to CamScreen
},
child: Container(
// Add your button UI here
alignment: Alignment.center,
child: Text(
'Go to Cam Screen',
style: TextStyle(fontSize: 20),
),
),
),
),
],
);
}
}
With these adjustments, tapping the button in HomeScreen
will transition to CamScreen
without leaving BasePage
, and the BottomNavigationBar
selection will update accordingly.