I have created a custom widget where an overlay entry widget is shown right bottom of it with a search bar and a list.
The problem I am facing is, when the user clicks the textfield inside the overlay widget, the screen does not push up enough for the user to see the textfield. Please check the screenshoot for more details
The code of the custom dropdown button widget is below:
import 'package:flutter/material.dart';
class DropDownWidget2 extends StatefulWidget {
DropDownWidget2({Key? key}) : super(key: key);
@override
State<DropDownWidget2> createState() => _DropDownWidget2State();
}
class _DropDownWidget2State extends State<DropDownWidget2> with TickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
bool isOpen = false;
final List<Map<String, dynamic>> _allData = [
{"id": 1, "name": "Andy", "age": 29},
{"id": 2, "name": "Aragon", "age": 40},
{"id": 3, "name": "Bob", "age": 5},
{"id": 4, "name": "Barbara", "age": 35},
{"id": 5, "name": "Candy", "age": 21},
{"id": 6, "name": "Colin", "age": 55},
{"id": 7, "name": "Audra", "age": 30},
{"id": 8, "name": "Banana", "age": 14},
{"id": 9, "name": "Caversky", "age": 100},
{"id": 10, "name": "Becky", "age": 32},
];
// This list holds the data for the list view
List<Map<String, dynamic>> _foundData = [];
final layerLink = LayerLink();
OverlayEntry? entry;
@override
void initState() {
_animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 450));
_animation = Tween(begin: 0.0, end: -.5)
.animate(CurvedAnimation(parent: _animationController, curve: Curves.easeOut));
_foundData = _allData;
super.initState();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _handleOnPressed() {
setState(() {
isOpen = !isOpen;
isOpen ? _animationController.forward() : _animationController.reverse();
showOverLay();
});
}
@override
Widget build(BuildContext context) {
return CompositedTransformTarget(
link: layerLink,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(10)),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Select one from below'),
IconButton(
padding: EdgeInsets.zero,
iconSize: 18,
splashRadius: 20,
splashColor: Colors.greenAccent,
icon: RotationTransition(
turns: _animation,
child: Icon(Icons.expand_more),
),
onPressed: () => _handleOnPressed(),
)
],
),
),
);
}
Widget itemsWidget() {
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10)),
padding: EdgeInsets.only(left: 12, top: 4, bottom: 4),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
onChanged: (value) => {},
decoration: const InputDecoration(labelText: 'Search', suffixIcon: Icon(Icons.search)),
),
_foundData.isNotEmpty
? ListView.separated(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: _foundData.length,
itemBuilder: (context, index) {
return Text(_foundData[index]['name']);
},
separatorBuilder: (context, index) {
return Divider();
},
)
: const Text(
'No results found',
style: TextStyle(fontSize: 14),
),
],
),
);
}
Widget buildOverlay() {
return Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: const BorderSide(color: Colors.black, width: 1),
),
child: AnimatedCrossFade(
duration: const Duration(microseconds: 500),
firstChild: Container(), // When you don't want to show menu..
secondChild: itemsWidget(),
crossFadeState: isOpen ? CrossFadeState.showSecond : CrossFadeState.showFirst,
),
);
}
void showOverLay() {
final overlay = Overlay.of(context)!;
final renderBox = context.findRenderObject() as RenderBox;
final size = renderBox.size;
entry = OverlayEntry(
builder: (context) => Positioned(
width: size.width,
child: CompositedTransformFollower(
link: layerLink,
showWhenUnlinked: false,
offset: Offset(0, size.height),
child: buildOverlay())));
overlay.insert(entry!);
}
}
As you can observe from the screenshot. The keyboard moves above overlayentry hiding my textfield and my list items. Is there any way I can push the whole overlayEntry above the keyboard? I've tried many ways like using mediaquery bottom insets and other things but i still could not achieve it.

