Android's framework modifies the bottom navigation bar navigationbar dynamic display and hide

Source: Internet
Author: User

As we all know, Android has joined Navigationbar since the 3.0 release, mainly to provide virtual keys for those devices that do not have physical keys, but it is always fixed at the bottom and occupies 48dp pixel height, although it can be fully transparent from Android 4.4. Using this part of the pixel, but three buttons are always hovering on the screen, which is unbearable for a friend with obsessive-compulsive disorder. Therefore, the purpose of this article is to modify the framework part of the code, can dynamically hide and display the Navigationbar, while trying not to affect the normal system.

Main ideas:

Add a button to the left of the Navigationbar layout (implemented in the Systemui module), click Hide Navigationbar to remove the Navigationbar from the WindowManager. When needed, the Navigationbar is paged out via a swipe gesture (implemented in the policy module) from the bottom of the screen. As shown in the two figure comparison: one is removed before the other is removed.


Specific implementation:

①. Add buttons to achieve dynamic hiding, mainly modified in the Frameworks/base/packages/systemui module, first we add a button, mainly modified

Frameworks/base/packages/systemui/res/layout/navigation_bar.xml file, picture resource and string I won't mention it, as follows:

Diff--git A/frameworks/base/packages/systemui/res/layout/navigation_bar.xml b/frameworks/base/packages/systemui/ Res/layout/navigation_bar.xmlindex 16027d9. 326AAFC 100644---a/frameworks/base/packages/systemui/res/layout/navigation_bar.xml+++ b/frameworks/base/packages /systemui/res/layout/navigation_bar.xml@@ -42,12 +42,28 @@ > <!--navigation Controls--- + <!--BEGIN liweiping <view android:layout_width= "40DP" Androi                 d:layout_height= "match_parent" android:layout_weight= "0" android:visibility= "invisible" />+-->+ <framelayout+ android:layout_width= "@dimen/navigation_                Extra_key_width "+ android:layout_height=" match_parent "+ android:layout_weight=" 0 ">+ <imagebutton+ android:id= "@+id/hide_bar_btn" + android:layout_width= "@dimen/navigation_extra_key_width "+ android:layout_height=" match_parent "+ Android:co                     ntentdescription= "@string/accessibility_hide" + android:src= "@drawable/ic_sysbar_hide" + />++ </framelayout>+ <!--END liweiping-<com.android.systemui.st                 Atusbar.policy.KeyButtonView android:id= "@+id/back" android:layout_width= "@dimen/navigation_key_width"                 android:layout_height= "Match_parent" @@ -246,12 +262,28 @@ -246,12 "0"             android:contentdescription= "@string/accessibility_back"/>+ <!--BEGIN liweiping                 <view android:layout_height= "40DP" android:layout_width= "Match_parent"             android:layout_weight= "0" android:visibility= "invisible"/>+-->+ <framelayout+ android:layout_weight= "0" + android:layout_width= "match_parent" + Android:                    layout_height= "40DP" >++ <imagebutton+ android:id= "@+id/hide_bar_btn" + Android:layout_width= "match_parent" + android:layout_height= "40DP" + android:c                     ontentdescription= "@string/accessibility_hide" + android:src= "@drawable/ic_sysbar_hide_land" +         />+ </framelayout>+ <!--END liweiping-</LinearLayout> <!--lights Out layout to match exactly--

Next Modify frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/ Navigationbarview.java, provide an interface for the button, as follows:

diff--git A/frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/navigationbarview.java b/ Frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/navigationbarview.javaindex 88e71e2. 7545984 100644---a/frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/ navigationbarview.java+++ b/frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/ navigationbarview.java@@ -45,6 +45,7 @@ import COM.ANDROID.SYSTEMUI.R; Import Com.android.systemui.statusbar.BaseStatusBar; Import Com.android.systemui.statusbar.DelegateViewHelper; Import Com.android.systemui.statusbar.policy.deadzone;+import Com.android.systemui.statusbar.policy.KeyButtonRipple; Import Com.android.systemui.statusbar.policy.KeyButtonView; Import java.io.filedescriptor;@@ -265,6 +266,13 @@ public class Navigationbarview extends LinearLayout {public View g     Etimeswitchbutton () {return Mcurrentview.findviewbyid (r.id.ime_switcher); }+//bEgin liweiping+ public View Gethidebarbutton () {+ View view = Mcurrentview.findviewbyid (R.ID.HIDE_BAR_BTN); + View.setbackground (New Keybuttonripple (GetContext (), view)), + return view;+}+//end liweiping Private void Geticons (Resources res) {Mbackicon = res.getdrawable (r.drawable.ic_sysbar_back); @@ -412,7 +420,6 @@ -412,7 C         Lass Navigationbarview extends LinearLayout {mcurrentview = mrotatedviews[surface.rotation_0];     Getimeswitchbutton (). Setonclicklistener (Mimeswitcherclicklistener);-Updatertlorder (); }



Finally, the Click event is implemented in Frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/phonestatusbar.java:

+    Private final Onclicklistener Mhidebarclicklistener = new Onclicklistener () {+        @Override + public        void OnClick (view view) {+           log.i ("The", "Mhidebarclicklistener  onClick ..."); +           Removenavigationbar (); +        }+    };+    private void Removenavigationbar () {+        if (DEBUG) log.d (TAG, "removenavigationbar:about to remove" + M Navigationbarview); +        if (Mnavigationbarview = = null) return;++        Mwindowmanager.removeview ( Mnavigationbarview); +        Mnavigationbarview = null;+    }



By this, the hidden Navigationbar has come to an adjourned.


②. The next step is to show Navigationbar, which is a bit more complicated. Because the Navigationbar is not visible at this point, we can't make it appear by adding buttons, but we know that the status bar drop-down is swipe down through the gesture. So it's easy to think of gestures that swipe up from the bottom of the screen to show Navigationbar. My idea is to add an interface to the policy module by frameworks/base/services/core/java/com/android/server/statusbar/ The Statusbarmanagerservice.java service is passed to the status bar, triggering the display of the Navigationbar event.

Maybe everyone will have questions, why is the policy module modified? Actually I'm just a solution because I know

The Frameworks/base/policy/src/com/android/internal/policy/impl/phonewindowmanager.java has a ready-made gesture swipe interface. In fact, you can also add an event like this in Systemui, what we need is such a trigger event.

The main modification of Phonewindowmanager.java is to implement the Onswipefrombottom (vertical screen) and onswipefromright (horizontal screen) two interfaces, and then call Shownavigationbar, In the Shownavigationbar function, we call the Shownavigationbar function in the Statusbarmanagerservice service, as follows:

Diff--git A/frameworks/base/policy/src/com/android/internal/policy/impl/phonewindowmanager.java b/frameworks/ Base/policy/src/com/android/internal/policy/impl/phonewindowmanager.javaindex Bb53e12. 907202d 100644---a/frameworks/base/policy/src/com/android/internal/policy/impl/phonewindowmanager.java+++ b/ frameworks/base/policy/src/com/android/internal/policy/impl/phonewindowmanager.java@@ -1241,13 +1241,27 @@ Public                         Class Phonewindowmanager implements Windowmanagerpolicy {public void Onswipefrombottom () { if (Mnavigationbar! = null && mnavigationbaronbottom) {requesttransient Bars (Mnavigationbar); + log.i ("The", "Onswipefrombottom ... mnavigationbar! = null && mNa                         Vigationbaronbottom "); }+//begin liweiping+ else{+ log.i ("The", "Onswipe Frombottom ... "); + SHownavigationbar (); +}+//end liweiping} @Override public void Onswipefromright () {if (Mnavigationbar! = null &A                            mp;&!mnavigationbaronbottom) {requesttransientbars (mnavigationbar); +                        LOG.I ("The", "onswipefromright ... mnavigationbar! = null &&!mnavigationbaronbottom"); + }+//begin liweiping+ else{+ log.i ("The", "on                         Swipefromright ... "); + Shownavigationbar (); }+//end liweiping} @Override Public V OID OnDebug () {@@ -1293,7 +1307,24 @@ -1293,7 class Phonewindowmanager implements Windowmanagerpolicy {Goingto      Sleep (Windowmanagerpolicy.off_because_of_user);   }}-+//begin liweiping+ private void Shownavigationbar () {+ Mhandler.post (new Runnable () {+ @Override + public void run () {+ try {+ Istatusbarservice StatusBar = Getstat                    Usbarservice (); + if (statusbar! = null) {+ Statusbar.shownavigationbar (); + }+} catch (RemoteException e) {+//Re-acquire status bar service next Ti  Me it is needed.+ mstatusbarservice = null;+}+}+}); +}+//end liweiping private void Updatekeyassignments () {Final Boolean hasmenu = (Mdevicehardwarekeys & key_mask_m         ENU)! = 0; Final Boolean hashome = (Mdevicehardwarekeys & key_mask_home)! = 0;



when the event is passed to Statusbarmanagerservice, let's take a look at how Statusbarmanagerservice.java implements Shownavigationbar:

diff--git A/frameworks/base/services/core/java/com/android/server/statusbar/statusbarmanagerservice.java b/ Frameworks/base/services/core/java/com/android/server/statusbar/statusbarmanagerservice.javaindex f85e2d9. 3f75840 100644---A/frameworks/base/services/core/java/com/android/server/statusbar/statusbarmanagerservice.java + + + b/frameworks/base/services/core/java/com/android/server/statusbar/statusbarmanagerservice.java@@ -366,6 + 366,27 @@ public class Statusbarmanagerservice extends Istatusbarservice.stub {"WINDOWMANAGER.LAYOUTP         Arams "); }}+//begin liweiping+ @Override + public void Shownavigationbar () {+ Enforcestatusbar (); + + and ROID.UTIL.LOG.D ("by", TAG + "Shownavigationbar ..."), + + synchronized (mLock) {+ mhandler.post (new Runnab  Le () {+ public void run () {+ if (MBar! = null) {+ try {+ Mbar.shownavigationbar (); +} catch (RemoteException ex) {+}+}+ }+}); +}+}+//end liweiping private void updateuivisibilitylocked (final I NT Vis, Final int mask) {if (msystemuivisibility! = Vis) {



as can be seen from the above code, Statusbarmanagerservice is only a transfer function, the message is passed to the StatusBar, the final implementation is in the Systemui module frameworks/base/packages/ Systemui/src/com/android/systemui/statusbar/commandqueue.java, as shown below:

Diff--git A/frameworks/base/packages/systemui/src/com/android/systemui/statusbar/commandqueue.java b/frameworks/ Base/packages/systemui/src/com/android/systemui/statusbar/commandqueue.javaindex 9db875f. 4F24B6E 100644---a/frameworks/base/packages/systemui/src/com/android/systemui/statusbar/commandqueue.java+++ b/ frameworks/base/packages/systemui/src/com/android/systemui/statusbar/commandqueue.java@@ -56,6 +56,7 @@ Public Class Commandqueue extends Istatusbar.stub {private static final int msg_buzz_beep_blinked = << MSG     _shift;     private static final int msg_notification_light_off = << msg_shift; private static final int msg_notification_light_pulse = << msg_shift;+ private static final int Msg_show_nav     Igationbar = << msg_shift;//add liweiping public static final int flag_exclude_none = 0; public static final int flag_exclude_search_panel = 1 << 0;@@ -83,6 +84,7 @@ public class Commandqueue extends IStat UsbAr.         Stub {public void animatecollapsepanels (int flags);         public void Animateexpandsettingspanel (); public void setsystemuivisibility (int vis, int. mask), + public void Shownavigationbar ();//add liweiping Publ         IC void Topappwindowchanged (Boolean visible); public void Setimewindowstatus (IBinder token, int vis, int backdisposition, Boolean showimeswitcher); @@-1 54,6 +156,14 @@ public class Commandqueue extends Istatusbar.stub {mhandler.obtainmessage (msg_set_systemui_vi         Sibility, Vis, mask, null). Sendtotarget (); }}+//begin liweiping+ public void Shownavigationbar () {+ synchronized (mlist) {+ mhandler.re Movemessages (Msg_show_navigationbar); + mhandler.sendemptymessage (msg_show_navigationbar); +}+}+/ /end liweiping public void topappwindowchanged (Boolean menuvisible) {synchronized (mlist) {@@ -283,6 +293,11 @@ public class Commandqueue extends IStatusbar.stub {case MSG_SET_SYSTEMUI_VISIBILITY:mCallbacks.setSystemUiVisibility (msg.a                     RG1, MSG.ARG2); break;+//begin liweiping+ Case msg_show_navigationbar:+ Mcallbacks.showna                     Vigationbar (); + break;+//end liweiping case msg_top_app_window_changed:                     Mcallbacks.topappwindowchanged (Msg.arg1! = 0); Break



Commandqueue.java received the message, and then the callback to base/packages/systemui/src/com/android/systemui/statusbar/phone/ Phonestatusbar.java, around the most of the day, the news finally came back, we need to implement the Phonestatusbar.java display Navigationbar function:

+ @Override//commandqueue+ public void Shownavigationbar () {+ LOG.I ("to", "TAG +" Shownavigationbar ... "); + Forceaddnavigationbar (); +}+ private void Forceaddnavigationbar () {+//If We have no Navbar view and W E should has one, create it+ if (mnavigationbarview! = null) {+ return;+}++ mnavigationb Arview =+ (Navigationbarview) view.inflate (mcontext, R.layout.navigation_bar, null); + Mnavigationbar View.setdisabledflags (mdisabled); + Mnavigationbarview.setbar (this); + Addnavigationbar (true); Dynamically adding nav bar, reset System UI visibility!+}+ private void Preparenavigationbarview (Boolean forcere Set) {+ Mnavigationbarview.reorient (); + Mnavigationbarview.getrecentsbutton (). Setonclicklistener (MRecentsCli Cklistener); + Mnavigationbarview.getrecentsbutton (). Setontouchlistener (Mrecentspreloadontouchlistener); + mNa Vigationbarview.getrecentsbutton (). SetlOngclickable (true); + Mnavigationbarview.getrecentsbutton (). Setonlongclicklistener (Mlongpressbackrecentslistener ); + Mnavigationbarview.getbackbutton (). Setlongclickable (true); + Mnavigationbarview.getbackbutton (). SetOnLong Clicklistener (Mlongpressbackrecentslistener); + Mnavigationbarview.gethomebutton (). Setontouchlistener ( Mhomeactionlistener); + Mnavigationbarview.gethidebarbutton (). Setonclicklistener (Mhidebarclicklistener);//ADD liweiping++ if (forcereset) {+//Nav Bar is added dynamically-we need to reset the Msystemuivisibili Ty and call+//setsystemuivisibility So, Mnavigationbarmode is set to the correct value+ log.i (" "", "preparenavigationbarview Mnavigationbarmode =" + Mnavigationbarmode + "msystemuivisibility =" + MSystemUiVisibili Ty + "mnavigationiconhints =" + mnavigationiconhints); + Mnavigationbarmode = 0;+ + int NE Wval = msystemuivisibility;+ Msystemuivisibility = view.system_ui_flag_visible;+ setsystemuivisibility (newval,/*SYSTEM_UI_VISIBILITY_MASK*/0XFFFFFF FF); + int hints = mnavigationiconhints;+ mnavigationiconhints = 0;+ setnavigationiconhint s (hints); + topappwindowchanged (mshowmenu); +}++ Updatesearchpanel (); +}++//For Small-scre        En devices (read:phones) that lack hardware navigation buttons+ private void Addnavigationbar (Boolean forcereset) {+ if (DEBUG) log.v (TAG, "addnavigationbar:about to add" + mnavigationbarview); + if (Mnavigationbarview = = nul L) return;++ Preparenavigationbarview (forcereset); + Mwindowmanager.addview (Mnavigationbarview, GetNavigatio Nbarlayoutparams ()); +}+//end liweiping


It is important to note that:

① display Navigationbar, you need to re-instantiate a navigationbarview, I have tried to remove the Navigationbarview after the empty, the next time the addition of direct use, there will be a status bar restart situation, the specific reason is unknown, Log shows animation playback errors.

② re-add navigationbarview need to restore the state before Navigationbarview, such as transparent before hiding, display Input method buttons, menu keys and so on.

③ This article was modified on the Android5.0 code, and the other versions were not validated.

④ This article is only to provide a way of thinking, not the optimal scheme.

⑤ Reprint Please specify the Source: Http://blog.csdn.net/way_ping_li



Android's framework modifies the bottom navigation bar navigationbar dynamic display and hide

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.