Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating action button moves up when used with keyboard input #2

Closed
stijnie2210 opened this issue Nov 7, 2018 · 7 comments
Closed

Comments

@stijnie2210
Copy link

First of all, I'm very grateful for this code to exist! But since i've been using it i've been coming across a couple layout bugs.

The first one is, when i'm using the code from the example there seems to be two FABs, and one seems to be lower than the other the first time the app boots up.
screen1

again, this is with the exact code from the repo, besides some text and theme changes ofcourse.

The second problem is when you tap on a text field and the keyboard pops up, the FAB moves up as well, and stays there even when you close the keyboard, as seen in the screenshots below. Maybe I'm doing something wrong here, but I'd appreciate some feedback.

screen3

screen2

Thank you very much in advance!

@vvasc
Copy link

vvasc commented Jan 18, 2019

to correct that, you could make a new class of FixedCenterDockedFabLocation extends FloatingActionButtonLocation and pass the context to it.

it's something like:

import 'dart:math';

import 'package:flutter/material.dart';

class FixedCenterDockedFabLocation extends FloatingActionButtonLocation {
  const FixedCenterDockedFabLocation({
    this.context,
  });
  final context;

  @protected
  double getDockedY(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    final double contentBottom = scaffoldGeometry.contentBottom;
    final double bottomSheetHeight = scaffoldGeometry.bottomSheetSize.height;
    final double fabHeight = scaffoldGeometry.floatingActionButtonSize.height;
    final double snackBarHeight = scaffoldGeometry.snackBarSize.height;
    double bottomDistance = MediaQuery.of(context).viewInsets.bottom;

    double fabY = contentBottom + bottomDistance - fabHeight / 2.0;

    // The FAB should sit with a margin between it and the snack bar.
    if (snackBarHeight > 0.0)
      fabY = min(fabY, contentBottom - snackBarHeight - fabHeight - kFloatingActionButtonMargin);
    // The FAB should sit with its center in front of the top of the bottom sheet.
    if (bottomSheetHeight > 0.0)
      fabY = min(fabY, contentBottom - bottomSheetHeight - fabHeight / 2.0);

    final double maxFabY = scaffoldGeometry.scaffoldSize.height - fabHeight;
    return min(maxFabY, fabY);
  }
  @override
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    final double fabX = (scaffoldGeometry.scaffoldSize.width - scaffoldGeometry.floatingActionButtonSize.width) / 2.0;
    return Offset(fabX, getDockedY(scaffoldGeometry));
  }
}

image

image

@aytunch
Copy link

aytunch commented Feb 19, 2019

@vvasc Thanks for this solution, I implemented it and now the FAB does not go up along with the keyboard. However the FAB makes a scale down to 0pixels and back up to its original size animation when the textfield is on focus. You can see it behind the keyboard in iOS simulator with a semi transparent keyboard.

Also, in my case, when i change through tabs of my bottomnavbar the same thing happens. Is this something about passing the context? Could you be so kind and check this issue?

@vvasc
Copy link

vvasc commented Feb 20, 2019

This happens with me too, unfortunately I don't know what causes that. But I've another approach which consist in apply a new fabLocation only when the keyboard appear.

static _dockedFabLocation(context) {
    if (MediaQuery.of(context).viewInsets.bottom != 0) {
      return FixedCenterDockedFabLocation(bottomDistance: MediaQuery.of(context).viewInsets.bottom);
    } else {
      return FloatingActionButtonLocation.centerDocked;
    }
  }

And FixedCenterDockedFabLocation still is the class above.
In this case I send the position of bottom distance instead of send context and the fab continues to make an animation when keyboard appear, however when I change tabs the FAB don't animate.

I know this one does not the best solution because the problem with animation FAB, although, this is the only solution I found to use an AppBar with a center FAB.

@srineesh
Copy link

srineesh commented Oct 24, 2019

how to navigate between other pages, when clicked items in the bottom bar without setting up a default index.
Thank you in advance.

@aarajput
Copy link

@vvasc Thanks for this solution, I implemented it and now the FAB does not go up along with the keyboard. However the FAB makes a scale down to 0pixels and back up to its original size animation when the textfield is on focus. You can see it behind the keyboard in iOS simulator with a semi transparent keyboard.

Also, in my case, when i change through tabs of my bottomnavbar the same thing happens. Is this something about passing the context? Could you be so kind and check this issue?

Code from #2 (comment) needs to be fixed in order to fix animation issue.

  1. Make FixedCenterDockedFabLocation const and dont pass context in it. I am asking you to this because animation on fab happens if FixedCenterDockedFabLocation rebuilds. const keyword will avoid that.
  2. Instead of double bottomDistance = MediaQuery.of(context).viewInsets.bottom;, use double bottomDistance = WidgetsBinding.instance.window.viewInsets.bottom

@sils
Copy link

sils commented Jul 29, 2021

For future reference, this is an implementation following this idea minus a few quirks, with less lines of code and using more upstream code, i.e. hopefully better to maintain:

class FixedCenterDockedFabLocation extends StandardFabLocation
    with FabCenterOffsetX, FabDockedOffsetY {
  const FixedCenterDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.fixedCenterDocked';

  @override
  double getOffsetY(
      ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    final double bottomMinInset = scaffoldGeometry.minInsets.bottom;
    if (bottomMinInset > 0) {
      // Hide if there's a keyboard
      return 0;
    }
    return super.getOffsetY(scaffoldGeometry, adjustment);
  }
}

Feel free to use this code without limitations or attribution.

Also note that when using this, use it with const.

@JamiuJimoh
Copy link

JamiuJimoh commented Sep 23, 2022

For future reference, this is an implementation following this idea minus a few quirks, with less lines of code and using more upstream code, i.e. hopefully better to maintain:

class FixedCenterDockedFabLocation extends StandardFabLocation
    with FabCenterOffsetX, FabDockedOffsetY {
  const FixedCenterDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.fixedCenterDocked';

  @override
  double getOffsetY(
      ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    final double bottomMinInset = scaffoldGeometry.minInsets.bottom;
    if (bottomMinInset > 0) {
      // Hide if there's a keyboard
      return 0;
    }
    return super.getOffsetY(scaffoldGeometry, adjustment);
  }
}

Feel free to use this code without limitations or attribution.

Also note that when using this, use it with const.

This works but the fab gets pushed to the top of the screen and still visible. A work around I used was to "return -100". This way, it gets pushed off the screen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants