Android Development Notes (101) Slide-out Menu

Source: Internet
Author: User

Removable page moveactivity slide-out menu from the interface, like a horizontal scrolling view horizontalscrollview, of course, you can also use Horizontalscrollview to implement the slide-off menu. Today, however, Bo mainly refers to the use of linear layout linearlayout to achieve, but also the horizontal direction of the linear layout.


But LinearLayout is a bit funny as a level display, because if there are two sub-views below the width of match_parent, then linearlayout only show the first child view, the second sub-view is how to pull or die. If you add a horizontalscrollview on the outside, because the horizontalscrollview width can only be wrap_content, the width of the child view can only be wrap_content and not match_parent. , so Horizontalscrollview does not make the full screen effect of the sub-page.


Now that we want the width of the two sub-views to be match_parent, and we want to be able to drag two sub-views, is there a way? There must be, in "Android Development note (35) Page Layout view", we mentioned that both the margin and padding can be used to set the gap, the value of the gap is positive, in fact, the gap value can be negative, negative means that the view is hidden part of the As if a piece of paper inserted part of the paper into the book, so only a part of the dew out. Specific to the LinearLayout code implementation, The corresponding is the LeftMargin parameter of the Linearlayout.layoutparams, if the parameter is positive, the view page is pulled out a blank, if the parameter is negative, the view page hides a section of content, if the parameter is assigned to the width of the view, the view page is completely hidden, with Visib The effect of le= "Gone" is similar.


So we can add a touch listener to the view Ontouchlistener, and at the same time the touch coordinates change, the menu page is hidden in the corresponding width, so as to achieve the effect of drawer-style pull-out menus. Once the touch bounces, depending on the distance of the gesture swipe, decide whether you want to pull out the entire menu, or retract it to pull out a portion of the menu. This judgment can be based on whether the sliding offset to the screen half of the width of the condition, as for automatic pull-out or automatic indentation animation, can be runnable to periodically refresh the view's leftmargin parameters.


Here is a simple side-slip effect:



Here is an example of a simple side-slip code:
Import Com.example.exmslidingmenu.util.metricsutil;import Android.annotation.suppresslint;import Android.annotation.targetapi;import Android.app.activity;import Android.os.build;import Android.os.Bundle;import Android.os.handler;import Android.view.motionevent;import Android.view.view;import Android.view.view.onclicklistener;import Android.view.view.ontouchlistener;import android.widget.LinearLayout; public class Moveactivity extends Activity implements Ontouchlistener,onclicklistener {private static final String TAG = " Moveactivity ";p rivate int screenwidth;private float rawx=0;private linearlayout.layoutparams menuParams;private View Ll_menu_move;private View ll_content_move; @Overrideprotected void OnCreate (Bundle savedinstancestate) { Super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_move); Initview ();} @TargetApi (build.version_codes. JELLY_BEAN_MR1) private void Initview () {ll_menu_move = (view) Findviewbyid (r.id.ll_menu_move); ll_content_move = (view) Findviewbyid (R.ID.LL_content_move); screenwidth = Metricsutil.getwidth (this); menuparams = (linearlayout.layoutparams) ll_menu_ Move.getlayoutparams (); menuparams.width = Screenwidth;menuparams.leftmargin =-screenwidth;ll_content_ Move.getlayoutparams (). width = Screenwidth;ll_menu_move.setonclicklistener (this); Ll_content_ Move.setontouchlistener (this);} @SuppressLint ("Clickableviewaccessibility") @Overridepublic boolean OnTouch (View V, motionevent event) {int Distancex = (int) (EVENT.GETRAWX ()-RAWX); switch (Event.getaction ()) {Case MotionEvent.ACTION_DOWN:rawX = event.getrawx (); break;case MotionEvent.ACTION_MOVE:if (Distancex > 0) {menuparams.leftmargin =-screenwidth + distancex;ll_menu_ Move.setlayoutparams (menuparams);} Break;case MotionEvent.ACTION_UP:if (Distancex < SCREENWIDTH/2) {mhandler.postdelayed (New scrollrunnable (-1, DISTANCEX), mtimegap);} else {mhandler.postdelayed (new scrollrunnable (1, Distancex), mtimegap);} break;} return true;} private int mtimegap = 20;private int mdistancegap = 20;privatE Handler mhandler = new Handler ();p Rivate class Scrollrunnable implements Runnable {private int mdirection;private int MD Istance;public scrollrunnable (int direction, int distance) {mdirection = Direction;mdistance = distance;}  @Overridepublic void Run () {if (mdirection==-1 && mdistance>0) {mdistance-= mdistancegap;if (Mdistance < 0) {mdistance = 0;} Menuparams.leftmargin =-screenwidth + mdistance;ll_menu_move.setlayoutparams (menuparams); MHandler.postDelayed (new Scrollrunnable ( -1, mdistance), mtimegap);} else if (mdirection==1 && mdistance<screenwidth) {mdistance + mdistancegap;if (mdistance > ScreenWidth) {m Distance = ScreenWidth;} Menuparams.leftmargin =-screenwidth + mdistance;ll_menu_move.setlayoutparams (menuparams); MHandler.postDelayed (new Scrollrunnable (1, mdistance), mtimegap);}}} @Overridepublic void OnClick (View v) {if (V.getid () = = R.id.ll_menu_move) {Menuparams.leftmargin =-screenwidth;ll_menu_ Move.setlayoutparams (Menuparams);}}}


Horizontal List View Horizontallistview the above-mentioned side-slip menu applies only to a single activity page, which is obviously inconvenient if you want to use a side-by-side menu on other pages. Based on this, we want to separate the slip function into a common control. Now there is an open source Horizontallistview, which is a horizontal scrolling list view, if the view has only two columns, the left column as the menu page, and the right column as the content page, which is similar to the function of the slide menu.


Of course, to use Horizontallistview as a side-slip menu, we also need to make the following modifications:
1, when the gesture is released, according to the current sliding offset, automatically determine the next to the left to slide the alignment, or to the right to slide alignment. The specific steps are: first in the Ontouch method to intercept the motionevent.action_up and motionevent.action_cance judgment, and then calculate the current sliding offset, if the sliding distance exceeds the threshold, then continue to slide the page, otherwise do slide retract; finally call Scroller's Startscroll method to complete the subsequent sliding animation effect.
2, the menu defaults to the left page, the content defaults to the right page, so the first time you load the view, the page will automatically slide to the right content page (call the Scrollto method to scroll to the content page).
3. After pulling out the menu page through gesture swipe, to capture the Click event Completion page, in the Onsingletapup method, switch the current page to the content pages.


The following is the effect of using Horizontallistview to achieve skidding:



Slide Out Menu Slidingmenuslidingmenu The two side-slip effects mentioned earlier in the development step, all rely on gesture touch events, actually in the development because many controls on the page to respond to click events, it is not possible to one by one take over the page touch event. The crux of the problem is that both the menu layout and the content layout are in the same page, so it is easy to create a sliding conflict, to completely solve the sliding conflict, it is best to separate the two layouts to different page processing, the technology is to use different fragment to place the menu and content layout respectively. Slidingmenu is an open source library that uses this mindset and is the most widely used slide-out menu control.


The development steps for using Slidingmenu are as follows:
1, to their own project reference Slidingmenu Library project;
2, write a succession from the Slidingfragmentactivity activity class;
3. Call the Setcontentview method to set the content layout, call the Setbehindcontentview method to set the menu layout, note that two initial layouts are empty;
4, from their own writing fragment class to construct the actual content layout and menu layout, and then call Fragmentmanager Replace method to replace the initial layout of the actual layout;
5. Call Getslidingmenu () to get an instance of the side-slip menu, and set the display parameters of the slide menu;


Slidingmenu parameter settings The following are the common parameter settings for Slidingmenu:

Setslidingenabled: Sets whether to allow sliding.
SetMode: Sets the slide-out mode. Left indicates the menu on the right side, and Left_right indicates that there are menus on both sides.
Settouchmodeabove: Sets the touch range. Touchmode_margin indicates that the touch is only answered in white space, touchmode_fullscreen means that the full screen responds to touch, and Touchmode_none indicates that it does not respond to touch.
Setbehindoffsetres: Sets the offset of the menu layout relative to the page.
Setbehindscrollscale: Sets the zoom ratio of the scroll bar.
Setfadedegree: Sets the degree of fade in.
Setshadowwidthres: Sets the width of the shadow.
Setshadowdrawable: Sets the background image.
Setsecondarymenu: Sets a second menu layout. Used when the SetMode is left_right.
Setsecondaryshadowdrawable: Sets a background image for the second menu. Used when the SetMode is left_right.


The interactive example that jumps back to the Content page menu click when the menu is clicked shows the responsiveuiactivity of the demo project, the main procedure is as follows:

1, define a menu click interface such as Onslidingmenulistener, its internal definition menu click Method such as Onmenuitemclick;
2, the Menu fragment class definition Onslidingmenulistener instance, and this instance's setting method Setonslidingmenulistener;
3, the menu layout fragment class inherits from the Listfragment;
4, the Menu fragment class calls the Setlistadapter method in the Oncreateview to set the menu item list information;
5, rewrite the menu fragment class Onlistitemclick method, received the Click event after the call Onmenuitemclick;
6, the activity class implements the interface Onslidingmenulistener, and overrides the Onmenuitemclick method to carry on the corresponding business logic processing;
7, the Activity class constructs the menu layout, the menu layout sets the Click Interface Setonslidingmenulistener (this);


Viewpager uses the Slidingmenuviewpager itself to do the paging operation using fragment, and then Slidingmenu also uses fragment to distinguish between menu layout and content layout, so if you put Viewpager as the content layout, There is a case of fragment nesting. That is, Viewpager itself is embedded as a content layout fragment into Slidingmenu, and then Viewpager's sub-pages are embedded as fragment into Viewpager, This creates a problem: fragment nesting can cause resource recycling exceptions.


Performance in the interface, that is, click on the menu layout back to the Viewpager page, you will see the first two pages of Viewpager blank, viewing the log found that the first two pages will not execute Oncreateview method. This involves fragment's recycling mechanism, Oncreateview will only be called when the page is first opened, and will not be recreated if the page has not been recycled. We first entered the activity page, Viewpager the first two pages have been executed Oncreateview, and then click on the menu item, slidingmenu the entire content page fragment replaced, but for Viewpager sub-page, Just do the detach operation, and do not do remove or destroy operation, that is, Viewpager sub-page is not recycled, so the click menu back to replace the Viewpager, the system found that the first two pages are not recycled, Naturally, it will not oncreateview again.


Do not know this situation is not a fragment of a bug, anyway, the system does not automatically recycle nested fragment, we have to manually recycle. Here is an example of a code that reclaims nested fragment, performing the detach operation first, and then performing the remove operation:
public void Cleanfragments () {Fragment fragment:mfragments) {mfragmentmgr.begintransaction (). Detach (( Colorfragment) fragment). Commit (), mfragmentmgr.begintransaction (). Remove ((colorfragment) fragment). commit ();}}


Code examples are limited to space, here does not post the full source of this article, there is a need for friends can leave the mailbox, I saw the project after the packaging of mail sent past.

Here is the effect of Slidingmenu+viewpager:



Here is an example of Slidingmenu's activity Main page code:
Import Android.os.bundle;import Android.support.v4.app.fragment;import Android.view.view;import Com.jeremyfeinstein.slidingmenu.lib.slidingmenu;import Com.jeremyfeinstein.slidingmenu.lib.app.slidingfragmentactivity;public Abstract class Basecontentactivity extends slidingfragmentactivity {protected Fragment mcontent;protected Fragment mmenuleft;protected Fragment mmenuright;@ overridepublic void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); int mode = Slidingmenu.left; Bundle bundle = Getintent (). Getextras (); if (bundle! = null) {mode = Bundle.getint ("mode", Slidingmenu.left);} if (Findviewbyid (r.id.menu_frame) = = null) {Setbehindcontentview (r.layout.menu_frame); Getslidingmenu (). SetMode ( mode); Getslidingmenu (). Setslidingenabled (True); Getslidingmenu (). Settouchmodeabove (Slidingmenu.touchmode_ fullscreen);} else {View V = new View (this); Setbehindcontentview (v); Getslidingmenu (). setslidingenabled (false); Getslidingmenu (). Settouchmodeabove (Slidingmenu.touchmode_none);} if (Savedinstancestate! = null) {mcontent = Getsupportfragmentmanager (). Getfragment (Savedinstancestate, "mContent");} if (mcontent = = null) {mcontent = Newdefaultcontent ();} Setfragment (R.id.content_frame, mcontent); mmenuleft = Newmenufragment (); Setfragment (R.id.menu_frame, mMenuLeft); Slidingmenu sm = Getslidingmenu (); Sm.setbehindoffsetres (R.dimen.slidingmenu_offset); Sm.setshadowwidthres ( R.dimen.shadow_width); Sm.setbehindscrollscale (0.25f); Sm.setfadedegree (0.25f); if (mode = = Slidingmenu.left_right) { Sm.setsecondarymenu (r.layout.menu_frame_two); mmenuright = Newmenufragment (); Setfragment (R.id.menu_frame_two, Mmenuright); sm.setsecondaryshadowdrawable (r.drawable.shadow_right);} Sm.setshadowdrawable (mode==slidingmenu.right)? R.drawable.shadow_right:r.drawable.shadow_left);} protected void setfragment (int resid, Fragment Fragment) {Getsupportfragmentmanager (). BeginTransaction (). Replace ( Resid, fragment). commit ();} Protected abstract Fragment newdefaultcontent ();p rotected abstract Fragment NEWMENUFRAGMENT (); @Overridepublic void Onsaveinstancestate (Bundle outstate) {super.onsaveinstancestate (outstate); Getsupportfragmentmanager (). Putfragment (Outstate, "mcontent", Mcontent);}}


The following is a code example of the Slidingmenu menu on the left:
Import Android.content.context;import Android.os.bundle;import Android.support.v4.app.listfragment;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Android.widget.ListView ;p ublic class Basemenufragment extends Listfragment {protected View mview;protected Context mcontext;protected Onslidingmenulistener onslidingmenulistener;public void Setonslidingmenulistener (Onslidingmenulistener listener) { This.onslidingmenulistener = listener;} protected int mlayoutid;public basemenufragment (int layout_id) {mlayoutid = layout_id;} @Overridepublic View Oncreateview (layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) {Mcontext = Getactivity (); MView = Inflater.inflate (Mlayoutid, null); return mView;} @Overridepublic void Onlistitemclick (ListView lv, View v, int position, long id) {if (Onslidingmenulistener! = null) {ONSL Idingmenulistener.onmenuitemclick (position);}}}




Click here to view the full list of Android development notes

Android Development Notes (101) Slide-out Menu

Related Article

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.