31

I have a faux dialog which uses this layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout    xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_height="match_parent"
                android:layout_width="match_parent"
                android:id="@+id/containerPageConatiner">

    <FrameLayout    android:id="@+id/dialogHolder"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:padding="15dp"
                    android:layout_gravity="center"
                    android:background="@drawable/panel_picture_frame_bg_focus_blue"/>    
</FrameLayout> 

I place a fragment inside the <FrameLayout> depending on the dialog which is opening - The activity controlling the Dialog looks like this:

<activity
    android:label="@string/app_name"
    android:name=".activity.DialogActivity"
    android:theme="@style/CustomTheme.Screen.Transparent" 
    android:windowSoftInputMode="adjustResize">

Unfortunately when you click on an edit text inside of the dialog, no resizing takes place. The windowSoftInputMode literally makes no difference as the functionality is the same as pan mode.

Documentation says "This of course only works for applications that have a resizeable area that can be reduced to make enough space" but doesn't tell you what it means by "a resizeable area" and makes me think that in some way I don't have a resizeable area?

If anyone knows what's up can they help me out?

EDIT

Surrounding the dialog like so doesn't change anything:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerPageConatiner"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <FrameLayout    
        android:id="@+id/dialogHolder"
        android:layout_height="wrap_content"
    android:layout_width="wrap_content"
        android:padding="15dp"
        android:layout_gravity="center"
        android:background="@drawable/panel_picture_frame_bg_focus_blue"/>

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

EDIT2

Scrollview as parent doesn't help either:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerPageConatiner"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
            android:id="@+id/dialogHolder"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:padding="15dp" />

</ScrollView>
Rahul Tiwari
  • 6,851
  • 3
  • 49
  • 78
Graeme
  • 25,714
  • 24
  • 124
  • 186
  • use one EditText for checking. click inside the edittect to display the soft keyboard, now you can see the use of this android:windowSoftInputMode=“adjustResize”. is you use adjustNothing even keyboard shows your layout should not get any change. – Padma Kumar Dec 06 '11 at 10:53
  • Sorry, I don't understand you. – Graeme Dec 06 '11 at 11:06

9 Answers9

52

I created a new project in order to try and get the basic features working for window resizing and the slowly moved it towards the target peice of my project. Doing this I tracked the problem down to this:

In my theme hierarchy I had this property:

<item name="android:windowFullscreen">true</item> 

which was burried at the level of Theme.Black.NoTitleBar.FullScreen - An ancestor of my custom theme.

The documentation suggests that this is a "Flag indicating whether this window should fill the entire screen". That sounds like a good thing to have if you have an app which takes up the whole screen... Except it still takes up the whole screen without the flag.

In fact, once you've taken this out, there is absolutely no change in the app at all... apart from adjustResize now works perfectly.

Graeme
  • 25,714
  • 24
  • 124
  • 186
  • 7
    Thanks for this post! But I want fullscreen and resizing. :( – lippo Oct 05 '12 at 19:14
  • 3
    Have a re-read of the answer. No matter if `windowFullscreen` is set to true, false or isn't present, your Activity will still be fullscreen. – Graeme Oct 08 '12 at 08:27
  • ok. I think my problem was, that I had no own theme. It works like you write with an own theme. :) – lippo Oct 13 '12 at 21:28
  • 3
    When I remove android:windowFullscreen from my custom theme, it stops being fullscreen unfortunantly (os 4.1). Can you post complete code of your theme please? Maybe there is something I'm missing in my implementation. – Alexey Dec 05 '12 at 07:36
  • 1
    I will add my observation. Graeme is right about android:windowFullscreen attribute. It hides the status bar (on top with clock and notifications and such). A consequence of this is that attribute android:windowSoftInputMode set at adjustResize does not function as expected. When the soft keyboard is shown the activity takes all available space and it is not aware that some is taken by soft keyboard. Therefore it is not possible to scroll to the bottom of activity. – Anderson Jul 02 '14 at 09:25
  • What is interesting though that this occurs on newer APIs. I tested it on API 19. On device with API 10 (2.3.5) adjustResize works. They activity is aware that keyboard takes place, and it is possible to scroll to the bottom with keyboard visible. A side not: It is demanded that if you hide status bar you should also hide action bar. – Anderson Jul 02 '14 at 09:26
  • I don't think this is a valid 'fix' as it brings back the notifications bar; something we are trying to achieve as well as adjustresize – Le-roy Staines Nov 29 '14 at 22:20
  • It's been a while, but I'm pretty sure `windowFullscreen` doesn't effect the title bar. Ensure you have on of the "NoTitleBar" themes as an ancestor. – Graeme Dec 03 '14 at 16:52
  • Wonderful, saved me. – Milad Moosavi Nov 21 '17 at 09:00
  • Great, Worked for me. (no solution worked but this one worked for me) – Tushar Ahmed Aug 07 '20 at 06:58
50

A while back i also had the same issue in a library i've created. (MaterialDrawer)

As far as i can see all the provided answers don't solve the main issue, they just point to remove the fullscreen flag (android:windowFullscreen), which is no solution for many out there.

The above mentioned "issue" only appears in Android versions starting with API Level 19 (KITKAT), because they changed the behavior. To be correct it is no issue, it is working as intended. See the comment by a Android employee (Android-Issue).


So i started digging around the Android source and came to the following solution by using the ViewTreeObserver.OnGlobalLayoutListener and reacting if the Keyboard gets shown / or hidden. If the Keyboard gets shown i add the padding to the bottom of the container view which will then emulate the same as the adjustResize would do.


Solution

To simplify the usage i've wrapped the whole thing in a simple KeyboardUtil helper class.

/**
 * Created by mikepenz on 14.03.15.
 * This class implements a hack to change the layout padding on bottom if the keyboard is shown
 * to allow long lists with editTextViews
 * Basic idea for this solution found here: http://stackoverflow.com/a/9108219/325479
 */
public class KeyboardUtil {
    private View decorView;
    private View contentView;

    public KeyboardUtil(Activity act, View contentView) {
        this.decorView = act.getWindow().getDecorView();
        this.contentView = contentView;

        //only required on newer android versions. it was working on API level 19 (Build.VERSION_CODES.KITKAT)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

    public void enable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

    public void disable() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }


    //a small helper to allow showing the editText focus
    ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            //r will be populated with the coordinates of your view that area still visible.
            decorView.getWindowVisibleDisplayFrame(r);

            //get screen height and calculate the difference with the useable area from the r
            int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
            int diff = height - r.bottom;

            //if it could be a keyboard add the padding to the view
            if (diff != 0) {
                // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                //check if the padding is 0 (if yes set the padding for the keyboard)
                if (contentView.getPaddingBottom() != diff) {
                    //set the padding of the contentView for the keyboard
                    contentView.setPadding(0, 0, 0, diff);
                }
            } else {
                //check if the padding is != 0 (if yes reset the padding)
                if (contentView.getPaddingBottom() != 0) {
                    //reset the padding of the contentView
                    contentView.setPadding(0, 0, 0, 0);
                }
            }
        }
    };


    /**
     * Helper to hide the keyboard
     *
     * @param act
     */
    public static void hideKeyboard(Activity act) {
        if (act != null && act.getCurrentFocus() != null) {
            InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
        }
    }
}

You can then use it in your activity or fragment by doing the following:

//initialize the KeyboardUtil (you can do this global)
KeyboardUtil keyboardUtil = new KeyboardUtil(activity, getContent().getChildAt(0));

//enable it
keyboardUtil.enable();

//disable it
keyboardUtil.disable();

The whole util class is used in the above mentioned library MaterialDrawer and can be found here KeyboardUtil. This will always contain the latest version. (if there are improvements)

GuilhE
  • 11,591
  • 16
  • 75
  • 116
mikepenz
  • 12,708
  • 14
  • 77
  • 117
  • the 73 of the comment is just information that this was the dp on my device. you do not have to set this or anything. i only keep the initial height to prevent issues with the detection – mikepenz Nov 27 '15 at 11:53
  • In an app that uses different themes, you may want to query if the current window has the `WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS` or `FLAG_TRANSLUCENT_NAVIGATION` set before applying the fix. Fixed an issue I came across on my side. – Richard Le Mesurier Dec 03 '15 at 10:53
  • An interesting effect happens if the screen has a numeric field and an alpha field on it. Clicking first on the numeric field adjusts the screen correctly, then changing to the alpha field makes the keyboard get bigger (autocorrect solutions sit above the keyboard), and screen does not re-adjust. – Richard Le Mesurier Dec 03 '15 at 10:55
  • @RichardLeMesurier thanks a lot for all your testing. i know that this solution is not perfect. and is still only a partial work around for the main android issue. i still hope for someone to get a real solution for this. which will work in 100% of all use cases, without any strange edge cases as described by you – mikepenz Dec 04 '15 at 00:25
  • 1
    you have the only working solution I have found so far - nice work! If I manage to work around this edge case, I will be sure to let you know. – Richard Le Mesurier Dec 04 '15 at 05:21
  • Im using this solution and it works great. But one problem is that the snackbar and FAB is showing up somewhere over the appbar. Any idea how I can fix that ? Thank you for the solution btw – Vineet Ashtekar Feb 28 '16 at 14:27
  • Hi, first of all thanks for the util class! I suggest to not only check if the API level is greater than 19, but also check if the activity window is in fullscreen mode. In our app you can toggle fullscreen and so it's much more convenient to check the fullscreen flag inside the KeyboardUtil. – rekt0x Mar 02 '16 at 07:50
  • great solution, and the only one working I've found. Thanks a lot man! – Analizer Apr 05 '16 at 08:23
  • Only issue I've found is that after the keyboard is hidden, the image in the navigation drawer header got a little smaller, the placeholder behind it can be seen below the statusbar. Anyone experiencing the same? – Analizer Apr 05 '16 at 08:30
  • 1
    It works for me! However, I don't know why "getContent" didn't work for me, but I replace it with: ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0) – cuble Apr 13 '16 at 15:25
  • I tried various settings to get this to work. This is the only one that worked for me! Thank you! – Surekha May 09 '16 at 20:30
  • while using forms inside Coordinator layout only this solution works fine !!!! thanks @mikepenz – LOG_TAG Feb 17 '17 at 09:19
  • Thanks for your answer!! – Manmohan Pal Jun 14 '17 at 17:11
  • @mikepenz I have tried this solution but it only works on some devices. It works on OnePlus 3 (7.1.1) and Blu X2 (5.1) but NOT on LG Lucid 2 (4.1.2) or Galaxy S3 4.4.4. Do you have any suggestions on what I should try for the older devices? Thank you – alexgophermix Jun 14 '17 at 18:52
  • @alexgophermix well I think on 4.x this util should not be necessary as, as far as I remember, on these devices the behaviour is different. Just debug into the source and see what's different and why it does not do what you expect – mikepenz Jun 18 '17 at 14:28
2

It seems that the problem is with FrameLayout, as it behaves that way, that each child occupying visible space of that frame, therefore no need to resize to fit children. Try to use RelativeLayout. It should work.

acm0x
  • 775
  • 6
  • 14
  • 1
    Exact same problem with RelativeLayout in place of FrameLayout. As you can see from the edit LinearLayout doesn't help either. – Graeme Dec 06 '11 at 10:36
  • try to add android:fillViewport="true" to ScrollView – acm0x Dec 06 '11 at 14:19
  • +1 frameLayout was not playing nice with android:windowSoftInputMode="adjustResize" for me, moving the view outside of my frameLayout fixed it. This was only not working on 4.0.4 however – Dori Oct 07 '13 at 11:32
1

Without using a ScrollView as my parent I just added android:fitsSystemWindows="true" to my parent view (which was a RelativeLayout) and adjustResize to the Manifest for the activity and it worked.

Josh Laird
  • 6,974
  • 7
  • 38
  • 69
0

I've had to set

<item name="android:windowFullscreen">false</item> 

Despite, I've never set it to true and app actually wasn't full screen.

loler
  • 2,594
  • 1
  • 20
  • 30
0

Try to put your LinearLayout on a ScrollView, that worked for me once..

Cata
  • 11,133
  • 11
  • 65
  • 86
  • 2
    Even using a ScrollView as the parent, clicking on an EditText inside the dialog doesn't resize any part of the screen. – Graeme Dec 06 '11 at 11:47
-1

As original poster discovered when the Fullscreen Flag is assigned to an activity the android:windowFullscreen attribute will not work and so your window will not resize when the soft keyboard is visible and it won't be scrollable.

Simply removing the Fullscreen flag and not using a Fullscreen theme will allow scrolling when the soft keyboard is visible.

RichTurner
  • 797
  • 7
  • 14
-1

I don't know why, but if you have <item name="android:windowTranslucentNavigation">true</item> in your theme, change it to false. And it will start working. Really strange.

Nastromo
  • 622
  • 1
  • 9
  • 16
-3

Ensure you set windowTranslucentStatus to false in your styles.

YTerle
  • 2,606
  • 6
  • 24
  • 40