Teach you 10 lines of code to write a side-slip menu

Source: Internet
Author: User
Tags gety


The original post is published in the Wisdom Podcast Forum, the Dark Horse Training programmer, Address: http://bbs.itheima.com/thread-167442-1-1.html

Let's take a look at the slide menu effect:

Above: initial status, Swipe, release open menu

Did you build it? After reading this article, write this side-by-side menu, so easy for you!

Did you build it? In fact, to write this side-by-side menu, only 10 lines of handwritten code can be done!

Did you build it? After reading this article, when you hear the product said "I want this effect", will never be weak!

In Android development, custom view effects are part of the Advanced section. Because of the common logic of things, after 1 years of development, you will be all. And for how to achieve the special effect of the view of the skills, you can be divided into a high and low. So, whether it's a matter of face (the cult of the Programmer's paper), or the improvement of professional skills, we all need to be familiar with the techniques of view effects.

Next, I'll use the principle analysis plus code examples to illustrate some of the common techniques for moving view.

In actual development, we generally need to let view move in 2 situations:

1. In the touch process, with the finger drag let the view move

2. When the finger is lifted, let the view smooth and slow move to a location

What is the nature of view movement?

Imagine that the view appears in any position on the screen has its coordinates, if there is no coordinates, then the appearance of the view is not controllable, and thus can not be drawn.

The so-called view movement is nothing more than moving the view from one coordinate point to another.

What coordinate system does the view move inside?

First think about the concept of a coordinate system:

Screen coordinate system: The origin point is in the upper left corner of the screen, the x axis is in the right direction, the Y axis is facing downward;

View coordinate system: The origin point is in the upper left corner of the view, the same x axis is in the right direction, and the Y axis is facing downwards;

(If you have doubts about the above 2 coordinate systems, you can put a simple textview in the activity, it is best to let textview distance from the parent view, the TextView for touch monitoring, Then Print Event.getx () and EVENT.GETRAWX () in Ontouchevent, which are the coordinates of the touch point relative to the upper-left corner of the view, which is the coordinate of the touch point relative to the upper-left corner of the screen.

The view movement can be subdivided into 2 categories:

The A.view itself moves in the parent view, that is, the whole move, and the category can be seen as the content of the parent view moving

The contents of the B.view are moving, that is, moving internally

What are the specific APIs for view movement?

Here's a look at how to move the view with the above analysis:

1. Move the view by changing the left,top,right,bottom of the view

This method is only suitable for moving sub-view in ViewGroup, that is, Class A in mobile classification. We know that LEFT,TOP,RIGHT,BOTTOM4 values are initialized at the time the OnLayout method executes. At the same time, the meaning of 4 parameters to do a simple explanation, just take left and top for example:

Left: Indicates the distance from the parent view origin of the current view

Top: Represents the distance from the top of the current view from the parent view origin.

View provides 3 ways to change these values:

Layout (l,r,t,b), offsetleftandright (offset),//offset to left and right offsettopandbottom (offset),//offsets for top and bottom at the same time

So if we add touch monitoring to a view, we get the value of touch moving when we touchmove, we can use these 3 methods to move the view in the parent view with our fingers.

code example:

public boolean OnTouch (View V, motionevent event) {         float x =  event.getx ();         Float y =  event.gety ();         Switch (event.getaction ()) {case         motionevent.action_down: Break                 ;         Case Motionevent.action_move:                 float deltax = x-lastx;                 float DeltaY = y-lasty;//                text.layout (Text.getleft () +deltax,text.gettop () +deltay, Text.getright () +deltaX, Text.getbottom () +deltay);                 Text.offsetleftandright ((int) deltax);                 Text.offsettopandbottom ((int) deltay);                 break;         }                 LASTX = x;                 Lasty = y;                 return true;}

2. By changing the SCROLLX and scrolly to move the view, the Scrollto and Scrollby methods, which are used to move the view content, in the official words: internally scroll theircontent.

Depending on the classification of the View movement, if used in ViewGroup, all child view of the current view can be moved at the same time, and if it is used for a single view, the contents of the view can be moved.

Note: View background is not part of the view,

Here's a comment from the draw method of view to see the steps for view drawing:

         /* *draw traversal performs several drawing steps which must be executed         *in the appropriate order         :  * 1. D Raw the background         *  2. If necessary, save the canvas ' layers toprepare for fading         *  3. Draw View ' s content         *  4. Draw Children         *  5. If necessary, draw the fading edges and restorelayers         *  6. Draw decorations (scrollbars forinstance)         */

For the content of the view here, for Textview,content is its text, for ImageView, it is its drawable object.

SCROLLX and scrolly are explained below:

First, if you use the 2 methods of Scrollto and Scrollby directly, you will find that when you Scrollto (10,0), the content of the view moves to the left 10, the same Scrollby (10,0), the view content will continue to move to the left 10, It's confusing to not move to the right.

First look at the official explanation for SCROLLX:

/**         *return The scrolled left position of this view. The the left edge of         *the displayed part of your view. You don't need to draw any pixels         *farther left, since those is outside of the frame of your view on screen.         * @return The Leftedge of the displayed part of your view, in pixels.         */

First, when the Android drawing view has a bounds, can be obtained through View.getdrawingrect (), is actually a Rect object, this rect area is the canvas really draw area, more than this bounds will not be drawn. In fact, the left edge of the displayed part if YourView in the note above refers to the left of bounds. The left,top,right,bottom values of rect are scrollx,scrolly,scrollx+width,scrolly+height respectively, and the left and top of the rect are obviously initially 0 because there is no scroll, When Scrollto (10,0), the left of the RECT is 10, that is, bounds to the right to move 10, then this time after the move in the bounds range, you will see the contents of the view is moved to the right, because the location of the view is unchanged, bounds shift , it creates a visual effect that moves the content to the left. This is where we are puzzled. The reason is that Scrollto and Scrollby refer to the bounds movement of the view, not directly referring to the movement of the view content. At the same time the scroll coordinate system is the current view coordinate system.

Scrollto and Scrollby methods move the view process:

So if we add touch monitoring to a view, we get the value of touch movement when we touchmove, we can use the Scrollto and Scrollby methods to move the contents of the view with our fingers.

code example:

public boolean OnTouch (View V, motionevent event) {         float x =  event.getx ();         Float y =  event.gety ();         Switch (event.getaction ()) {case         motionevent.action_down: Break                 ;         Case Motionevent.action_move:                 float deltax = x-lastx;                 float DeltaY = y-lasty;                                                            /* Why subtract DELATX:NEWSCROLLX: Move your finger to the right, DeltaX will be positive, SCROLLX will be smaller, bounds left is smaller, then bounds will move to the right, and the contents of the view move to the starboard */                 float NEWSCROLLX =text.getscrollx ()-deltax;                 Float newscrolly =text.getscrolly ()-DeltaY;                 Text.scrollto ((int) newscrollx, (int) newscrolly);                 Scrollby the principle of negative value Text.scrollby ((int)-deltax, (int)-deltay);                 break;         }                 LASTX = x;                 Lasty = y;                 return true;}

How do I make the view move smoothly?

The above 2 methods are generally used when the view is touchmove to let the view move, and layout and scroll are instantaneous move past, then the question comes, when we lift the finger, want to let the view move smooth to the specified position what to do? Since both layout and scroll can move the view, we loop through these methods over a period of time, and each time we move it, we can move it smoothly.

For this requirement, there are generally 2 ways of doing this:

1.Scroller implementations

2. Custom Animation implementations

I. Using scroller to achieve view smooth movement

The scroller encapsulates the operation of the view move, but it is a simulated move, not really going to move the view. Since it simulates the entire movement of the view, we can loop through the scrollx,scrolly of the current view's real movement during the simulation, then SCROLLX and scrolly, then call Scrollto to achieve a smooth move.

There are generally 3 fixed steps for using scroller:

A. Initializing Scroller

Scroller Scroller =new Scroller (GetContext ());

B. Turn on the simulation process

Scroller.startscroll (StartX, starty, DX, dy,500); invalidate ();

C. Get the value of the view real movement during the simulation and call Scrollto to really move the view

public void Computescroll () {         super.computescroll ();         if (Scroller.computescrolloffset ()) {                  scrollTo (Scroller.getcurrx (), Scroller.getcurry ());                 Invalidate ();         }}

Note: In the b,c step, it should be stated that the invalidate () method must be called, because we can only get scrollx and scrolly in the simulation process in the Computescroll method, but Computescroll is not automatically called. invalidate->draw->computescroll; therefore need to call invalidate, which indirectly calls Computescroll, to achieve the purpose of loop acquisition scrollx and scrolly. When the simulation process is finished, Scroller.computescrolloffset () returns false, which interrupts the loop.

Two. Use custom animations for view smooth movement

Since the system-defined translateanimation can only move the view itself, it cannot move the contents of the view, so it needs to be customized. System-defined 4 kinds of animation, essentially in a period of time to change the view of a property, so we can also customize the animation, inherited from the animation class, to change the properties we want to change over time, such as scrollx,scrolly.

Animation also simulates an execution process, which is similar to scroller, unlike Scroller, which calculates the scrollx and scrolly of real-world view movements, and animation does not. In addition scroller need us to actively call Computescroll, and animation do not need, it will call the Applytransformation method in the execution process until the end of the animation. So we need to calculate the current scrollx and scrolly in the Applytransformation method, and then call View.scrollto (x, y);

Since the first interpolatedtime of Applytransformation identifies the progress and percentage of the animation execution, we can get scrollx and scrolly at any time during execution based on this parameter.

The following is a generic animation that lets view slowly scroll to a specified position over a period of time, with the following code:

public class Smoothscrollanimation extends animation{         private view view;          private int originalscrollx;         private int totalscrolldistance;         Public smoothscrollanimation (View view,int targetscrollx) {                 super ();                 this.view= view;                    ORIGINALSCROLLX = View.getscrollx ();                   Totalscrolldistance = TARGETSCROLLX-ORIGINALSCROLLX;                    Setduration (+);         }    @Override         protected void applytransformation (float interpolatedtime, transformation t) {                 Super.applytransformation (Interpolatedtime, t);                 int newscrollx = (int) (originalscrollx+                 totalscrolldistance*interpolatedtime);                                View.scrollto (newscrollx,0);         }}

Use the powerful Viewdraghelper

Finally, the introduction of a more powerful class viewdraghelper, in the above process we need to monitor the touch, calculate the distance of the finger movement, in the go to constantly call the layout method to move the view, when the finger lift to move slowly to the view, with this class, you do not need to do.

Viewdraghelper is typically used to drag and drop a pair of view in ViewGroup, but it needs to receive a TouchEvent event.

It encapsulates the position of the touch (whether it is the sub-view of the edge and current touch), the distance of the finger movement, the movement speed, the direction of movement, and the scroller. We only need to specify when to start testing, how much to move.

So now we're going to do this article the beginning of the slide menu effect, is the real 10 lines of handwritten code implementation, visible Viewdraghelper powerful.

The description of the method is in the code, and the code is as follows:

public class Slidemenu extends framelayout{public slidemenu (Contextcontext, AttributeSet attrs) {                 Super (CONTEXT,ATTRS);         Init ();         } private View Menuview,mainview;         private int menuwidth;//menu width private viewdraghelperviewdraghelper;         private void Init () {viewdraghelper =viewdraghelper.create (this,callback);                 } @Override protected void Onfinishinflate () {super.onfinishinflate (); if (Getchildcount ()!=2) {throw newillegalargumentexception ("Youlayout must has only 2 children!"                 );                 } Menuview =getchildat (0);         MainView = Getchildat (1); } @Override protected void onsizechanged (int w,int h, int oldw,int oldh) {Super.onsizecha                 Nged (W,h, OLDW, OLDH);         Menuwidth = Menuview.getmeasuredwidth ();       } @Override  public boolean onintercepttouchevent (Motionevent ev) {return viewdraghelper.shouldintercepttouchevent (E         V); } @Override public boolean ontouchevent (Motionevent event) {//To pass touch events to Viewdraghelper, this action must be                 No less viewdraghelper.processtouchevent (event);         return true;                  //viewdraghelper the callback for touch snooping private viewdraghelper.callbackcallback = new Callback () {/** * When to start monitoring touch */@Override public boolean Trycaptureview (                  View Child,int Pointerid) {return mainview==child;//start detection if the child currently touching is MainView} /** * Callback when touch to Childview */@Override Pub LIC void onviewcaptured (View capturedchild,int activepointerid) {super.onviewcaptured (capturedch               Ild,activepointerid);  }/** * When the drag state changes, such as idle,dragging */@Override                 public void onviewdragstatechanged (int.) {super.onviewdragstatechanged (state); /** * Here determines how much the view really moves in the vertical direction, the default implementation does not move * Move principle: The first top is 0, when the hand detection                  Point down drag 10, then dy=10,top=child.gettop () +dy; * If you return 0, the top is always 0, then the view will not move in the vertical direction * If you return top, the view will always follow your finger dragging and moving * @param top top for it to think you want to move To the latest top value * @param dy how much vertical direction is moved/@Override public int cl                 Ampviewpositionvertical (View child,int top, int dy) {return 0; /** * Here determines how much the view is actually moved horizontally, and the default implementation does not move * Move principle: Initially left is 0, when the finger is detected to drag 10 to the right, D                  X=10,left=child.getleft () +dx; * If you return 0, then left is always 0, then the view will not move in the horizontal direction * If the return leFT, the view will always follow the finger drag and move * @param left for it to think that you want to move to the most recent value left * @param dx horizontal direction how much moved                           */@Override public int clampviewpositionhorizontal (View child,int left, int dx) {                 return left; }/** * The callback after the view move * @param the latest left value of the left-moving view * @par                 The latest top value of the view after the AM top move * @param the dx x direction how much * @param dy y-direction moved how much */                                   @Override public void onviewpositionchanged (View changedview,int left, int top,                 int dx,int dy) {super.onviewpositionchanged (changedview,left, top, DX, dy);  /** * Finger Lift callback * @param xvel x-direction sliding speed * @param the speed of yvel in y direction */@Override publicvoid onviewreleased (View releasedchild,float xvel, float yvel) {super.onviewreleased (Releasedchil                         D,xvel, Yvel);                           Move the finger slowly to the specified position if (Mainview.getleft () <MENUWIDTH/2) {//Close menu                           Viewdraghelper.smoothslideviewto (mainView, 0, 0);//equivalent to Scroller Startscroll method                         Viewcompat.postinvalidateonanimation (Slidemenu.this); }else {//Open menu Viewdraghelper.smoothslideviewto (mainview,menuwidth, 0)                           ;                         Viewcompat.postinvalidateonanimation (Slidemenu.this);         }                 }         }; /** * Package for scroller */public void Computescroll () {if (Viewdraghelper.continuese                 Ttling (True)) {viewcompat.postinvalidateonanimation (this);   }      }} 
View Mobile Summary

In summary, when you understand the mobile view of the principle and API, do not have to go to touchmove in the time to manually move the view, if the layout method and Scrollto,scrollby method is not deep understanding, Copy the above corresponding code to your demo to feel it.

Because more mobile veiw situation is in the ViewGroup to move the sub-view, so generally use viewdraghelper to do, the introduction of this class due to space is limited, may be the understanding of each method is not thorough enough, the code to run and try to change the effect, Feel it a little bit and you'll understand.

Teach you 10 lines of code to write a side-slip menu

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.