I want to make so my status bar is transparent, but also without icons on it. I managed to make it so that bar disappeared, but then it left a line that isn't filled with the background. I want to change that so i can actually see the background without any icons being in the way.
Also, I'm testing it on Xiaomi Redmi Note 8T
Code (with the result seen on the 1st picture)
MainActivity.kt
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
class MainActivity : AppCompatActivity() {
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) hideSystemUI()
}
private fun hideSystemUI() {SYSTEM_UI_FLAG_IMMERSIVE_STICKY
window.decorView.systemUiVisibility =
(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or 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)
}
override fun onCreate(savedInstanceState: Bundle?) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Both themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.TestingSystemModes" parent="Theme.Design.NoActionBar">
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
</style>
</resources>
Here is how it looks with that line:
I want it to look like in the picture below, but without that status bar's icons:
EDIT:
I think, it's phone that makes it like that ( in the center there is a camera ) and probably the black line is made to blend in the camera. That's why, whatever i did it didn't disappear. Still, thanks a lot to everyone who tried to help me.
The problem:
Phone's can now have a "cut-out" (for notched phones etc. etc.), and when you hide the status bar properly, the phone thinks "ok, I need to make the former status bar just a black cut-out so it doesn't look silly."
The solution:
There's actually four things you need to do:
Tell Android you don't want status bars in the app (hide them). There is now a correct, backwards compatible way of doing this which I will detail below.
Tell Android to draw the app behind the cut-out area.
Tell Android that your layout should NOT fit the system window (if you don't do this, it will STILL put your layout within the space where the status bar used to be)
Manually adjust the bottom insets, as when you tell Android your layout should not fit the system window (step 3), unfortunately that's going to include the Navigation Bar, so if you don't adjust for this then your layout will be under the nav bar which may be undesirable.
The Code:
The below is a neat little extension function that will cover steps 1 and 3... (hide the status bars, set decorFitsSystemWindows to false). This allows, in your activity to simply put window.setInImmersiveMode()
fun Window.setInImmersiveMode() {
val windowInsetsController = ViewCompat.getWindowInsetsController(decorView) ?: return
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
windowInsetsController.hide(WindowInsetsCompat.Type.statusBars())
WindowCompat.setDecorFitsSystemWindows(this, false)
}
You need to change your themes.xml to tell Android to draw behind these cutouts, with this line (api 27 and above only, hence the tools:targetApi part):
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
And finally, there's a slightly more complex bit of code to handle setting up the bottom insets for your layout - again I've made it into an extension function so you can call view.setupInsets():
fun View.setupInsets() {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
bottomMargin = insets.bottom
}
WindowInsetsCompat.CONSUMED
}
}
Set these properties in your theme. Thats all
<item name="android:windowTranslucentStatus">true</item>
you can use below lines to make it transparent or can set fix color getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
getWindow().setStatusBarColor(ContextCompat.getColor(ContactUsActivity.this,R.color.white));// set status background white
Related
Since Android released the new Splash Screen API with Android 12, a lot of apps had issues with duplicate splash screens, lack of customization, etc.
Right now, it is possible to set the background color and icon in the middle of it, but is it possible to customize it a bit more? Since right now we are limited to use single-colored background and non-resizable logo icon which doesn't look quite good.
What I'm trying to achieve is a custom splash screen, with an image drawable as background (or layer-list with 2 items - one background image and one centered logo), as it could be used before Android 12.
Did someone succeed to achieve this type of behavior?
There is a workaround to set windowIsTranslucent attribute to true and show only the second splash (the right one), but it introduces bad UX since it seems like the app is not responding for a few seconds.
Short answer is No, but here in my answer you can find more info:
Android: How to set a drawable as a windowSplashScreenBackground parameter in the new SplashScreen API?
I did something like this.
First remove default drawable
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">#color/...</item>
<item name="windowSplashScreenAnimatedIcon">#android:color/transparent</item>
<item name="postSplashScreenTheme">#style/AppTheme</item>
</style>
Then inflate your custom splash view
class MainActivity : AppCompatActivity(), SplashScreen.OnExitAnimationListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val installSplashScreen = installSplashScreen()
installSplashScreen.setOnExitAnimationListener(this)
setContentView(R.layout.activity_main)
}
override fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
val view = splashScreenViewProvider.view
if (view is ViewGroup) {
val binding = ActivityMainSplashBinding.inflate(layoutInflater,view, true)
// Do what you want with your inflated view
animate(view) {
// Remove splash
splashScreenViewProvider.remove()
}
}
}
private fun animate(view: View, doOnFinish: () -> Unit) {
view.animate()
.withEndAction(doOnFinish)
.start()
}
}
At the end remember to call splashScreenViewProvider.remove() to remove splash.
I followed the Android dev tutorial and got full screen sticky immersive mode working. This makes the status bar and navigation bar hidden until the user swipes up from the bottom or down from the top, at which point they appear and slowly fade out if not used.
The problem is on Android 10 (and possibly other versions): the navigation bar at the bottom of the screen is just white icons. There's no transparent black background. This makes it really hard to see with a light UI.
Is there any way to change the background or icon colors of the navigation bar? Specifically the sticky immersive navigation bar that appears and fades away (since it is too light to work with light UI's).
I've tried styles and setting the color programmatically, but they only work in non-full screen mode:
<!-- does not work -->
<item name="android:navigationBarColor">#android:color/white</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowLightNavigationBar">true</item>
I've also tried listening to OnSystemUiVisibilityChangeListener so I could show my own transparent bar behind the navigation bar, but it doesn't trigger for sticky immersive mode (as explained in this SO post and video):
Detecting when the system ui is visible with sticky immersive mode
https://www.youtube.com/watch?v=cBi8fjv90E4&feature=youtu.be&t=6m56s
Activity code for setting full screen (kotlin):
protected fun isFullscreen() = defaultSharedPref.getBoolean(SharedPreferenceKey.IS_FULL_SCREEN, false)
private fun supportsFullscreenMode(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus && isFullscreen()) toggleFullScreenMode(true)
}
/**
* "sticky immersive" full screen mode.
* When user swipes from top/bottom edge, transparent status bar and navigation bar appear and slowly fade out if not used.
* https://developer.android.com/training/system-ui/immersive
*/
protected fun toggleFullScreenMode(goFullScreen: Boolean) {
when {
!supportsFullscreenMode() -> {
makeActivityToast("Your version of Android is too old to support this feature", Toast.LENGTH_LONG).show()
}
goFullScreen -> {
hideSystemUI()
}
!goFullScreen -> {
showSystemUI()
}
}
}
private fun showSystemUI() {
window.decorView.systemUiVisibility = 0
}
private fun hideSystemUI() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// Hide the nav bar and status bar
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN)
}
In the app, I have status bar and hide the bottom control bar.
Last time, I used marginTop="20dp" to fits the under line of status bar. However, I tested out with Galaxy 10 And the status bar is very different. So, My app looked weird, And solved the problem with applying this attribute at the root view.
fitsSystemWindows = "true"
However, Now, I have another problem, that the bottom control bar is hid but there's empty space as big as the bottom control bar after applying the attribute. Is there any way to fits the screen that shows status bar and no bottom control bar(While I hide it)?
(Yellow one is MainActivity and Black one is Fragment)
The pink part must reach the bottom, but it can't reach because of that attribute.
I tested and I think just happens with kitkat and Q.
When I remove that attribute it works with the bottom control bar, but not the status bar...
this is my layout file.
<FrameLayout 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:fitsSystemWindows="true"
tools:context="com.example.main.MainActivity">
<fragment
...
/>
...
</FrameLayout>
So, I use only one Activity which has lots of Fragments.
And this is what Activity use:
private fun hideStatusBar() {
DisplayUtil.hideStatusBar(this)
this?.window?.decorView?.setOnSystemUiVisibilityChangeListener { visibility ->
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
DisplayUtil.hideStatusBar(this)
}
}
}
object DisplayUtil {
fun hideStatusBar(activity: Activity?) {
activity?.window?.decorView?.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY // hide status bar and nav bar after a short delay, or if the user interacts with the middle of the screen
)
}
}
I have to make layout, where top of the layout should be drawn under SystemBars. (min API level for this app is 22)
I set these flags to achieve that. In other activities I can draw whole fragment with views under SystemBars, but here I cant do it.
I used this code to allow layout to be drawn under SystemBars
window.apply {
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
statusBarColor = resources.getColor(android.R.color.transparent)
navigationBarColor = resources.getColor(android.R.color.transparent)
setBackgroundDrawable(background)
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
This is result in app:
I need to draw that grey area under system bar.
Update:
#Redman solution worked only partially.
Now I can draw under StatusBar but also I can draw under software buttons (navigationButtons) as you can see at screen below. Is there any way how to allow layout to be drawn under SystemBars but do not allow it under navigationButtons? Because that code what I've posted works for different fragments in app. But in other fragments I don't have ImageView as a part of ToolBar. If you have just ToolBar with for example 2-color gradient background and some backButton + SearchView, it is working fine. But as I add ImageView, ImageView will not "slide" under top SystemBar(aka StatusBar). Even in image above you can clearly see that green color (it's ToolBar background drawn under StatusBar). But ImageView is not allowed to be drawn under that bar.
The only way how to achieve that was with that special line of code
window.apply {
setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
}
but this line also allowed to draw layout content under NavigationButtons (which is an issue).
In your Activity Theme add these properties
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
and in parent layout add property
android:fitsSystemWindows="true"
Edit
Try this to do it programmatically, it should work above on devices having kitkat and above
window.apply {
setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
}
use toolbar view in your xml file. See below example
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="#dimen/height_50dp"
android:background="#f1f1f1">
\\define your any element here. Like back arrow or title
</android.support.v7.widget.Toolbar>
All you need to do is set these properties in your theme:
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
Your activity / container layout you wish to have a transparent status bar needs this property set:
android:fitsSystemWindows="true"
It is generally not possible to perform this for sure on pre-kitkat, looks like you can do it but some strange code makes it so.
EDIT: I would recommend this lib: https://github.com/jgilfelt/SystemBarTint for lots of pre-lollipop status bar color control.
Well after much deliberation I've learned that the answer to totally disabling the translucency or any color placed on the status bar and navigation bar for lollipop is to set this flag on the window:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window w = getWindow(); // in Activity's onCreate() for instance
w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
How about this:
Window window = getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(ContextCompat.getColor(this, R.color.primary_dark));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
window.addFlags(flags);
}
This should make Only StatusBar transparent.
If this didn't help, try adding:
<item name="android:windowTranslucentStatus">true</item>
To the Activity styles code in styles.xml.
I know that I can make the ActionBar overlay using requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY)
and can toggle/show the status bar in my screen (by switching between FLAG_FULLSCREEN and FLAG_FORCE_NOT_FULLSCREEN).
This works great. However, I don't want my layout moving when I toggle the status bar.
I know that I can make the status bar "overlay" (albeit not transparently) the content using:
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
This works also great, except for the (expected) consequence that, when using an ActionBar, the ActionBar gets half cut off - half of it is under the status bar basically.
So I am wondering, is there a way to "move the ActionBar down" by the status bar's height in this case?
I know that in worse case, I can do this with a custom view that lives within the layout, but I rather not do this (want to benefit from the ActionBar).
thanks!
so apparently, you can do this in Jellybean. google includes two examples in the api docs. here is a link: http://developer.android.com/reference/android/view/View.html#setSystemUiVisibility%28int%29
summary:
use setSystemUiVisibility on a view to toggle visibility (on jellybean+).
It's not perfect, but this is how I have achieved what you want:
In onCreate:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Then:
private void hideStatusBar() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
}
private void showStatusBar() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
I also have a style on the activity with the following:
<style name="readingStyle" parent="#style/Theme.Sherlock">
<item name="android:windowActionBarOverlay">true</item>
<item name="windowActionBarOverlay">true</item>
</style>
Your activity will shift down when the status bar shows, but I don't think it's too noticeable.
Why you dont make it in the Manifest
android:theme="#android:style/Theme.Black.NoTitleBar"
than you have no statusbar and more space for the Actionbar??
Put this method in onCreate() method activity:
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
refer: link