Android Custom ViewGroup teaches you to implement Arcmenu

Source: Internet
Author: User
Tags cos

Reprint please indicate source: http://blog.csdn.net/lmj623565791/article/details/37567907

Stroll EoE found such UI effect, feel very good, and later know that there is an open source project on GitHub ~ ~ ~ Of course this article is not to teach you how to use this open source project, but to teach you how to customize the ViewGroup to write such effects, custom viewgroup is also my pain, Hey, hope this can be a catalyst ~ ~



1. Realization of Ideas

Through, there will be several questions:

A, how to achieve the animation effect

It can be seen that the animation is emitted from outside the vertex, it may be said that it is not simple, the default elements are in the fixed position, and then traslateanimation is good; this ignores a point, that is, traslateanimation although there is animation effect, But the essence is not to change the position of the button, our button animation end is to click, some people may say that the use of property animation, or change leftmagin,rightmagin, this may be more troublesome, in fact, we can default to let the submenu is already in the target location, and then gone, When clicked or with Traslateanimation, set the starting position as the fixed point, the end position is our hidden area, the animation end visible.

b, how to determine the location?

This may require a little bit of mathematical knowledge, and I have drawn a sketch (ice-cold, kneeling glass to paint the tools below these graphs):


Each time according to the number of sub-menu, calculate a This angle, and then through sin, cos respectively calculate the left of each submenu, top;

Of course, this is the case on the left, if on the right, then top is the same as the left top, and the remaining is (the width of the screen-left to make it out); the other two directions the same ~


As a whole I customize a viewgroup, the first child element in this viewgroup is a click button (you can casually layout, whatever control you want), and the next child element I think is the menu item. According to, decide to expand the radius and display the location, let the user to customize. Here's a look at the specific implementation:

2. Custom View Properties:

<?xml version= "1.0" encoding= "Utf-8"?><resources>    <attr name= "position" >        <enum name= " Left_top "value=" 0 "/>        <enum name=" Right_top "value=" 1 "/>        <enum name=" Right_bottom "value=" 2 "/ >        <enum name= "Left_bottom" value= "3"/>    </attr>    <attr name= "radius" format= "dimension "></attr>    <declare-styleable name=" Arcmenu ">        <attr name=" position "/>        <attr Name= "radius"/>    </declare-styleable></resources>

3. Get these attributes in a custom ViewGroup

Arcmenu.java

/** * @author Zhy */public class Arcmenu extends ViewGroup implements onclicklistener{private static final String TAG = "A Rcmenu ";/** * Menu display location */private Position mposition = position.left_top;/** * Menu display radius, default 100dp */private int mradius = 100;/  * * User-clicked button */private View mbutton;/** * Current arcmenu status */private Status Mcurrentstatus = status.close;/** * Callback interface */private Onmenuitemclicklistener onmenuitemclicklistener;/** * State Enumeration class * * @author Zhy * */public enum Status{open, close}/** * Set Place menu realistic Position, four select 1, default right * * * @author zhy */public enum position{left_top, Right_top, Right_bottom, Left_bottom;} public interface Onmenuitemclicklistener{void OnClick (view view, int pos);} Public Arcmenu (Context context) {This (context, null);} Public Arcmenu (context context, AttributeSet Attrs) {This (context, attrs, 0);}  /** * Initialization Properties * * @param context * @param attrs * @param defstyle */public arcmenu (context context, AttributeSet attrs, int Defstyle) {Super (context, attrs, defstyle);//dp Convert to Pxmradius = (int) TYpedvalue.applydimension (Typedvalue.complex_unit_dip,mradius, Getresources (). Getdisplaymetrics ()); TypedArray a = Context.gettheme (). Obtainstyledattributes (Attrs,r.styleable.arcmenu, Defstyle, 0); int n = A.getindexcount (); for (int i = 0, i < n; i++) {int attr = A.getindex (i); switch (attr) {case r.styleable.arcmenu_position: int val = a.getint (attr, 0); switch (val) {case 0:mposition = position.left_top;break;case 1:mposition = position.right_top ; Break;case 2:mposition = position.right_bottom;break;case 3:mposition = position.left_bottom;break;} Break;case r.styleable.arcmenu_radius://dp Convert to Pxmradius = A.getdimensionpixelsize (attr, (int) Typedvalue.applydimension (Typedvalue.complex_unit_dip, 100f,getresources (). Getdisplaymetrics ())); break;}} A.recycle ();}

4. Calculate the size of the child elements:

@Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {int count = Getchildcount (); for (int i = 0; I < count; i++) {//mesure childgetchildat (i). measure (measurespec.unspecified,measurespec.unspecified);} Super.onmeasure (Widthmeasurespec, heightmeasurespec);}

5. Determine the location of the child elements:

@Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {if (changed) {Layoutbutton (); int count = GetC  Hildcount ();/** * Set all children's positions for example (first button): Top left, left to right] 2nd: Mradius (Sin0, COS0) * 3rd: Mradius (Sina, Cosa) Note: [A = MATH.PI/2 * (cCount-1)] * 4th: Mradius (SIN2A, cos2a) 5th: Mradius (sin3a, cos3a) ... */for (int i = 0; i < count-1; i++) {View child = Getchilda T (i + 1); child.setvisibility (view.gone); int cl = (int) (Mradius * Math.sin (MATH.PI/2/(count-2) * i)); int ct = (int) ( Mradius * Math.Cos (MATH.PI/2/(count-2) * i));//Childview Widthint cwidth = Child.getmeasuredwidth ();//Childview Hei Ghtint cheight = Child.getmeasuredheight ();//upper right, lower right if (mposition = = Position.left_bottom| | mposition = = Position.RIGHT_ BOTTOM) {ct = getmeasuredheight ()-cheight-ct;} Upper right, lower right if (mposition = = position.right_top| | mposition = = position.right_bottom) {cl = Getmeasuredwidth ()-cwidth-cl;} LOG.E (TAG, cl + "," + ct); Child.layout (cl, CT, cl + cwidth, CT + cheight);}}

First, set the button position in the Layoutbutton, and initialize the Click event, then start with the second child element as the menu item, set its position separately, the calculation principle is the above I draw sketch, can go to look carefully, hands on the paper to draw a picture.

/** * The first child element is a button, the button layout is initialized and the Click event */private void Layoutbutton () {View CButton = getchildat (0); Cbutton.setonclicklistener ( this); int L = 0;int t = 0;int width = cbutton.getmeasuredwidth (); int height = cbutton.getmeasuredheight (); switch (mpositio N) {case left_top:l = 0;t = 0;break;case Left_bottom:l = 0;t = Getmeasuredheight ()-Height;break;case RIGHT_TOP:l = GetMea Suredwidth ()-width;t = 0;break;case right_bottom:l = getmeasuredwidth ()-width;t = Getmeasuredheight ()-height;break;} LOG.E (TAG, L + "," + t + "," + (l + width) + "," + (t + height)); Cbutton.layout (L, T, L + width, t + height);}

This is the code that locates the button, at which point the code has been positioned, if you put the onlayout in Childview.setvisibility (VISIBLE). The entire control of the Arcmenu has been implemented, followed by the Click event, the implementation of the effect animation.

6. Set Button click event

/** * Add Click event for button */@Overridepublic void OnClick (View v) {Mbutton = Findviewbyid (R.id.id_button); if (Mbutton = = null) {Mbutto n = getchildat (0);} Rotateview (Mbutton, 0f, 270f, Togglemenu (300);}

/** * Button Rotation animation * * @param view * @param fromdegrees * @param todegrees * @param durationmillis */public static void rotate View (view view, float fromdegrees,float todegrees, int durationmillis) {rotateanimation rotate = new Rotateanimation ( Fromdegrees, Todegrees,animation.relative_to_self, 0.5f, animation.relative_to_self,0.5f); Rotate.setDuration ( Durationmillis); Rotate.setfillafter (true); view.startanimation (rotate);} public void Togglemenu (int durationmillis) {int count = Getchildcount (), for (int i = 0; i < count-1; i++) {final View C Hildview = Getchildat (i + 1); childview.setvisibility (view.visible); int xflag = 1;int Yflag = 1;if (mposition = = Position.L eft_top| |  Mposition = = position.left_bottom) Xflag = -1;if (mposition = position.left_top| | mposition = Position.RIGHT_TOP) Yflag = -1;//child Leftint cl = (int) (Mradius * Math.sin (MATH.PI/2/(count-2) * i)),//child topint ct = (int) (Mradius * Math.Cos (MATH.PI/2/(count-2) * i)); Animationset animset = new Animationset (True); Animation Animation = null;if (Mcurrentstatus = = Status.close) {//To Openanimset.setinterpolator (new Overshootinterpolator (2F)) animation = new Translateanimation (Xflag * cl, 0, Yflag * ct, 0); Childview.setclickable (True) ; Childview.setfocusable (true);} else{//to Closeanimation = new Translateanimation (0f, Xflag * cl, 0f, Yflag* CT); childview.setclickable (false); Childview . setfocusable (false);} Animation.setanimationlistener (New Animationlistener () {public void Onanimationstart (animation animation) {}public void Onanimationrepeat (Animation Animation) {}public void Onanimationend (Animation Animation) {if (Mcurrentstatus = = Status.close) childview.setvisibility (View.gone);}); Animation.setfillafter (True); Animation.setduration (durationmillis);//Set a start delay time for the animation, purely beautiful, May not set Animation.setstartoffset ((I *)/(count-1)); Rotateanimation rotate = new Rotateanimation (0, 720,animation.relative_to_self, 0.5f,animation.relative_to_self, 0.5f ); Rotate.setduration (Durationmillis); Rotate.setfillafter (True); animset.addanimation (rotate); animset.addanimation (animation); childview.startanimation (animset); final int index = i + 1;childview.setonclicklistener (new View.onclicklistener () {@Overridepublic void OnClick (View v) {if ( Onmenuitemclicklistener = null) Onmenuitemclicklistener.onclick (Childview, index-1); Menuitemanin (index-1); Changestatus ();}});} Changestatus (); LOG.E (TAG, Mcurrentstatus.name () + "");}

When clicked, trigger Tanslateanimation animation, extend from the point outward, also add a rotation animation to the Click button, each sub-menu item also added rotation animation, and if the user set callback, call callback interface, Set submenu of Click event. The whole is click then animation effect ~ ~

7. Set sub-menu click events

/** * Start Menu animation, click on the MenuItem zoom disappears, other shrink disappears * @param item */private void menuitemanin (int item) {for (int i = 0; i < Getchildco UNT ()-1; i++) {View Childview = getchildat (i + 1), if (i = = Item) {childview.startanimation (Scalebiganim);} else{ Childview.startanimation (Scalesmallanim (300));} Childview.setclickable (false); childview.setfocusable (false);}} /** * Shrinking disappears * @param durationmillis * @return */private Animation scalesmallanim (int durationmillis) {Animation anim = new S Caleanimation (1.0f, 0f, 1.0f, 0f,animation.relative_to_self, 0.5f, animation.relative_to_self,0.5f); Anim.setduration (Durationmillis); Anim.setfillafter (true); return anim;} /** * Zoom in, transparency down * @param durationmillis * @return */private Animation scalebiganim (int durationmillis) {Animationset Animati onset = new Animationset (true); Animation anim = new Scaleanimation (1.0f, 4.0f, 1.0f, 4.0f,animation.relative_to_self, 0.5f, animation.relative_to_self , 0.5f); Animation alphaanimation = new Alphaanimation (1, 0); Animationset.addanimation (ANIm); Animationset.addanimation (alphaanimation); animationset.setduration (Durationmillis); Animationset.setfillafter (True); return animationset;}

Click on the menu item to become larger and slowly disappear, the menu item is not clicked disappear ~ Interested can be changed to their favorite animation ~

Note: Many of the animation effects of the EoE on the man's code, this kind of animation is relatively simple, not much said ~


All right, the rest is some getter,setter.

8. Layout file:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http// Schemas.android.com/tools "xmlns:zhy=" Http://schemas.android.com/apk/res/com.example.zhy_arcmenu "android:layout _width= "Match_parent" android:layout_height= "Match_parent" > <com.example.zhy_arcmenu. Arcmenu android:id= "@+id/id_arcmenu1" android:layout_width= "fill_parent" android:layout_height= "Fill_ Parent "zhy:position=" Left_top "zhy:radius=" 130DP "> <relativelayout android:layout_ Width= "Wrap_content" android:layout_height= "wrap_content" android:background= "@drawable/composer_but Ton "> <imageview android:id=" @+id/id_button "android:layout_width=" Wrap_co                Ntent "android:layout_height=" Wrap_content "android:layout_centerinparent=" true " android:src= "@drawable/composer_icn_plus"/> </relativelayout> <imageview android:layout_width= "wrap_content" android:layout_height= "Wrap_conte NT "android:layout_centerinparent=" true "android:src=" @drawable/composer_camera "Android: tag= "Camera"/> <imageview android:layout_width= "wrap_content" android:layout_height= "W Rap_content "android:layout_centerinparent=" true "android:src=" @drawable/composer_sun "an droid:tag= "Sun"/> <imageview android:layout_width= "Wrap_content" android:layout_height            = "Wrap_content" android:layout_centerinparent= "true" android:src= "@drawable/composer_place" android:tag= "Place"/> <imageview android:layout_width= "Wrap_content" Androi d:layout_height= "Wrap_content" android:layout_centerinparent= "true" android:src= "@drawable/composer_ Sleep "Android:tag= "Sleep"/> </com.example.zhy_arcmenu. Arcmenu>

Well, the first element is the button, the other is the menu item ~ ~ Like with code, can also code generation, I prefer to write these things in the layout file ~

9, Mainactivity

Package Com.example.zhy_arcmenu;import Android.app.activity;import Android.os.bundle;import Android.view.View; Import Android.view.window;import android.widget.imageview;import Android.widget.toast;import com.example.zhy_ Arcmenu. Arcmenu.onmenuitemclicklistener;public class Mainactivity extends Activity{private arcmenu marcmenulefttop;@ overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview ( R.layout.activity_main); marcmenulefttop = (Arcmenu) Findviewbyid (R.ID.ID_ARCMENU1);//dynamically add a Menuitemimageview People = new ImageView (this);p Eople.setimageresource (r.drawable.composer_with);p Eople.settag ("people"); Marcmenulefttop.addview (people); Marcmenulefttop.setonmenuitemclicklistener (new Onmenuitemclicklistener () {@ overridepublic void OnClick (view view, int pos) {toast.maketext (Mainactivity.this,pos + ":" + View.gettag (), toast.length _short). Show ();}});}}



End ~ ~ Have any comments Welcome to point ~ ~


SOURCE Click to download



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.