Detect soft navigation bar availability in MIUI/Xiomi device pragmatically? - java

This question specific to the issue with Xiomi devices with MIUI over it.
How can I detect Fullscreen Mode (Gesture) or Navigation Button (soft navigation) is selected?
I Have tried a few solutions, but that does work on other devices but didn't work on Xiomi or MIUI.
I have tried this solution available on SO, so please provide another if you have.
1
public boolean hasNavBar (Resources resources)
{
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
return id > 0 && resources.getBoolean(id);
}
2
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
if (hasBackKey && hasHomeKey) {
// no navigation bar, unless it is enabled in the settings
} else {
// 99% sure there's a navigation bar
}
3
View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener
(new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
// TODO: The navigation bar is visible. Make any desired
// adjustments to your UI, such as showing the action bar or
// other navigational controls.
} else {
// TODO: The navigation bar is NOT visible. Make any desired
// adjustments to your UI, such as hiding the action bar or
// other navigational controls.
}
}
});
Any idea of how can I get to know that the navigation bar is currently visible or not?
I also tried to calculate the real width and available width, it seems like MIUI always returning the reserved with of navigation bar.
Thanks.

There is no need to detect if Soft input navigation bar is visible or hidden for full screen activity you can create style and apply style to activity.
<style name="Theme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds" tools:targetApi="lollipop">false</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
and add following line in activity :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
This is led you to stop the layout overlap from soft input navigation.

I have the same problem too. I found 2 solution:
This solution works for me for versions above Android Q.
public static int isEdgeToEdgeEnabled(Context context) {
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("config_navBarInteractionMode", "integer", "android");
if (resourceId > 0) {
return resources.getInteger(resourceId);
}
return 0;
}
If this method returns 2 then Full screen mode is enabled.
2.This solution works for me above Android Q and below it:
ViewCompat.setOnApplyWindowInsetsListener(
findViewById(android.R.id.content)
) { _: View?, insets: WindowInsetsCompat ->
navigationBarHeight = insets.systemWindowInsetBottom
insets
}
I used 2 method myself

Related

How can i anchor a Snackbar to the android soft navigation bar?

Thank you in advance!
I decided to implement a Snackbar with this method (which will later be called in onClick method):
public void showSnackbar(int selector, int textSelector){
String sOne = (String) getResources().getText(R.string.charPart1);
String sTwo = String.valueOf(selector);
String sThree = (String) getResources().getText(R.string.charPart2);
String sFour = sOne.concat(sTwo.concat(sThree));
String sFive = (String) getResources().getText(R.string.charPart4);
String sSix = sFour.concat(sFive);
Snackbar notification = Snackbar.make(getWindow().getDecorView().getRootView(), "PLACEHOLDER", Snackbar.LENGTH_SHORT);
if (textSelector==1){
notification.setText(sFour);
notification.show();
}
else if (textSelector==2){
notification.setText(sSix);
notification.show();
}
}
I am facing this problem:
The Snackbar is displayed behind the system navigation bar:
My first idea was, that i could use the method Snackbar.setAnchorView(View anchorView) to position the Snackbar above the system navigation bar / soft navigation bar. Description of setAnchorView(View anchorView):
By default, Snackbars will be anchored to the bottom edge of their parent view. However, you can use the setAnchorView method to make a Snackbar appear above a specific view within your layout, e.g. a FloatingActionButton. This is especially helpful if you would like to place a Snackbar above navigational elements at the bottom of the screen, such as a BottomAppBar or BottomNavigationView.
I would like to position the Snackbar above the system navigation bar, but i donĀ“t know how to query the view id of the system navigation bar.
Snackbar notification = Snackbar.make(getWindow().getDecorView().getRootView(), "PLACEHOLDER", Snackbar.LENGTH_SHORT);
// View systemNavigationView = findViewById(int id) ;
notification.setAnchorView(systemNavigationView);
notification.show();
Is it at all possible to assume that the android system navigation bar has an assigned id that can be retrieved?
I only found this method for detecting if it exists, but no approach for getting the View or the id of the view:
public boolean hasNavBar (Resources resources)
{
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
return id > 0 && resources.getBoolean(id);
}
You should place your snackbar inside a CoordinatorLayout view.

Fully Transparent Navigation Bar and Status Bar

I want to make a fully transparent status bar and navigation bar like Google Play did. When I use window settings to achieve it, the keyboard covers EditText.
When this code used EditText covered by Keyboard Input:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
Also this code doesn't make it fully transparent, it just makes it translucent
getWindow().setNavigationBarColor(Color.TRANSPARENT)
or this
<item name="android:navigationBarColor">#android:color/transparent</item>
I need a window like this:
What you need is something like this:
class Utils {
static void enableInmersiveMode(Activity act, boolean drawBehindNavBar) {
View rootView = act.getWindow().getDecorView().getRootView();
int uiFlags = rootView.getSystemUiVisibility();
int flags =0;
if(drawBehindNavBar) { flags = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; }
flags = flags | uiFlags | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEEN;
rootView.setSystemUiVisibility(flags);
}
}
And in your onCreate of your activity:
#Override
void onCreate(Bundle b) {
Utils.enableInmersiveMode(this, true);
super.onCreate(b);
// setContentView and the rest of your code here...
}
Take in mind that afterwards views will go behind the system UI and you'll need to dynamically add padding to the first and last Views so the user can interact with them.
Hopefully, you can try this in your-main-path/res/values/styles.xml
This is for transparent Status Bar and Navigation Bar in any android devices.
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:navigationBarColor">#android:color/transparent</item>
One more thing if you want to try transparency and float the to the bar you can use this but the background of Navigation Bar will reduce 50% of transparency.
<item name="android:windowTranslucentNavigation">true</item>
When you want to unset the TranslucentNavigation float, this one can fit the screen between Status Bar and Navigation Bar
<item name="android:fitsSystemWindows">true</item>

How can I hide Navigation Bar without hiding the status bar

I am trying to hide the Bottom navigation bar only and not the status bar. Most of the code I am getting is hiding both the navigation bar and the status bar.
Try the below function. Owing to changes in Android R, View.SYSTEM_UI_FLAG_HIDE_NAVIGATION, setSystemUiVisibility etc are being deprecated. I have made the function to handle this scenario.
public void hideBottomNavigationBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getWindow().setDecorFitsSystemWindows(false);
WindowInsetsController controller = getWindow().getInsetsController();
if(controller != null) {
controller.hide(WindowInsets.Type.navigationBars());
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
} else {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
Another thing to note about using View.SYSTEM_UI_FLAG_HIDE_NAVIGATION from the docs:
There is a limitation: because navigation controls are so important, the least user interaction will cause them to reappear immediately. When this happens, both this flag and SYSTEM_UI_FLAG_FULLSCREEN will be cleared automatically, so that both elements reappear at the same time.
Inorder to work around this limitation you can set View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY as well like this:
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
But this only works SDK 19 onwards.
View v = getWindow().getDecorView();
int options = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
v.setSystemUiVisibility(options);

Android Tooltip menu item style

I can't find anything on the google and stackoverflow so I had to ask.
I have menu on Toolbar:
<item
android:icon="#drawable/help_button_selector"
android:title="#string/Menu_Toolbar_Help"
android:id="#+id/MENU_HELP"
app:showAsAction="always"/>
When user long press icon, system shows tooltip (popup/context menu) with title. However on most devices it has black border (like in Toast). Is there any way to style this border/background? I have already created style for toolbar theme and popup, but I can't find a proper item name.
1.- You can follow this post to create your ToolTip link
2.-You can do this to show a Toast as a ToolTip, then you can customize it as you want.
view.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "I'm a ToolTip", Toast.LENGTH_SHORT).show();
return true;
}
}
Hope it helps :)
Use below link to customize your Action Bar:
http://romannurik.github.io/AndroidAssetStudio/
open url -> GoTo Android Action Bar Style Generator -> Select the options -> click DOWNLOAD.ZIP -> Copy all the componets into their correspondence folders -> In your styles.xml file remove all the code and copy all the code of styles_**.xml file and delete this file.
Menu tooltip
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_skip) {
View view = findViewById(R.id.menu_skip);
Tooltip.make(this, new Tooltip.Builder(101)
.anchor(view, Tooltip.Gravity.BOTTOM)
.closePolicy(mClosePolicy, 5000)
.text("Tooltip on a TabLayout child...Tooltip on a TabLayout child...")
.fadeDuration(200)
.fitToScreen(true)
.activateDelay(2000)
.withCallback(this)
.floatingAnimation(Tooltip.AnimationBuilder.DEFAULT)
.showDelay(400)
.build()
).show();
return true;
}
return super.onOptionsItemSelected(item);
}
Visit more

How to avoid Default selection on long press in android Kitkat 4.4?

Hello Developers,
i am working with Btwebview here on long press we are avoiding the default selection functionality on long press and giving our own.The overriding of long press method is working perfectly till android 4.3 but with 4.4 the defalut selection also coming with actionbar.Below i am mentioning the sample code-
public class BTWebView extends WebView implements TextSelectionJavascriptInterfaceListener, OnTouchListener, OnLongClickListener,DragListener {
.......
public BTWebView(Context context) {
super(context);
this.ctx = context;
this.setup(context);
}
protected void setup(Context context)
{
this.setOnLongClickListener(this);
this.setOnTouchListener(this);
}
and on long press
#Override
public boolean onLongClick(View v)
{
......
return true;
}
}
Here after overriding the long click and return value as true so it avoid default selection till 4.3 so please tell me how to avoid either the complete default selection or atleast avoid the action bar comes on long press .thanks in advance
i found the solution for this question here on github ,it is-
if(event.getAction() == MotionEvent.ACTION_UP)
{
if(!mScrolling){
mScrolling = false;
endSelectionMode();
return false;
}
mScrollDiffX = 0;
mScrollDiffY = 0;
mScrolling = false;
// Fixes 4.4 double selection
return true;
}
here also you have to return the true,after that the default selection will not come .
The solution for KitKat and above proposed by Ravi Saini works to prevent the default selection interface to appear. However, return true for ACTION_UP event prevents fling gestures for scrolling the contents vertically quickly, so the use of WebView seems unnatural. I added isInSelectionMode() condition to prevent this, now fling gestures work fine, except when in selection mode. The code from WebViewMarker GitHub project with my change is as follows (in TextSelectionSupport.java module, onTouch() method):
case MotionEvent.ACTION_UP:
if (!mScrolling) {
endSelectionMode();
//
// Fixes 4.4 double selection
// See: http://stackoverflow.com/questions/20391783/how-to-avoid-default-selection-on-long-press-in-android-kitkat-4-4
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return false;
}
}
mScrollDiffX = 0;
mScrollDiffY = 0;
mScrolling = false;
//
// Fixes 4.4 double selection
// See: http://stackoverflow.com/questions/20391783/how-to-avoid-default-selection-on-long-press-in-android-kitkat-4-4
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && isInSelectionMode()) {
return true;
}
break;
Greg
If the onLongClick() method isn't getting called and the long press in the WebView is enabling the user selection (i.e. copy, cut, paste etc) then you could try the user-select CSS property
user-select:none;
Which will surpress that behaviour, although not sure if this will still fire the long click listener, or whether the WebView will continue to inherit the click events.

Categories