Android own definition ViewGroup teach you to achieve Arcmenu

Source: Internet
Author: User
Tags cos sin

Tag: offset with position imp settag position OTT problem visible

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

Stroll EoE found this 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 define your own ViewGroup write this effect, your own definition of 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, possibly someone said. That's not easy. The default elements are at the fixed point location. And then traslateanimation, so ignore the point, that is traslateanimation despite the animation effect, but the essence is not change the position of the button, our button animation end is to click, and one might say that the use of property animation, or change leftmagin,rightmagin, which may be more troublesome, in fact we can by default 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 bit of mathematical knowledge. I drew a sketch (the Ice and snow). Kneeling glass ballast to draw the following diagram of the tool):


Each time it is based on the number of sub-menus. The angle of a is calculated, then the left, top of each sub-menu is calculated by sin, cos respectively;

Of course this is the case on the left. If you are on top right, then top is still the same as the top left. Left is (width of the screen-right-hand exit); the other two directions the same ~


Overall I define a viewgroup by myself, the first child element in this viewgroup is a click button (you can lay it out casually.) Whatever control is used), the next child element I think is the menu item. Based on, decide to expand the radius and display location, let the user to customize.

Here's a look at the detailed implementation:

2. Define the properties of the view yourself:

<?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 your own defined 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 */pri  Vate Onmenuitemclicklistener onmenuitemclicklistener;/** * State Enumeration class * * @author Zhy * */public enum Status{open, CLOSE}/** * Set Menu Realistic location, four select 1. Default Lower 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 such as (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++) {Vie W child = Getchildat (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 Heightint 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, the button position in the Layoutbutton can be set, as well as initialize the click event, and then from the second child element start as a menu item, set its position separately, the calculation principle is the above I draw the sketch, can go to the detailed look, 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.getmeasur Edheight (); switch (mposition) {case left_top:l = 0;t = 0;break;case Left_bottom:l = 0;t = Getmeasuredheight ()-Height;brea K;case right_top:l = Getmeasuredwidth ()-width;t = 0;break;case right_bottom:l = getmeasuredwidth ()-width;t = GetMeasur Edheight ()-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 this point the code has been positioned, assuming you put the onlayout in Childview.setvisibility (VISIBLE).

The entire control of Arcmenu has been implemented, followed by a click event. The effect animation has been implemented.

6. Set Button click event

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

/** * Button Rotation animation * * @param view * @param fromdegrees * @param todegrees * @param durationmillis */public static void ro Tateview (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, which is purely good-looking, Can 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, triggers the Tanslateanimation animation. Scale out from fixed point. Also adds a rotation animation to the click button. Each submenu item is joined in the same rotation animation, and the user is assumed to set the callback. Invokes the callback interface. Sets the Click event for the submenu. Overall is click then animation effect ~ ~

7. Set sub-menu click events

/** * Start Menu animation. Click on the MenuItem to enlarge disappears. Other narrowing disappears * @param item */private void menuitemanin (int item) {for (int i = 0; i < Getchildcount ()-1; i++) {View Childvie W = 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 Reduction * @param Durationmillis * @return */private Animation scalebiganim (int durationmillis) {Animationset Animationset = n EW 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;}

The clicked menu item becomes big and disappears slowly and transparently, the menu item that is not clicked disappears ~ is interested to be able to change the animation which oneself likes ~

Note: The animation effect is very much borrowed from the EoE on the man's code, this kind of animation is also relatively simple. It's not much to say ~


All right, the rest is the getter. Setter Up ~

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 a button, the other is the menu item ~ ~ Like in code, also can code generation, I am more like the layout of the file to write these things ~

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);//dynamic Join 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 ~ ~ There is no matter what the comments Welcome to point ~ ~


Source code click to download




Android own definition ViewGroup teach you to achieve Arcmenu

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.