I am developing a chat page which contains a text field at the bottom. When on-screen keyboard is active it covers the text field.
I tried all the online suggestions such as wrapping the body inside singlechildscrollview and set resizeToAvoidBottomInset: true with no success
is there any suggestion to fix this issue ?
Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: AppColors.scaffoldColor,
appBar: subAppBar(
title: "${"order".tr} #${widget.orderModel.order?.id}",
onBackTap: () {
controller.countdownTimer.value.cancel();
Get.back();
}),
body: Container(
height: Get.height,
width: Get.width,
padding: EdgeInsets.symmetric(
horizontal: 17.0.w,
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 28.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: 31.h,
padding: EdgeInsets.symmetric(horizontal: 9.9.w),
decoration: BoxDecoration(
color: AppColors.bgColorprimary,
borderRadius: BorderRadius.circular(12.r)),
child: Row(
children: [
SvgPicture.asset(
Images.animalLogoIcon,
width: 14.28.w,
height: 11.64.h,
),
SizedBox(width: 4.75.w),
BaseText(
widget.orderModel.order?.specialization?.title ?? "",
size: 10.sp,
color: AppColors.header2TextColor,
)
],
),
),
SizedBox(width: 12.w),
Container(
height: 31.h,
padding: EdgeInsets.symmetric(
horizontal: 9.9.w,
),
decoration: BoxDecoration(
color: AppColors.bgColorprimary,
borderRadius: BorderRadius.circular(12.r)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SvgPicture.asset(
Images.calenderIcon,
width: 14.28,
height: 11.3,
),
SizedBox(width: 4.75.w),
BaseText(
(widget.orderModel.order?.createdAt ?? "")
.substring(0, 10),
size: 10.sp,
color: AppColors.header2TextColor,
)
],
),
),
],
),
SizedBox(height: 20.h),
Obx(() {
final time = widget.timerController.timerValue.value;
return timeCard(time.isNotEmpty ? time : "-- -- --");
}),
if (widget.isDoctor) ...[
SizedBox(height: 24.h),
Row(
children: [
chatCardOption("View order".tr, () {
// getAnimatedDialog(
// content: DialogContent15MinutesUser(
// controller: controller,
// orderId: widget.orderModel.order?.id ?? -1,
// ));
final DoctorOrderModel order = DoctorOrderModel.fromJson(
json.decode(json.encode(widget.orderModel.order)));
Get.to(OrderDetails(
orderModel: order,
fromChat: true,
));
}),
customeSpaceW(10.w),
Obx(() {
return Visibility(
visible: controller.showOptionButton.value,
child: chatCardOption("Options".tr, () {
chatOptions(
context,
widget.orderModel.sessionId ?? -1,
widget.orderModel.order?.id ?? -1);
}),
);
}),
],
),
],
SizedBox(height: 10.h),
Obx(() {
if (!controller.state.messageLoading.value &&
controller.state.messages.isEmpty) {
return EmptyMessages(
isDoctor: widget.isDoctor,
doctorImg:
'${widget.orderModel.offer?.user?.profile?.image}',
userImg: '${widget.orderModel.order?.user?.profile?.image}',
);
}
final itemCount = controller.state.messageLoading.value
? 10
: controller.state.isPageLoading.value ||
(widget.isDoctor &&
controller.state.messages.length == 1)
? controller.state.messages.length + 1
: controller.state.messages.length;
return Expanded(
child: ListView.separated(
controller: scrollController,
physics: ClampingScrollPhysics(),
itemCount: itemCount,
padding: EdgeInsets.only(top: 30.h, bottom: 20.h),
separatorBuilder: (context, index) => SizedBox(
height: 22.h,
),
itemBuilder: (context, index) {
if (controller.state.messageLoading.value) {
return MessageCardLoading(isSender: index % 2 == 0);
}
if (widget.isDoctor &&
controller.state.messages.length == 1 &&
index == 1) {
return NoticeDoctorAbout15();
}
if (controller.state.isPageLoading.value && 0 == index) {
return CustomProgressIndicatorForPagination();
}
final item = controller.state.isPageLoading.value
? controller.state.messages[index - 1]
: controller.state.messages[index];
bool isSender;
if (item.user?.id.toString() == userId.value) {
isSender = true;
} else {
print(item.user?.id);
print(item.user);
isSender = false;
}
return MessageCard(
isSender: isSender,
messageModelEntity: item,
);
},
),
);
}),
Obx(() {
if ((widget.isDoctor && controller.state.messages.isEmpty) ||
(!widget.isDoctor && controller.state.messages.length == 1))
return Container(
height: 46.h,
decoration: BoxDecoration(
color: AppColors.bgColorprimary,
borderRadius: BorderRadius.circular(25.r)),
child: Center(
child: BaseText(
widget.isDoctor
? "Waiting for the Client".tr
: "Waiting for the Doctor".tr,
size: 12.sp,
color: AppColors.header3TextColor,
),
),
);
else if (widget.timerController.timerValue.value ==
"00m:00sec") {
return SizedBox();
} else
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (controller.state.isRecode.value)
Container(
width: 240.w,
height: 46.h,
padding: EdgeInsets.symmetric(horizontal: 20.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: AppColors.bgColorprimary),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StreamBuilder<RecordingDisposition>(
stream: controller.recorder.onProgress,
builder: (context, snapshot) {
final duration = snapshot.hasData
? snapshot.data!.duration
: Duration.zero;
DateTime date = DateTime(
DateTime.now().year,
DateTime.now().month,
duration.inDays,
duration.inHours.remainder(24),
duration.inMinutes.remainder(60),
duration.inSeconds.remainder(60));
duration.inSeconds.remainder(60);
String time =
DateFormat('mm:ss').format(date);
print(duration.inSeconds);
return BaseText('${time}');
}),
IconButton(
onPressed: () {
controller.state.isRecode.value = false;
controller.state.voicePath.value = '';
},
icon: Icon(
Icons.cancel,
color: AppColors.red,
))
],
),
)
else if (controller.state.imgPath.value.isNotEmpty)
Container(
width: 200.r,
height: 200.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: AppColors.bgColorprimary,
),
clipBehavior: Clip.antiAlias,
child: Stack(
children: [
GeneralImageFile(
path: controller.state.imgPath.value,
width: 200.r,
height: 200.r,
fit: BoxFit.fill),
Align(
alignment: Alignment.topLeft,
child: IconButton(
onPressed: () {
controller.state.imgPath.value = '';
},
icon: Icon(
Icons.cancel,
color: AppColors.red,
)),
)
],
),
)
else
SizedBox(
width: 240.w,
child: CustomTextFromField(
margin: EdgeInsets.zero,
controller: controller.messageController,
onChanged: (v) {
if (controller.messageController.text.isNotEmpty)
controller.state.isHaveText.value = true;
else
controller.state.isHaveText.value = false;
},
borderStyleType: BorderStyleType.outlineInput,
fillColor: AppColors.bgColorprimary,
borderRadius: BorderRadius.circular(25.r),
hintText: LocalKeys.type_here.tr,
contentPadding: EdgeInsets.only(
top: 12.h,
left: 20.w,
right: 5.w,
bottom: 12.h),
),
),
if (!controller.state.isHaveText.value &&
!(controller.state.isRecode.value &&
controller.state.voicePath.value.isNotEmpty))
InkWell(
onTap: controller.selectImageFromGallery,
borderRadius: BorderRadius.circular(50.r),
child: Container(
height: 46.r,
width: 46.r,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.bgColorprimary),
child: Icon(Icons.add_rounded,
color: AppColors.mainColor, size: 18.r),
),
),
if (controller.state.isHaveText.value ||
controller.state.imgPath.value.isNotEmpty ||
(controller.state.isRecode.value &&
controller.state.voicePath.value.isNotEmpty))
InkWell(
onTap: () {
controller.sendMessage(
sessionId:
widget.orderModel.sessionId.toString(),
isDoctor: widget.isDoctor,
timerController: widget.timerController,
activeOrderModel: widget.orderModel,
scrollController: scrollController);
},
borderRadius: BorderRadius.circular(50.r),
child: Container(
height: 46.r,
width: 46.r,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.bgColorprimary),
child: Icon(Icons.send_rounded,
color: AppColors.mainColor, size: 18.r),
),
)
else
RecorderSound(controller: controller),
],
);
}),
SizedBox(height: 32.h),
],
),
),
),
2
Answers
Thank you for your answer. I started digging what could the problem be, and I figured it out. In my case I am using the package flutter_screenutil, upgrading it to latest (5.8.1) and setting useInheritedMediaQuery = true fixed the issue in my app.
There is a property in the scaffold named as bottomSheet, you can take your customTextFormField and return it from there, it till place the text field in the bottom of the scaffold, and as the scaffold is reduced when you open the keyboard so the text field will stay right there.
Here is the Code for you reference:
And here are the screenShots of implementation:
text field with open keyboard
enter image description here