I am trying to make a working menu but I’m having issues such as having RangeErrors, the creation of menus is not immediate, etc. This is my current code:
@override
Widget build(BuildContext context) {
bool isDrawerOpen = _key.currentState?.isDrawerOpen ?? false;
bool isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return GestureDetector(
onTap: () {
setState(() {
_key.currentState!.closeDrawer();
isTextFieldEnabled = false;
isSidebarOpen = false;
});
},
child: Scaffold(
appBar: isSearching
? AppBar(
backgroundColor: Theme.of(context)
.bottomNavigationBarTheme
.backgroundColor,
automaticallyImplyLeading: false,
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Theme.of(context)
.bottomNavigationBarTheme
.backgroundColor),
actions: [
Container(
width: MediaQuery.of(context).size.width / 1.2,
color: Theme.of(context)
.bottomNavigationBarTheme
.backgroundColor,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: TextField(
autofocus: true,
controller: SearchController,
onChanged: (value) {
setState(() {
SearchText = value;
});
},
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
filled: true,
fillColor: Color.fromARGB(255, 23, 23, 24),
prefixIcon: Padding(
padding: EdgeInsets.only(left: 17, right: 0),
child: Icon(Icons.search_rounded,
color: Colors.grey[400]),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent),
),
hintText: 'Search',
),
),
),
),
),
Expanded(
child: AnimatedContainer(
color: Theme.of(context)
.bottomNavigationBarTheme
.backgroundColor,
width: 80,
height: 90,
duration: Duration(milliseconds: 200),
child: GestureDetector(
onTap: () {
setState(() {
SearchController.text = '';
SearchText = '';
isSearching = false;
});
},
child: Center(
child: Text(
'Cancel',
style: TextStyle(
fontSize: 16,
color: Colors.blue.withOpacity(1.0),
),
),
),
),
),
),
],
)
: AppBar(
backgroundColor: Theme.of(context)
.bottomNavigationBarTheme
.backgroundColor,
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Theme.of(context)
.bottomNavigationBarTheme
.backgroundColor),
leadingWidth: 90,
leading: Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 10),
child: GestureDetector(
onTap: () {
setState(() {
_key.currentState?.closeDrawer();
});
Future.delayed(Duration(milliseconds: 300), () {
Navigator.of(context).popUntil((route) => route.isFirst);
});
},
child: ImageIcon(
AssetImage("assets/Back - White.png"),
color: Colors.blue[700],
),
),
),
Padding(
padding: const EdgeInsets.only(left: 10),
child: GestureDetector(
onTap: () {
// When in portrait, sidebar button uses the drawer
// When landscape, sidebar button uses boolean for sidebar function
if (isPortrait) {
if (isDrawerOpen) {
setState(() {
isSidebarOpen = false;
});
_key.currentState!.closeDrawer();
} else {
setState(() {
isSidebarOpen = true;
});
_key.currentState!.openDrawer();
}
} else {
setState(() {
isSidebarOpen = !isSidebarOpen;
});
}
},
child: Icon(
CupertinoIcons.sidebar_left,
color: Colors.blue[700],
),
),
),
],
),
actions: [
// Add Shot Button
Padding(
padding: const EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: () {
if (!widget.sidebarPhoneData.ShootDateList.isEmpty)
setState(() {
widget.shotPagePhoneData.createData(
widget.shotPagePhoneData.CurrentShotList);
widget.shotInfoPhoneData.createInner(
widget.shotPagePhoneData.CurrentShotList);
});
showModalBottomSheet(
useSafeArea: true,
isScrollControlled: true,
context: context,
transitionAnimationController: animationController,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context)
.size
.height,
maxWidth: MediaQuery.of(context)
.size
.width,
),
builder: (context) {
return ShotInfoPhone(
ShotListIndex: widget
.shotPagePhoneData
.CurrentShotList,
ShotIndex: widget.shotPagePhoneData.ShotName[widget.shotPagePhoneData.CurrentShotList].length - 1,
isTablet: false,
Title: 'Shot ${widget.shotPagePhoneData.ShotName[widget.shotPagePhoneData.CurrentShotList].length + 1}',
isNew: true,
shotInfoPhoneData: widget
.shotInfoPhoneData,
);
}
).then((value) {
CheckFilled(widget.shotPagePhoneData.CurrentShotList, widget.shotPagePhoneData.ShotName.length - 1);
});
},
child: Icon(
CupertinoIcons.add,
color: widget.sidebarPhoneData.ShootDateList.isEmpty
? Colors.grey
: Colors.blue[700],
),
),
),
// Search Button
Padding(
padding: const EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: () {
if (!widget.sidebarPhoneData.ShootDateList.isEmpty)
setState(() {
isSearching = true;
});
},
child: Icon(
Icons.search,
color: widget.sidebarPhoneData.ShootDateList.isEmpty
? Colors.grey
: Colors.blue[700],
),
),
),
// Share Menu Button
Padding(
padding: const EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: () {
if (!widget.sidebarPhoneData.ShootDateList.isEmpty) {
showModalBottomSheet(
useSafeArea: true,
isScrollControlled: true,
context: context,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context)
.size
.height,
maxWidth: MediaQuery.of(context)
.size
.width,
),
builder: (context) {
return ShareMenu(
shotPagePhoneData: widget.shotPagePhoneData,
shotInfoPhoneData: widget.shotInfoPhoneData,
sidebarPhoneData: widget.sidebarPhoneData,
);});}},
child: Icon(
CupertinoIcons.share,
color: widget.sidebarPhoneData.ShootDateList.isEmpty
? Colors.grey
: Colors.blue[700],
))),
// Shot Menu Button
Padding(
padding: const EdgeInsets.only(right: 20),
child: GestureDetector(
onTap: () {
if (!widget.sidebarPhoneData.ShootDateList.isEmpty)
showModalBottomSheet(
useSafeArea: true,
isScrollControlled: true,
context: context,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context)
.size
.height,
maxWidth: MediaQuery.of(context)
.size
.width,
),
builder: (context) {
return ShotMenu(
shotPagePhoneData: widget.shotPagePhoneData,
);});},
child: ImageIcon(
AssetImage('assets/More - White.png'),
color: widget.sidebarPhoneData.ShootDateList.isEmpty
? Colors.grey
: Colors.blue[700],
)))],
bottom: PreferredSize(
preferredSize: Size(1, 1),
child: Container(
height: 0.8,
width: MediaQuery.of(context).size.width,
color: Colors.grey[800],
))),
body: GestureDetector(
onTap: () {
setState(() {
isSearching = false;
isTextFieldEnabled = false;
});},
child: Scaffold(
drawerScrimColor: isPortrait ? Colors.black54 : Colors.transparent,
onDrawerChanged: (value) {
setState(() {
isSidebarOpen = value;
});},
key: _key,
// Sidebar
drawer: isPortrait ? Container(
width: 250,
child: SidebarPhone(
length: widget.shotPagePhoneData.ShotName.length,
CurrentShotList: widget.shotPagePhoneData.CurrentShotList,
isTablet: false,
sidebarPhoneData: widget.sidebarPhoneData,
onScene: () {
setState(() {
widget.shotPagePhoneData.create();
widget.shotInfoPhoneData.createOuter();
});},
onDelete: (index) {
setState(() {
widget.shotPagePhoneData.delete(index);
widget.shotInfoPhoneData.deleteOuter(index);
});},
onSelect: (index) {
setState(() {
widget.shotPagePhoneData.CurrentShotList = index;
_key.currentState?.closeDrawer();
});}),
) : null,
body: Row(
children: [
// Sidebar for landscape mode
if (!isPortrait && isSidebarOpen)
Container(
width: 300,
child: SidebarPhone(
length: widget.shotPagePhoneData.ShotName.length,
CurrentShotList: widget.shotPagePhoneData.CurrentShotList,
isTablet: false,
sidebarPhoneData: widget.sidebarPhoneData,
onScene: () {
setState(() {
widget.shotPagePhoneData.create();
widget.shotInfoPhoneData.createOuter();
});},
onDelete: (index) {
setState(() {
widget.shotPagePhoneData.delete(index);
widget.shotInfoPhoneData.deleteOuter(index);
});},
onSelect: (index) {
setState(() {
widget.shotPagePhoneData.CurrentShotList = index;
isSidebarOpen = false;
});})),
widget.shotPagePhoneData.ShotName.isEmpty ||
widget.shotPagePhoneData.ShotName[widget.shotPagePhoneData
.CurrentShotList]
.isEmpty
? Center(
child: SingleChildScrollView(
controller: scrollController,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(left: isSidebarOpen ? 150.0 : 350.0),
child: Column(
children: [
Icon(
Icons.access_time_filled,
size: 50,
color: Colors.grey,
),
Text(
'No Shots',
style: TextStyle(fontSize: 18),
),
Text(
'Recently created shots will',
style: TextStyle(
color:
Theme.of(context).appBarTheme.surfaceTintColor),
),
Text(
'appear here',
style: TextStyle(
color:
Theme.of(context).appBarTheme.surfaceTintColor),
)]))])))
: Expanded(
child: SingleChildScrollView(
controller: scrollController,
child: Padding(
padding: EdgeInsets.only(
right: isPortrait ? 30 : 80, left: 30, top: 20, bottom: 20),
child: Container(
width: 50,
child: ReorderableListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: widget
.shotPagePhoneData
.ShotName[widget.shotPagePhoneData.CurrentShotList]
.length,
onReorder: (oldIndex, newIndex) {
Reorder(oldIndex, newIndex);
},
itemBuilder: (context, index) {
TextEditingController TitleController =
TextEditingController();
TitleController.text = widget
.shotPagePhoneData
.ShotName[widget.shotPagePhoneData
.CurrentShotList][index];
final key = ValueKey(widget.shotPagePhoneData
.ShotName[widget.shotPagePhoneData
.CurrentShotList][index]);
if (widget.shotPagePhoneData
.ShotName[widget.shotPagePhoneData
.CurrentShotList][index]
.contains(SearchText)) {
return Center(
key: key,
child: Padding(
padding: const EdgeInsets.only(bottom: 10),
child: GestureDetector(
onTap: () {
showModalBottomSheet(
useSafeArea: true,
isScrollControlled: true,
transitionAnimationController: animationController,
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height,
maxWidth: MediaQuery.of(context).size.width,
),
context: context,
builder: (context) {
return ShotInfoPhone(
ShotListIndex: widget
.shotPagePhoneData
.CurrentShotList,
ShotIndex: index,
isTablet: false,
Title: widget.shotPagePhoneData.ShotName[widget.shotPagePhoneData.CurrentShotList][index],
isNew: false,
shotInfoPhoneData: widget
.shotInfoPhoneData,
);
}).then((value) => setState(() {
}));},
// Slide to delete function for shot
child: Dismissible(
key: key,
direction: DismissDirection.endToStart,
onDismissed: (direction) {
setState(() {
// Remove the item from the data source.
widget.shotPagePhoneData.ShotName[
widget.shotPagePhoneData.CurrentShotList]
.removeAt(index);
});},
background: Container(
color: Colors.red,
child: Align(
alignment: Alignment.centerRight,
child: Padding(
padding:
const EdgeInsets.only(right: 25),
child: Icon(
Icons.delete,
color: Colors.white,
)))),
child: Container(
width: isPortrait ? MediaQuery.of(context).size.width : MediaQuery.of(context).size.width / 1.5,
height: 80,
decoration: BoxDecoration(
color: Colors.grey[900],
borderRadius:
BorderRadius.circular(10)),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 20, vertical: 10),
child: Row(
children: [
widget.shotInfoPhoneData
.ImageFile[widget
.shotPagePhoneData
.CurrentShotList]
.isEmpty
? SizedBox.shrink()
: widget
.shotInfoPhoneData
.ImageFile[widget
.shotPagePhoneData
.CurrentShotList][index]
.path
.isEmpty
? Image(
image: AssetImage(
'assets/Add Photo - 4.3.png'),
color: null,
height: 60,
width: 70,
)
: Container(
height: 50,
width: 70,
child: ClipRRect(
borderRadius:
BorderRadius
.circular(
10),
child: Image.file(
widget
.shotInfoPhoneData
.ImageFile[widget.shotPagePhoneData.CurrentShotList]
[
index],
fit: BoxFit.fill
))),
SizedBox(
width: 20,
),
Expanded(
child: TextField(
enabled: isTextFieldEnabled,
controller: TitleController,
style: TextStyle(
color: Colors.white),
decoration: InputDecoration(
disabledBorder:
InputBorder.none),
onChanged: (value) {
TitleController.text =
value;
widget.shotPagePhoneData
.ShotName[widget
.shotPagePhoneData
.CurrentShotList]
[index] = value;
},
onSubmitted: (value) {
setState(() {
TitleController.text =
value;
widget
.shotPagePhoneData
.ShotName[widget
.shotPagePhoneData
.CurrentShotList]
[index] = value;
widget.shotPagePhoneData
.save();
isTextFieldEnabled =
false;
});})),
Spacer(),
GestureDetector(
onTap: () {
setState(() {
widget.shotPagePhoneData
.CheckBoxList[widget
.shotPagePhoneData
.CurrentShotList]
[index] = !widget
.shotPagePhoneData
.CheckBoxList[widget
.shotPagePhoneData
.CurrentShotList]
[index];
});},
child: widget.shotPagePhoneData
.CheckBoxList[widget
.shotPagePhoneData
.CurrentShotList]
.isEmpty
? SizedBox.shrink()
: !widget.shotPagePhoneData
.CheckBoxList[widget
.shotPagePhoneData
.CurrentShotList]
[index]
? Image(
image: AssetImage(
"assets/Tick (Empty).png"),
color:
Colors.grey,
height: 30)
: Image(
image: AssetImage(
"assets/Tick (Full).png"),
height: 30,
))])))))));
} else {
return Container(
key: key,
);}})))))])))));}
I have tried readjusting my code but I could not get it to work smoothly. The image attached is what the menu should look like with no errors and the timing works well.