79721210

Date: 2025-07-31 11:24:18
Score: 0.5
Natty:
Report link

Flutter: Background Image Moves Up When Tapping on TextFormField – How to Prevent Layout Shift?

I have a CustomScaffold widget that contains a background image, and the body of the screen is placed inside a Scaffold widget. However, when I tap on a TextFormField, the background image shifts upward along with the body content. I want to prevent the background image from shifting when the keyboard appears without breaking my layout.

What I Tried:

What Worked:

I found a solution by wrapping the background image in a SingleChildScrollView. This allowed the background to remain fixed while the body could still scroll independently. Below is my updated CustomScaffold widget that fixed the issue:

class CustomScaffold extends StatelessWidget {
  final Widget body;
  final Color? backgroundColor;
  final PreferredSizeWidget? appBar;
  final Widget? bottomNavigationBar;
  final bool? extendBodyBehindAppBar;
  final bool? resizeToAvoidBottomInset;
  final bool bgImg;
  final String productType;

  const CustomScaffold({
    Key? key,
    required this.body,
    this.backgroundColor,
    this.appBar,
    this.bottomNavigationBar,
    this.extendBodyBehindAppBar = false,
    this.resizeToAvoidBottomInset,
    this.bgImg = false,
    this.productType = "",
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        WidgetsBinding.instance.focusManager.primaryFocus?.unfocus();
      },
      child: Stack(
        children: [
          bgImg == false && productType.isEmpty
              ? SizedBox.shrink()
              : Positioned.fill(
                  left: 0,
                  top: 0,
                  right: 0,
                  bottom: 0,
                  child: SingleChildScrollView( // Added SingleChildScrollView
                    child: Image.asset(
                      _getBackgroundImage(productType),
                      fit: BoxFit.fill,
                    ),
                  )),
          Scaffold(
            extendBodyBehindAppBar: extendBodyBehindAppBar ?? false,
            resizeToAvoidBottomInset: resizeToAvoidBottomInset,
            appBar: appBar,
            backgroundColor: backgroundColor ??
                (bgImg == false
                    ? Constants.colors.background
                    : Colors.transparent),
            body: body,
            bottomNavigationBar: bottomNavigationBar,
          ),
        ],
      ),
    );
  }

  String _getBackgroundImage(String? productType) {
    switch (productType) {
      case "A":
        return 'assets/images/pl_bg.webp';
      case "B":
        return 'assets/images/pl_bg.webp';
      case "C":
        return 'assets/images/pl_bg.webp';
      case "D":
        return 'assets/images/pl_bg.webp';
      case "E":
        return 'assets/images/pl_bg.webp';
      case "F":
        return 'assets/images/pl_bg.webp';
      case "G":
        return 'assets/images/ce_bg.webp';
      default:
        return 'assets/images/splash.webp';
    }
  }
}

and here is my UI

child: CustomScaffold(
            resizeToAvoidBottomInset: false,
bgImg : true,
productType: "A",
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                LabelWidget(
                  text: 'My UI'.tr,
                  fontWeight: FontWeight.w600,
                  fontSize: 28.sp,
                  textColor: Colors.black,
                  padding: 0,
                ).marginSymmetric(horizontal: 16.w),

                // Select the card for offers
                CardWidgetForOffers(
                    offerController: controller,
                    entitiesController: entController), // select card
                16.verticalSpace,

                Expanded(
                  child: SingleChildScrollView(
                    controller: scrollController,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        // Banners widget  swipe cards
                        BannerWidget(),

                        // saved offers
                        SavedOffersWidget(
                            offersController: controller),

                        // search offers here [This is my TextFormField]
                        SearchOffersWidget(offersController: offersController),

                        //  offers in list view
                        NewTestListViewWidget(),
                        15.verticalSpace,
                      ],
                    ),
                  ),
                ),
              ],
            ).marginOnly(top: 50.h),
          ),
Reasons:
  • RegEx Blacklisted phrase (1): I want
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Low reputation (0.5):
Posted by: Ijlal Hussain