Prevent android activity from expanding into navigation bar - android

I am using a NativeActivity with the style #android:style/Theme.DeviceDefault.NoActionBar.FullScreen. However, the Activity expanded behind the system navigation bar, which is not what I want.
(Black region on the left is due to device cutout, which is what I intended)
I tried to search about this topic and couldn't find posts addressing this problem. Any help would be appreciated.
The effect that I intend would be like:

You can try this function. It will remove only status bar. Call this on onCreate().
private fun hideStatusBar() {
WindowCompat.getInsetsController(window,window.decorView).apply {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(WindowInsetsCompat.Type.statusBars())
}
}
To hide only navigation bar,
use hide(WindowInsetsCompat.Type.navigationBars())
To hide both status and navigation bar,
use hide(WindowInsetsCompat.Type.systemBars())
Additional thing, if you need this in multiple activities, you can create a BaseActivity and call this in BaseActivity on create and extend required activities with BaseActivity. So it will work for activities that extend BaseActivity
Here is Java Equivalent.
private void hideSystemBars() {
WindowInsetsControllerCompat windowInsetsController =
WindowCompat.getInsetsController(getWindow(),getWindow().getDecorView());
windowInsetsController.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
);
windowInsetsController.hide(WindowInsetsCompat.Type.statusBars());
}
Hope it helps
Read more here

Related

How can I prevent options menu icons flickering in the action bar when switching between fragments?

I am trying to migrate from the deprecated setHasOptionsMenu()/onCreateOptionsMenu() methods to the new addMenuProvider()/onCreateMenu() methods in order to show an options menu from a fragment. Using the new API, I get an ugly delay/flicker of the icons in the action bar when navigating between two fragments that both implement MenuProvider.
I assume this is caused by asynchronous lifecycle callbacks: the new fragment's menu is probably inflated and added just before the old fragment's Lifecycle.Event.ON_DESTROY event triggers the removal of the old menu items, causing a brief moment when both menus are active simultaneously. However, I can't figure out how to avoid this behavior. I have tried calling both removeMenuProvider() and invalidateOptionsMenu() from onDestroyView() in each fragment with no success. I also tried moving addMenuProvider() to onViewCreated() instead of onCreateView(). The issue does not occur with the old setHasOptionsMenu() API.
Minimal reconstruction:
Open Android Studio, create a new project, and select the "Bottom Navigation Activity" template.
Create two menu resource files, each containing at least one menu item with an icon and app:showAsAction="always".
In two of the fragments shown by the bottom navigation controller, call the following from within onCreateView():
requireActivity().addMenuProvider(object: MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(/* one of the menus from step 2 */, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return false
}
}, viewLifecycleOwner)
Run the app and switch between these fragments using the bottom navigation bar. You should see something like this: example gif.
Got the answer from some nice people on the Buganizer: see https://issuetracker.google.com/issues/243679672.
In short, use addMenuProvider(/* provider */, viewLifecycleOwner, Lifecycle.State.RESUMED)
Using addMenuProvider(/* provider */, viewLifecycleOwner, Lifecycle.State.STARTED) seems to prevent a brief moment where no menu icons are visible (while also preventing overlap of the menus), though this seemingly contradicts the lifecycle state transitions that occur during animation as described in the link above...

Login - Navigation Architecture Component

I implemented conditional navigation to my LoginFragment, with android navigation architecture component. The problem I facing now, is that I would like to hide the up button on the toolbar, and the disable any in-app navigation while the user is not logged in.
I would like to be able to implement this with a one-activity approach, where the Activity sets up the in app navigation UI and the navController like in the android sunflower demo, and the navigation destinations are Fragments.
I implemented the conditional navigation as discribed here:
Navigation Architecture Component - Login screen
How can I properly implement hiding the navigation and the up button on the login screen, with Navigation Architecture Component?
I don't know exactly what you mean by hiding navigation, but I will assume you mean hiding a drawer layout. To hide the up button and lock the drawer add the following to your MainActivity's onCreate. I'm using Kotlin.
myNavController.addOnDestinationChangedListener { _, destination ->
if (destination.id == R.id.loginFragment) {
myDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
myToolbar.setVisibility(View.GONE)
} else {
myDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
myToolbar.setVisibility(View.VISIBLE)
}
To make just the up button go away use myToolbar.setNavigationIcon(null) and to make it come back use myToolbar.setNavigationIcon(R.id.my_icon)
My method is adding the login page to the root set
val navController = findNavController(R.id.main_nav_host)
val appBarConfiguration = AppBarConfiguration(setOf(R.id.home_dest,
R.id.user_dest,R.id.login_dest))
toolbar.setupWithNavController(navController, appBarConfiguration)
So when you are on the login page, there is no back button.
System back button can override onBackPressed()
override fun onBackPressed() {
if (findNavController(R.id.main_nav_host).currentDestination?.id != R.id.next_dest)
super.onBackPressed()
}
}
Sorry for my English

Show View in all my app

I need show a TextView in all Activities, but is much work to do it one by one, because I have +10 Activities.
My objective is when I click in a button, show a textview ("Importing ...") at the bottom of the application. This textview will disappear when I receive a push notification, and I owe a pop up with the response (the pop up also has to appear in any activity).
My project has a custom abstract BaseActivity and all activities extends it.
public abstract class BaseActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
protected void setActionBar(#IdRes int idResToolbar) {
Toolbar toolbar = (Toolbar) findViewById(idResToolbar);
setSupportActionBar(toolbar);
updateFont(toolbar);
}
// ...
}
I think I could use for my purpose but not how to do it.
If anyone has any suggestions I will be happy to hear it.
Thanks in advance.
Use fragments for your content (instead of different activites) you then can add global views to the activity, which holds the fragments.
If you don't want to do that, you'd have to modify the layout(s) in your Base class.
I would suggest you to use a PopupWindow that contains the text view and create a separate class that initializes the PopupWindow on the basis of context given to it.
Now in all your Activities you will have the control of showing and hiding the window as you want. Make sure to make all utility methods required in the separate class to avoid coherence for example hiding and showing the window. setting text of text view of the window and etc.
You can write in onCreate() of your base activity something like
setContentView(R.layout.base_layout);
And in every other Activity at start of onCreate() method, just use super.onCreate()
And more than that to support different layouts add something like this in onCreate() (example for one of activities)
LayoutInflater inflater = getLayoutInflater();
inflater.inflate(R.layout.activity_1_layout,rootGroup)
where rootGroup is a ViewGroup in your Base Activity, in which you will add additional components for every other activity
Create a service, which creates a View which can be drawn over other apps (will require the relevant permission in the manifest)
You could use one of the open source libraries available like this or refer to this example
It's better you use fragments instead of using many activities. However, if you don't wanna do so, I suggest you create a factory which will generate a textview to all activities. Then you must add it into each activity's view.

Hide status bar in only one fragment and display it on the others

I have 3 fragments in my activity and I want to make one fragment full screen by hiding the status bar. When I exit that fragment, the status bar should reappear. How can I do that?
Its always better to define a function in your parent activity which will have the code to hide the status bar and calling that in your target fragment will hide the status bar for that fragment and when you are exiting the fragment in its stop method you can show the status bar again.
Let this be your method in activity,
public void hideStatusBar()
{
// your code depending upon what you have implemented
}
public void showStatusBar()
{
// your code depending upon what you have implemented
}
and then on fragment resume you can call this method like this,
((ParentActivity)getActivity()).hideStatusBar();
and to show it again for other fragment you can override the onStop of fragment,
((ParentActivity)getActivity()).showStatusBar();
Visit https://developer.android.com/training/system-ui/status.html
and
https://developer.android.com/training/system-ui/visibility.html
clearly explained how to hide and show statusbar in different android versions.
If you want to programmatically clear flags set with setSystemUiVisibility(), you can do so as follows:
activity?.window?.decorView?.systemUiVisibility = 0
https://developer.android.com/training/system-ui/dim
Kotlin version of show/hide-ing status bar from fragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).supportActionBar?.hide()
}

How to hide the actionbar in some activities

I have an application, when I test it in 2.3.3 the activities I want don't have an actionbar, but when I test it in emulator using 4.2, those activities have an action bar.
How can I remove the actionbar completely from those activities.
I tried this from here:
android:theme="#android:style/Theme.NoTitleBar"
Doesn't work.
If I use getActionBar().hide(), and test it on my 2.3.3 it crashes. And if I try getSupportActionBar().hide() i get error: The method getSupportActionBar() is undefined. Note: I am not extending actionbar activity. I am extending Activity.
(From the comments I wrote)
First, make your classes extends ActionBarActivity. Then call this method in the onCreate() callback of the activies in which you want to hide the action bar:
private void hideActionBar() {
//Hide the action bar only if it exists
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
}
You can hide the action bar with the getActionBar().hide() method (Or getSupportActionBar().hide is you are using support library.
or
You can call requestWindowFeature(Window.FEATURE_NO_TITLE); in onCreate method before calling setContentView.

Categories

Resources