Fullscreen DialogFragment with softInputMode adjustResize - android

So I have a DialogFragment that i expand to the whole screen in onResume with the following code:
val params = dialog?.window?.attributes
params?.width = ViewGroup.LayoutParams.MATCH_PARENT
params?.height = ViewGroup.LayoutParams.MATCH_PARENT
dialog?.window?.attributes = params as WindowManager.LayoutParams
I also use the following style:
<style name="AppTheme.FullscreenDialogFragment" parent="Theme.MaterialComponents.Light.Dialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowBackground">#color/background1</item>
</style>
Now I also want this to extend under the status bar and I do this via the following (I also set the status bar color to transparent):
dialog?.window?.decorView?.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE.addFlag(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
This all works completely fine, but now I want to adjust the softInputMode to adjustResize. And I just can't get it to work. It only works if I remove the Layout flags above. It works fine in normal fragments. Does anybody have an idea what I'm missing here or is it just not possible with a DialogFragment?

So my problem was not the DialogFragment but the fact that Android does not honor adjustResize when you make your layout draw under the system bars. To prevent this you need to listen to the Window insets and apply them as padding to your layout so that when the keyboard is open, the bottom inset makes your whole content smaller for that amount and the ScrollView can be scrolled to the bottom. I use the following library for insets:
https://github.com/chrisbanes/insetter

Related

Showing content behind status and navigation bar

This looks like a duplicate question but I am not able to do it. I want complete transparent(not translucent) status bar as well as navigation bar and want the content to appear behind them.
activity_details.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
tools:context="com.bitspilanidvm.bosm2017.DetailsActivity">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/q"
android:scaleType="centerCrop"/>
</LinearLayout>
v21 styles.xml
<resources>
<!-- Theme for API level > 21 -->
<style name="AppTheme" parent="AppBaseTheme">
<!--Customize your theme here. -->
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:navigationBarColor">#android:color/transparent</item>
</style>
In the activity java file
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
This is what I get.
How to get content behind the navigation bar?
If I add
<item name="android:windowTranslucentNavigation">true</item>
to my styles.xml
Here is what I get
As you can see, the content goes behind navigation bar but the navigation bar has to be translucent for this.
Is there any solution for this?
Add the FLAG_LAYOUT_NO_LIMITS flag within the Window. This will work for Android KitKat and above APIs. Example of this would be something like this:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
The reason why the FLAG_FULLSCREEN doesn't work is simply because the FULLSCREEN flag is for removing screen decors like status bar(which works for you). However Navigation bar is not a screen decor. The LAYOUT_NO_LIMIT flag allows the window to extend beyond the screen limit, hence Navigation bar also gets covered within this flag.
Also you could simply hide the navigation and status bar by setting the app in immersive mode.
EDIT
The API ViewCompat.setOnApplyWindowInsetListener solves issues which the android:fitsSystemWindows=”true” does not and window insets can be applied to a particular view. An example of this.
ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
params.topMargin = insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
});
Standard layouts like FrameLayout , LinearLayout or RelativeLayout will not pass window insets to their children, whereas material layouts will do (e.g. DrawerLayout , CoordinatorLayout ). So we can change our layout to any material one, or we can subclass a standard layout and pass the insets to the children of layout ourselves. We just have to override onApplyWindowInsets method.
#TargetApi(Build.VERSION_CODES.KITKAT)
#Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
int childCount = getChildCount();
for (int index = 0; index < childCount; ++index)
getChildAt(index).dispatchApplyWindowInsets(insets);
// let children know about WindowInsets
return insets;
}
Reference Documentation:OnApplyWindowInsetsListener, WindowInsets
I wanted to comment the accepted answer but i can't yet.
Just to warn everyone who'll take this approach
The FLAG_LAYOUT_NO_LIMITS let extend your root view outside of the screen bounds creating other concerns about your layout design. For example, this flag simply breaks form readability by forcing the system to ignore "adjustPan" and "adjustResize" flags
So, even though i still consider Ahbi's answer as the correct one, make sure that nothing breaks outside of the scope of this flag
BETTER SOLUTION:
Actually, i've just found a better way to achieve the same result, without breaking anything
This is my style file
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:navigationBarColor">#android:color/transparent</item>
</style>
And these are the flags that i set programmatically
w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
Setting the flag LAYOUT_HIDE_NAVIGATION (in combination with the style items) did the trick and my form still reacts to the adjustPan flag
If you want the image showing behind the status bar
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
but by doing this, fitsSystemWindows="true" is not working
toolbar overlaps to status bar.

DialogFragment gravity not showing dialog completely in corner

I want dialog to appear completely in corner. I am setting gravity this way:
Window win = dialog.getWindow();
WindowManager.LayoutParams wmlp = win.getAttributes();
wmlp.gravity = Gravity.TOP | Gravity.RIGHT;
wmlp.horizontalMargin = 0;
wmlp.verticalMargin = 0;
Margins don't affect anything here. Layout inspector also doesn't work on dialog so I can't really inspect what is setting margin/padding.
Can I show this dialog fragment completely in corner (without recreating custom overlay fragment over whole screen that acts as a dialog)?
That extra padding/margin may have something to do with the background drawable. Change the style of your dialog to set android:windowBackground and android:background to be transparent by doing something like this:
<style name="TransparentDialog" parent="#style/Theme.AppCompat.Light.Dialog">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:background">#android:color/transparent</item>
</style>
(I believe that android:windowBackground is important here, and you may not need to set android:background.)
Thanks goes to andrew who answered this question for helping to provide a solution.

EditText shows the status bar, or causes content above to move instead of resize

Background
I have a login Activity , which has a layout as such (vertically, from top to bottom) :
title (logo ImageView and TextView)
image&viewPager that takes the rest of the screen
EditTexts&login button, appear on top of #2 (covering a part of them), but at the bottom of the screen
I need to have this activity full screen, hiding the status bar, and when the soft keyboard appears, change the layout a bit for what's shown above #3 .
The problem
It seems that the combination of those requirements are quite problematic.
I have 2 main issues with them:
What I've made for sensing the soft-keyboard being shown- doesn't seem to work here even though it worked fine on other Activities.
When the soft-keyboard appears, it either re-shows the status bar, or it moves the content above the bottom area (#3) instead of resizing it, while also hiding the button at the bottom (of #3) and showing only the EditText as the first view above the soft-keyboard.
Since there is no way to really have a listener for when the soft-keyboard is shown/hidden, I had to create a customized layout that just tells me when its size has changed. When its height is reduced, I assume the keyboard is shown, and vice versa.
What I've tried
I've tried multiple variants of the layout. Doesn't seem to help
I've used this layout as the root of the fragment, to check if the soft-keyboard is shown (as it changes its size) :
https://stackoverflow.com/a/25895869/878126
Sadly, it works on all other activities except for this one.
I've tried various "windowSoftInputMode" values, including "adjustResize" and "adjustPan"
I thought the issues were because I use a transparent navigation bar, so I've disabled it and also disabled "fitsSystemWindows" for the bottom area (#3) .
I've tried this way to hide the status bar:
requestWindowFeature(Window.FEATURE_NO_TITLE);
and also this way:
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
} else
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
The current layout
here's a short description of the current layout:
<LayoutSizeChangedSensorFrameLayout>
<RelativeLayout>
#1
<LinearLayout vertical, aligned to parent-top>
<ImageView/>
<TextView/>
<CirclePageIndicator/>
</LinearLayout>
#2
<ImageView aligned to parent-bottom, and below #1 />
<ViewPager aligned to the ImageView from all sides/>
#3
<LinearLayout vertical, aligned to the parent-bottom>
<TextView/>
<EditText/>
<Button/>
</LinearLayout>
</RelativeLayout>
</LayoutSizeChangedSensorFrameLayout>
And this is the theme of the activity:
<style name="AppTheme.Material" parent="#style/Theme.AppCompat.Light.DarkActionBar">
...
<item name="windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowTranslucentNavigation" tools:ignore="NewApi">true</item>
<item name="android:windowTranslucentStatus" tools:ignore="NewApi">true</item>
<item name="android:navigationBarColor" tools:ignore="NewApi">#android:color/transparent</item>
</style>
The question
How come hiding the status bar doesn't work permanantly, or it affects what's shown when showing the soft-keyboard ?
How come my customized layout can't sense that the soft-keyboard is shown?
Are there any other ways to achieve what I've tried?
I managed to keep the status bar hidden when the soft keyboard shows, by doing the following 2 steps:
Adding the following in the onCreate of the activity:
//No title bar is set for the activity
requestWindowFeature(Window.FEATURE_NO_TITLE);
//Full screen is set for the Window
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
Setting windowFullscreento truein the theme:
<style name="CustomTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowFullscreen">true</item>
</style>
Unfortunately this is not a complete answer, but it might help you get some of the way.
In addition to adding FLAG_FULLSCREEN to window,
FLAG_FORCE_NOT_FULLSCREEN - this flag can also be cleared:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

Activity as dialog: Place in top left corner

I'm trying to place an Android activity that uses the Holo.Dialog theme in the top left corner of my application by using the following code in OnCreate():
var layoutParams = this.Window.Attributes;
layoutParams.Gravity = GravityFlags.Top | GravityFlags.Left;
(This is Mono for Android)
It kind of works, however there is a tiny gap between the actual corner and the beginning of my dialog, which you can see in the following screen shot:
https://www.dropbox.com/s/cyy9lglq5642nz1/device-2013-05-26-223855.png
Notice the gap between the menu box and the actual edge of the screen.
What can I do to remove that gap completly?
Turns out the problem is rather simple: Theme.Holo.Dialog defines a background that adds a transparent border around the dialog. This causes the spacing between the corner and the dialog.
Creating a custom style fixes it:
<style name="MyCustomDialog" parent="android:Theme.Holo.Dialog">
<item name="android:windowBackground">#null</item>
</style>
This overwrites the background and removes the spacing.

windowIsFloating attribute in Android theme

What does this attribute really do?
I've read the documentation and I understand what it's supposed to be. However, when I use it in a theme (I created a style with the android:Theme.Dialog as the parent), changing the value for this attribute doesn't seem to have any effect.
I don't know all of the effects of setting windowIsFloating to true, but one thing that I noticed is that when it is set to true, the activity would not expand the width to fill the screen, even if you set the layout width to match_parent (i.e. android:layout_width="match_parent")
From my experiments, it seems to affect how the window reacts to the soft input. It you set this to false, the window won't slide up when the keyboard becomes visible.
When you use Dialog Theme, this attribute default is true.
<style name="Base.V7.Theme.AppCompat.Light.Dialog" parent="Base.Theme.AppCompat.Light">
...
<item name="android:windowIsFloating">true</item>
...
</style>
And in this case, the Dialog will create PhoneWindow with this code:
if (mIsFloating) {
setLayout(WRAP_CONTENT, WRAP_CONTENT);
setFlags(0, flagsToUpdate);
}
It will cause contentView always wrap content as small as. You could set it to false or Manual update the Dialog window layout to MATCH_PARENT like this:
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
}
I was using really naïve code to show a bottom sheet dialog fragment. However, my dialog was covering bottom navigation bar in light mode. See the picture below:
After adding the item to my dialog theme, this issue got resolved.
<style name="myTheme" parent="Theme.MaterialComponents.BottomSheetDialog">
<item name="android:windowSoftInputMode">stateAlwaysHidden|adjustNothing</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowIsFloating">false</item>
</style>

Categories

Resources