Android 12 ignoring showSoftInput as VIEW is not served - android

My app worked fine for lots of devices. But since upgrading to Android 12 on my own Pixel the following happens when calling showSoftInput or just when tapping the AppCompatEditText in a Bottomsheet.
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager;
imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
Logcat warning (nothing happens in the app):
Ignoring showSoftInput() as view=androidx.appcompat.widget.AppCompatEditText{b5311a0 VFED..CL. .F.P..ID 84,0-996,118 #7f0900a7 app:id/et_bottomsheet aid=1073741827} is not served.
I tried lots of things like requesting focus, showSoftInput with SHOW_FORCE but nothing worked.

Starting from Android 11 (API 30) you can manually force the ime/keyboard to show with inset's API show()
myAppCompatEditText.windowInsetsController.show(WindowInsetsCompat.Type.ime())
And hide it with:
myAppCompatEditText.windowInsetsController.hide(WindowInsetsCompat.Type.ime())
To targed APIs below API 30, This is backported using the Compat version:
WindowInsetsControllerCompat(window, myAppCompatEditText)
.show(WindowInsetsCompat.Type.ime())
WindowInsetsControllerCompat(window, myAppCompatEditText)
.hide(WindowInsetsCompat.Type.ime())

Solution:
The problem seems to be that the keyboard couldn't gain window focus?
Anyways, the parts that were causing problems were:
window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
window?.decorView?.systemUiVisibility = fullscreenFlags
and
private const val fullscreenFlags = (View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_IMMERSIVE
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
I removed them for now on SDK 33+, which kind of breaks the hiding of navigation elements that I had before but it's the only way I could fix this quickly.
Now everything seems to work.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) doThose()

Related

Android studio, kotlin fails when trying to use immersive mode

I'm trying to learn android studio, android, and kotlin. Mostly this has been straightforward but with a few glitches. One such glitch is the following for which I could use some help:
I'm trying to create a phone view in immersive mode. According to the documentation (https://developer.android.com/training/system-ui/immersive) the following function should do the trick.
private fun hideSystemBars() {
val windowInsetsController =
ViewCompat.getWindowInsetsController(window.decorView) ?: return
// Configure the behavior of the hidden system bars
windowInsetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// Hide both the status bar and the navigation bar
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
}// end hideSystemBars function
I set this in the main Activity onCreate function as follows
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
requestWindowFeature(Window.FEATURE_NO_TITLE)
supportActionBar?.hide()
setContentView(binding.root)
hideSystemBars()
}// end onCreate function
Unfortunately I seem to missing something basic as this always fails because
ViewCompat.getWindowInsetsController(window.decorView) always returns null (I ran several tests to verify this)
I've verified that window.decorView is not null and looks okay. As a precaution I replaced the hideSystemBars() function call with window.decorView.doOnLayout {hideSystemBars()} in case the layout wasn't complete but this doesn't help. In fact, from some addition tests I ran use of the window.decorView.doOnLayout {} doesn't seem to work either no matter what function is used in the brackets (another glitch I don't understand)
I think I may be missing something basic (and possibly trivial) but cannot seem to discover how to make this work. Any help will be appreciated.
Maybe you should check your API Level on the device. The following solution works for me.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView) ?: return
// Configure the behavior of the hidden system bars
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// Hide both the status bar and the navigation bar
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
}else{
val flags =
(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
window!!.decorView.setSystemUiVisibility(flags)
}

Customize Full-Screen Behaviour

Per the android docs, we can make an activity go full-screen by adding the following block of code in the onCreate method (inside setContent{...}, specifically, if you are using Compose)
val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView)
windowInsetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
However, this seems to only hide the information displayed on the statusbar, replacing it with just a black stripe.
Now, my question is - How can we modify the color of this stripe so that the UI of the app seems to extend to the entire display?
I am not sure where to start but I've heard accompanist MAY have something related to this, but I thought it better to post this question here, so that if anyone already knows a way around, they may share since it will be helpful to the community.
Other than that, solutions that do not involve accompanist are also welcome, and may be even preferred.
For reference, here's the output as of now
Notice the black bar at the top? That's the target.
copy and paste it in onCreate method after result you can understand
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val window: Window = window
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
val decorView: View = window.getDecorView()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
window.setStatusBarColor(Color.TRANSPARENT)
}

Xamarin Forms How to change Android status bar icon color in API 30 (Android 11)

I have a Xamarin.Forms app being built for iOS and Android.
I'm having some difficulty in Android updating the icon colors when setting the status bar color. I have this working for API levels below 30 using the following code:
var isLight = false;
Window currentWindow = Platform.CurrentActivity.Window;
if (Color.FromHex(hexColor).Luminosity > 0.5)
{
isLight = true;
}
currentWindow.SetStatusBarColor(androidColor);
currentWindow.DecorView.SystemUiVisibility = isLight ? (StatusBarVisibility)(SystemUiFlags.LightStatusBar) : 0;
From what I can tell, DecorView.SystemUiVisibility is deprecated in API 30, and is supposed to be replaced with window.insetsController
What I can't figure out is if/where this API is exposed in Xamarin for me to use.
I looked at this SO question:
How to change the status bar color without a navigation page
and following the last answer, I attempted to use:
var lightStatusBars = isLight ? WindowInsetsControllerAppearance.LightStatusBars : 0;
currentWindow.InsetsController?.SetSystemBarsAppearance((int)lightStatusBars, (int)lightStatusBars);
but it will not build, saying Window doesn't have InsetsController
Has anyone figured this out? I definitely need to support the latest Android and this feature is killing me
Thanks in advance!
Your code looks correct. Change target framework to Android 11.0 (R). InsetsController was added in API level 30. Due to this you may receive build error.
public void UpdateStatusBarColor(String color)
{
Window.SetStatusBarColor(Color.ParseColor(color));
if (Build.VERSION.SdkInt >= BuildVersionCodes.R)
{
Window?.InsetsController?.SetSystemBarsAppearance((int)WindowInsetsControllerAppearance.LightStatusBars, (int)WindowInsetsControllerAppearance.LightStatusBars);
}
else
{
#pragma warning disable CS0618
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)SystemUiFlags.LightStatusBar;
#pragma warning restore CS0618
}
}
Can you please try this in MainActivity.cs
$ Window.SetStatusBarColor(Android.Graphics.Color.Argb(255, 114, 75, 203));

Android 11 - window.setDecorFitsSystemWindow doesn't show screen behind Status and Navigation Bars

I'm trying to update my App to Android 11. Many Screens of my App were Designed with App Content behind the StatusBar. I Updated my gradle to Android 11 and started updating the Window code to get the No Limit behavior also for Android 11 Devices.
I achived my desired result for pre Android 11 Devices with the folowing Code in my Activitiys onCreate method:
Window w = getWindow();
w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
I tried to get the same no limit behavior for Android 11 by using w.setDecorFitsSystemWindows(false);
I tried using it instead of using the flags, using it with flags and passing true and false, setting it before and after setting the flags but i always see a white status and system navigation bar instead of my Apps content behind them.
What i tried:
Window window = getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false); //also tried with true
} else {
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
//or
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false); //also tried with true
}
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
//or
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false); //also tried with true
}
My App still is in Java Code, i tried window?.setDecorFitsSystemWindows(false) in another app which uses Kotlin code and it worked without any troubles.
Does anyone have an idea what i'm missing or doing wrong here?
My App still is in Java Code, i tried window?.setDecorFitsSystemWindows(false) in another app which uses Kotlin code and it worked without any troubles.
Kotlin internally uses Java, so it does not matter whether you code in Java or Kotlin in terms of that insets API.
Probably, one of the view groups, which you use in your view hierarchy, consumes insets and does not propagate them to the child views. This was my case - my app is using DebugDrawer and window.setDecorFitsSystemWindows(false); didn't have any effect on the layout in my case. There is even the solution for that case. Maybe you could use it too, if you have a similar problem. It could be helpful to check the view hierarchy in the new Layout Inspector of Android Studio. Pay attention to the views that have attribute fitsSystemWindows = true. Also, that answer could be helpful.
For android 11 along with flags we also need to add below styles in the app theme
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>

View moving up in xamarin forms android when keyboard appears

The status bar and the screen moves up completely when the keyboard popsUp in xamarin forms android and the EditText field is in the bottom of the screen. I tried using
WindowSoftInputMode = SoftInput.AdjustPan
and
WindowSoftInputMode = SoftInput.AdjustResize
But unfortunately both are not working,i also clubbed both
From a blog post i read putting
Xamarin.Forms.Application.Current.On<Xamarin.Forms.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
and
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
Window.DecorView.SystemUiVisibility = 0;
var statusBarHeightInfo = typeof(FormsAppCompatActivity).GetField("_statusBarHeight", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
statusBarHeightInfo.SetValue(this, 0);
Window.SetStatusBarColor(new Android.Graphics.Color(0,0,0, 255)); // Change color as required.
}
after launch application is an alternative, but unfortunately this also failed. Any other option available?
Its a bug in Xamarin. I used following code in mainActivity
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
Window.DecorView.SystemUiVisibility = 0;
var statusBarHeightInfo = typeof(FormsAppCompatActivity).GetField("_statusBarHeight", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
statusBarHeightInfo.SetValue(this, 50);
}
And used
Xamarin.Forms.Application.Current.On<Xamarin.Forms.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
The problem was it wont work if you forcefully hide the title bar
Forms.SetTitleBarVisibility(AndroidTitleBarVisibility.Never);
I commented out this code and the issue was solved.
But due to resize property i faced lot of issue since i have designed screens with Grid and star value which caused many unwanted issues.
So i am not going to use this method sadly. :(

Categories

Resources