Reprinted please indicate the source: http://blog.csdn.net/guolin_blog/article/details/8714621
The Renren client has a special effect that is quite attractive. sliding the finger on the main interface to the right will display the menu, while the main interface will be mostly hidden, however, a small part on the left is displayed together with the menu.
It is said that the special effect of the Renren client was imitated from the Facebook client. It is unknown whether Facebook has been imitated from other places. Well, today we will work together to achieve this effect. In short, the first time I saw this special effect on the Renren client, I thought that I was imitating the special effect on the Renren client.
Although there are many implementations of similar effects on the internet, I find that most of the implementation solutions are very complicated and not easy to understand. But in fact this effect is not difficult to achieve, so what I bring to you today is the simplest sliding menu implementation solution in history.
First, let's talk about the implementation principle. There must be two parts in the layout of an activity. One is the layout of menus and the other is the layout of content. The two la s are arranged horizontally. The menu is left and the content is right. During initialization, the menu layout is shifted to the left to be completely hidden, so that the content layout is fully displayed in the activity. Then, the left offset distance of the menu layout is changed by listening to the finger sliding event to control the display and hiding of the menu layout. The schematic diagram is as follows:
Change the left offset of the menu layout to 0, as shown below:
Well, we started to implement it using code. First, create an android project in eclipse. The project name is renrenslidemenudemo. Write the layout file, create or open the activity_main.xml file in the layout directory, and add the following code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" tools:context=".MainActivity" > <LinearLayout android:id="@+id/menu" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/menu" > </LinearLayout> <LinearLayout android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/content" > </LinearLayout></LinearLayout>
The outermost layout of the layout file is a linearlayout, which is arranged horizontally. Under this linearlayout, two sublinearlayout elements are nested, namely, the menu layout and the content layout. In order to make the layout as simple as possible, no controls are added to the menu layout and content layout, but a background image is added to each of the two la S, these two background images are taken from the Renren client. In this way, we can focus on how to achieve the sliding menu effect without worrying about the complicated layout.
Create or open mainactivity. This class is still the main activity of the program and the only activity of this demo. Add the following code to it:
Public class mainactivity extends activity implements ontouchlistener {/*** the speed at which the fingers slide to display and hide the menu by scrolling. */Public static final int snap_velocity = 200;/*** screen width value. */Private int screenwidth;/*** the menu can slide to the left edge at most. The value is determined by the width of the menu layout. After marginleft reaches this value, it cannot be reduced. */Private int leftedge;/*** the menu can slide to the right edge at most. The constant value is 0, that is, after marginleft reaches 0, it cannot be increased. */Private int rightedge = 0;/*** the width left to the content when the menu is fully displayed. */Private int menupadding = 80;/*** layout of the main content. */Private view content;/*** menu layout. */Private view menu;/*** menu layout parameter. this parameter is used to change the leftmargin value. */Private linearlayout. layoutparams menuparams;/*** record the abscissa when the finger is pressed. */Private float xdown;/*** record the abscissa when the finger moves. */Private float xmove;/*** record the abscissa when the mobile phone is lifted. */Private float xup;/*** whether the menu is currently displayed or hidden. This value is changed only when the menu is fully displayed or hidden. This value is invalid during sliding. */Private Boolean ismenuvisible;/*** is used to calculate the Sliding Speed of the finger. */Private velocitytracker mvelocitytracker; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); initvalues (); content. setontouchlistener (this);}/*** initialize some key data. Including obtaining the screen width, resetting the width for the content layout, and resetting the width and offset distance for the menu layout. */Private void initvalues () {windowmanager window = (windowmanager) getsystemservice (context. window_service); screenwidth = Window. getdefadisplay display (). getwidth (); content = findviewbyid (R. id. content); menu = findviewbyid (R. id. menu); menuparams = (linearlayout. layoutparams) menu. getlayoutparams (); // set the menu width to the screen width minus menupaddingmenuparams. width = screenwidth-menupadding; // The value of the left edge is assigned to the negative leftedge of the menu width = -Menuparams. width; // set leftmargin of the menu to the value of the left edge, so that the menu becomes invisible during initialization. leftmargin = leftedge; // set the content width to the screen width content. getlayoutparams (). width = screenwidth;} @ overridepublic Boolean ontouch (view V, motionevent event) {createvelocitytracker (event); Switch (event. getaction () {Case motionevent. action_down: // the x-axis xdown = event when the finger is pressed. getrawx (); break; Case motionevent. action_move: // when the finger moves, compare Calculates the moving distance to adjust the leftmargin value of menu to display and hide menuxmove = event. getrawx (); int distancex = (INT) (xmove-xdown); If (ismenuvisible) {menuparams. leftmargin = distancex;} else {menuparams. leftmargin = leftedge + distancex;} If (menuparams. leftmargin <leftedge) {menuparams. leftmargin = leftedge;} else if (menuparams. leftmargin> rightedge) {menuparams. leftmargin = rightedge;} menu. setlayoutparams (menuparams); Break; Case motionevent. action_up: // when the finger is raised, judge the intent of the current gesture to decide whether to scroll to the menu interface or to the content interface xup = event. getrawx (); If (wanttoshowmenu () {If (shouldscrolltomenu () {scrolltomenu () ;}else {scrolltocontent () ;}} else if (wanttoshowcontent ()) {If (shouldscrolltocontent () {scrolltocontent () ;}else {scrolltomenu () ;}} recyclevelocitytracker (); break ;} return true ;} /*** determine whether the intent of the current gesture is to display the content. If the distance from the finger movement is negative and the current menu is visible, the current gesture is considered to display the content. ** @ Return: if the current gesture is to show content, true is returned. Otherwise, false is returned. */Private Boolean wanttoshowcontent () {return xup-xdown <0 & ismenuvisible;}/*** determines whether the intent of the current gesture is to display the menu. If the distance between fingers is positive and the current menu is invisible, the current gesture is regarded as displaying the menu. ** @ Return: returns true if you want to display the menu. Otherwise, false is returned. */Private Boolean wanttoshowmenu () {return xup-xdown> 0 &&! Ismenuvisible;}/*** determines whether to scroll the menu display. If the finger movement distance is greater than 1/2 of the screen, or the finger movement speed is greater than snap_velocity, * the menu should be displayed in scroll mode. ** @ Return: returns true if the menu is displayed in scroll mode. Otherwise, false is returned. */Private Boolean shouldscrolltomenu () {return xup-xdown> screenwidth/2 | getscrollvelocity ()> snap_velocity;}/*** determines whether to scroll to display the content. If the finger movement distance plus menupadding is greater than 1/2 of the screen, * or the finger movement speed is greater than snap_velocity, the content should be displayed in scroll mode. ** @ Return: if the content is displayed in a scroll mode, true is returned. Otherwise, false is returned. */Private Boolean shouldscrolltocontent () {return xdown-xup + menupadding> screenwidth/2 | getscrollvelocity ()> snap_velocity;}/*** scroll the screen to the menu interface, the scroll speed is set to 30. */private void scrolltomenu () {New scrolltask(cmd.exe cute (30);}/*** scroll the screen to the content page and set the scroll speed to-30. */private void scrolltocontent () {New scrolltask(cmd.exe cute (-30);}/*** create a velocitytracker object and add the sliding events on the touch content interface to velocitytracker. ** @ Param event * Sliding event on the content page */private void createvelocitytracker (motionevent event) {If (mvelocitytracker = NULL) {mvelocitytracker = velocitytracker. obtain ();} mvelocitytracker. addmovement (event);}/*** get the speed at which the finger slides on the content interface. ** @ Return sliding speed, measured in the unit of how many pixels are moved per second. */Private int getscrollvelocity () {mvelocitytracker. computecurrentvelocity (1000); int velocity = (INT) mvelocitytracker. getxvelocity (); Return math. ABS (velocity);}/*** reclaim the velocitytracker object. */Private void recyclevelocitytracker () {mvelocitytracker. recycle (); mvelocitytracker = NULL;} class scrolltask extends asynctask <integer, integer, integer >{@ overrideprotected integer doinbackground (integer... speed) {int leftmargin = menuparams. leftmargin; // scroll the interface based on the input speed. When the scroll reaches the Left or Right boundary, the page jumps out of the loop. While (true) {leftmargin = leftmargin + speed [0]; If (leftmargin> rightedge) {leftmargin = rightedge; break;} If (leftmargin <leftedge) {leftmargin = leftedge; break;} publishprogress (leftmargin); // in order to have a rolling effect, the thread sleeps for 20 milliseconds each cycle, so that you can see the scroll animation with the naked eye. Sleep (20);} If (speed [0]> 0) {ismenuvisible = true;} else {ismenuvisible = false;} return leftmargin ;} @ overrideprotected void onprogressupdate (integer... leftmargin) {menuparams. leftmargin = leftmargin [0]; menu. setlayoutparams (menuparams);} @ overrideprotected void onpostexecute (integer leftmargin) {menuparams. leftmargin = leftmargin; menu. setlayoutparams (menuparams) ;}}/*** specifies the number of milliseconds to sleep the current thread. ** @ Param millis * specifies the duration of sleep of the current thread, in milliseconds */private void sleep (long millis) {try {thread. sleep (millis);} catch (interruptedexception e) {e. printstacktrace ();}}}
All the code is here. We can see that only over two hundred lines of code can be added with comments to achieve the special effect of the sliding menu. Next I will explain the above Code. First, call the initvalues method during initialization, where the content layout width is set to the screen width, the width of the menu layout is set to the screen width minus the menupadding value. This ensures that some content la s are displayed during the menu layout display. If you do not re-define the two layout widths during initialization, the layout will be declared as the same as in the layout file. Both layout are fill_parent, so that the sliding menu cannot be achieved. Then, set the left offset of the menu layout to the width of the negative menu layout, so that the menu layout will be completely hidden, and only the content layout will be displayed on the interface.
Then register the listening event for the content layout, so that the ontouch event will be triggered when the finger slides over the content layout. In the ontouch event, the left offset of the menu layout is changed based on the sliding distance of the finger to control the display and hiding of the menu layout. When the finger leaves the screen, it will determine whether to slide to the menu layout or content layout. The judgment is based on the sliding distance or speed of the finger. For details, see the comments in the code.
Finally, the androidmanifest. XML code is automatically generated, which is very simple:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.renrenslidemenudemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" > <activity android:name="com.example.renrenslidemenudemo.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
Now let's run it and check the effect. First, the content layout is displayed when the program is started. Slide your fingers to the right of the page to see the menu layout.
When the menu layout is fully displayed, the effect is as follows:
Click here to download the source code
Today, we have seen the simplest implementation scheme of sliding menus in history, which is indeed very simple. Some friends may ask, it is very easy to implement the sliding menu in an activity, but if many of my applications have activity, you need to slide the menu, every activity is implemented in this way, and it becomes complicated. Yes, the current solution only applies to a single activity. If you want to achieve the sliding menu effect in multiple activities, please refer to my other article completely parsing Android sliding menu framework and teach you how to implement sliding menu effects in one minute
Now, today's explanation is over. If you have any questions, you can leave a message below.