Android implementation of customized satellite menu (Curved menu) Detailed _android

Source: Internet
Author: User
Tags cos sin sleep stub

First, the preface

Android implementation of the satellite menu is also called the Arc menu, the main work to do is as follows:

1. The processing of animation

2. Custom ViewGroup to implement the satellite menu view

(1) Custom properties

A. Defining properties in Attrs.xml

B. Using custom attributes in a layout

C. Reading custom attributes from View a layout file in a customization

(2) onMeasure measuring child is the main button and the menu item

(3) onLayout layout child is the layout of the main button and menu items

(4) Set the selection animation of the main button

A. menuItem add a translation animation and a rotational animation to a menu item

B. Implementing menuItem The Click Animation of the menu item

Screenshot of satellite menu effect:

Second, realize

The above describes the principle and effect diagram, the following to see the implementation of the Satellite menu class:

1. The implementation of the layout file

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http:// Schemas.android.com/tools "xmlns:xcskin=" Http://schemas.android.com/apk/res/com.xc.xcskin "android:id=" @+id/ Container "android:layout_width=" match_parent "android:layout_height=" Match_parent "> < Com.xc.xcskin.view.XCArcMenuView android:id= "@+id/arcmenu" android:layout_width= "150DP" android:layout_height= " 150DP "android:layout_alignparentbottom=" true "android:layout_alignparentleft=" true "xcskin:position=" Left_bottom "xcskin:radius=" 120DP "> <relativelayout android:layout_width=" wrap_content "android:layout_height=" wrap _content "android:background=" @drawable/composer_button "> <imageview android:id=" @+id/id_button "and Roid:layout_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_centerinparent= "true" and
  roid:src= "@drawable/composer_icn_plus"/> </RelativeLayout> <imageview  Android:id= "@+id/id_button" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" Android : src= "@drawable/composer_camera" android:tag= "Camera"/> <imageview android:id= "@+id/id_button" Androi D:layout_width= "Wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/composer_music" Andr oid:tag= "Music"/> <imageview android:id= "@+id/id_button" android:layout_width= "Wrap_content" Android:
    layout_height= "Wrap_content" android:src= "@drawable/composer_place" android:tag= "place"/> <imageview Android:id= "@+id/id_button" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" android:s rc= "@drawable/composer_sleep" android:tag= "Sleep"/> <imageview android:id= "@+id/id_button" Android:la Yout_width= "Wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/composer_thought" Androi
  d:tag= "thought"/><imageview android:id= "@+id/id_button" android:layout_width= wrap_content "android:layout_height=" Wrap_cont
 
 Ent "android:src=" @drawable/composer_with "android:tag=" with "/> </com.xc.xcskin.view.XCArcMenuView> <com.xc.xcskin.view.xcarcmenuview android:id= "@+id/arcmenu2" android:layout_width= "Wrap_content" Android:
  layout_height= "Wrap_content" android:layout_alignparentbottom= "true" android:layout_alignparentright= "true"
   xcskin:position= "Right_bottom" xcskin:radius= "150DP" > <relativelayout android:layout_width= "wrap_content" android:layout_height= "Wrap_content" android:background= "@drawable/composer_button" > <imageview androi D:id= "@+id/id_button" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" Android:layout_ Centerinparent= "true" android:src= "@drawable/composer_icn_plus"/> </RelativeLayout> <imageview an Droid:id= "@+id/id_button" Android:laYout_width= "Wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/composer_camera" Android : tag= "Camera"/> <imageview android:id= "@+id/id_button" android:layout_width= "Wrap_content" Android:la yout_height= "Wrap_content" android:src= "@drawable/composer_music" android:tag= "Music"/> <imageview an Droid:id= "@+id/id_button" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" android:src = "@drawable/composer_place" android:tag= "place"/> <imageview android:id= "@+id/id_button" Android:layo Ut_width= "Wrap_content" android:layout_height= "wrap_content" android:src= "@drawable/composer_sleep" Android:ta g= "Sleep"/> <imageview android:id= "@+id/id_button" android:layout_width= "Wrap_content" android:layout _height= "Wrap_content" android:src= "@drawable/composer_thought" android:tag= "thought"/> <imageview an Droid:id= "@+id/id_button"Android:layout_width=" wrap_content "android:layout_height=" wrap_content "android:src=" @drawable/composer_wit H "android:tag=" with "/> </com.xc.xcskin.view.XCArcMenuView> </RelativeLayout>

2. Implementation of the Satellite menu class

Package Com.xc.xcskin.view;

Import COM.XC.XCSKIN.R;
Import Android.content.Context;
Import Android.content.res.TypedArray;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import Android.util.TypedValue;
Import Android.view.View;
Import Android.view.View.OnClickListener;
Import Android.view.ViewGroup;
Import android.view.animation.AlphaAnimation;
Import android.view.animation.Animation;
Import Android.view.animation.Animation.AnimationListener;
Import Android.view.animation.AnimationSet;
Import android.view.animation.RotateAnimation;
Import android.view.animation.ScaleAnimation;
Import android.view.animation.TranslateAnimation; /** * Satellite Menu View * @author caizhiming * * */public class Xcarcmenuview extends ViewGroup implements onclicklistener{p
 rivate static final int pos_left_top = 0;
 private static final int pos_left_bottom = 1;
 private static final int pos_right_top = 2;
 
 private static final int pos_right_bottom = 3; Private Position mposition = Position.right_BOTTOM;
 private int Mradius;
 Private Status mstatus = Status.close;
 Main Course single button private View Mcbutton;
 Private Onmenuitemclicklistener Monmenuitemclicklistener; /** * Menu Status Enumeration class * @author caizhiming * * */public enum status{open,close}/** * Menu Position Enumeration class * @author Caizhi Ming */public enum position{Left_top,left_bottom, Right_top,right_bottom}/** * Click the callback interface for the submenu item * @author
 caizhiming * */public interface Onmenuitemclicklistener {void OnClick (view view, int pos); } public void Setonmenuitemclicklistener (Onmenuitemclicklistener onmenuitemclicklistener) {This.monmenuitemclickl
 Istener = Onmenuitemclicklistener;
  The public Xcarcmenuview {This (context, NULL); TODO auto-generated Constructor stub} public Xcarcmenuview (context, AttributeSet attrs) {The context, at
  TRS, 0); TODO auto-generated Constructor stub} public Xcarcmenuview (context, AttributeSet attrs, int defstyle) {su Per (contExt, attrs, defstyle);
    TODO auto-generated constructor stub//Get custom attribute TypedArray a = Context.gettheme (). Obtainstyledattributes (Attrs,
  r.styleable.xcarcmenuview,defstyle,0);
  int pos = A.getint (r.styleable.xcarcmenuview_position, Pos_right_bottom);
    Switch (POS) {case pos_left_top:mposition = position.left_top;
   Break
    Case pos_left_bottom:mposition = Position.left_bottom;
   Break
    Case pos_right_top:mposition = position.right_top;
   Break
    Case pos_right_bottom:mposition = Position.right_bottom;
  Break } Mradius = (int) a.getdimension (R.styleable.xcarcmenuview_radius, (int) typedvalue.applydimension (TypedValue.COMPL
  Ex_unit_dip, Getresources (), Getdisplaymetrics ()));
  LOG.V ("Czm", "mposition =" + Mposition + ", Mradius =" +mradius);
 A.recycle (); @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//TODO auto-generated method Stu
  b int count = Getchildcount (); For (int i = 0; I < count;
  i + +) {Measurechild (Getchildat (i), Widthmeasurespec, Heightmeasurespec);
 } super.onmeasure (Widthmeasurespec, Heightmeasurespec);
  @Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {//TODO auto-generated method stub
   if (changed) {Layoutcbutton ();
  Layoutmenuitems (); }/** * Layout main Menu item */private void Layoutcbutton () {//TODO auto-generated method Stub Mcbutton = Getchildat (
  0);
  Mcbutton.setonclicklistener (this);
  int l = 0;
  int t = 0;
  int width = mcbutton.getmeasuredwidth ();
  int height = mcbutton.getmeasuredheight ();
    Switch (mposition) {case left_top:l = 0;
    t = 0; 
   Break
    Case left_bottom:l = 0;
    t = getmeasuredheight ()-height;
   Break
    Case right_top:l = Getmeasuredwidth ()-width;
    t = 0;
   Break
    Case right_bottom:l = Getmeasuredwidth ()-width;
    t = getmeasuredheight ()-height;
   Break
  Default:break; } Mcbutton.layoUT (l, T, L + width, t + height); }/** * Layout menu item */private void Layoutmenuitems () {//TODO auto-generated method Stub int count = Getchildcount ()
  ;
   for (int i = 0; i < count-1. i++) {View child = Getchildat (i + 1);
   int L = (int) (Mradius * Math.sin (MATH.PI/2/(count-2) * i));
   int t = (int) (Mradius * Math.Cos (MATH.PI/2/(count-2) * i));
   int width = child.getmeasuredwidth ();

   int height = child.getmeasuredheight (); If the menu position is at the bottom left, lower right if (mposition = Position.left_bottom | | | mposition = = position.right_bottom) {t = Getmeasuredhe
   Ight ()-height-t;  //upper Right, bottom right if (mposition = Position.right_top | | | mposition = = position.right_bottom) {L = getmeasuredwidth ()-
   Width-l;
   } child.layout (L, T, L + width, t + height);
  Child.setvisibility (View.gone); @Override public void OnClick (View v) {//TODO auto-generated method Stub Mcbutton = Findviewbyid (R.id.id_butt
  ON);
  Rotatecbutton (v,0,360,300); TogglemenU (300); /** * Toggle Menu */public void Togglemenu (int duration) {//TODO auto-generated Method Stub//Add translation animation and rotation to MenuItem

  Draw int count = Getchildcount ();
   for (int i = 0; i < count-1 i++) {final View Childview = getchildat (i + 1);

   Childview.setvisibility (view.visible);
   End 0, 0//start int cl = (int) (Mradius * Math.sin (MATH.PI/2/(count-2) * i));

   int ct = (int) (Mradius * Math.Cos (MATH.PI/2/(count-2) * i));
   int xflag = 1;

   int yflag = 1;
   if (mposition = = Position.left_top | | mposition = = position.left_bottom) {Xflag =-1;
   } if (mposition = = Position.left_top | | mposition = = position.right_top) {Yflag =-1;
   } animationset Animset = new Animationset (true);

   Animation Trananim = null;
    To open if (mstatus = = status.close) {Trananim = new translateanimation (Xflag * cl, 0, Yflag * ct, 0);
    Childview.setclickable (TRUE);

   Childview.setfocusable (TRUE);
} else   To close {Trananim = new Translateanimation (0, Xflag * cl, 0, Yflag * ct);
    Childview.setclickable (FALSE);
   Childview.setfocusable (FALSE);
   } trananim.setfillafter (True);
   Trananim.setduration (duration);

   Trananim.setstartoffset ((i *)/count); Trananim.setanimationlistener (New Animationlistener () {@Override public void Onanimationstart (Animation anima tion) {} @Override public void Onanimationrepeat (Animation Animation) {} @Override P ublic void Onanimationend (Animation Animation) {if (Mstatus = = status.close) {Childview.setvisibilit
     Y (View.gone);
   }
    }
   }); Rotary animation Rotateanimation Rotateanim = new Rotateanimation (0, 720, animation.relative_to_self, 0.5f, Animation.
   Relative_to_self, 0.5f);
   Rotateanim.setduration (duration);

   Rotateanim.setfillafter (TRUE);
   Animset.addanimation (Rotateanim);
   Animset.addanimation (Trananim); Childview.startanimatIon (Animset);
   Final int pos = i + 1; Childview.setonclicklistener (New Onclicklistener () {@Override public void OnClick (View v) {if monme

     Nuitemclicklistener!= null) Monmenuitemclicklistener.onclick (Childview, POS);
     Menuitemanim (POS-1);

    Changestatus ();
  }
   });
  
 //Toggle Menu Status Changestatus (); /** * Select Main Menu button */private void Rotatecbutton (View V, float start, float end, int duration) {//TODO auto-g enerated method Stub Rotateanimation anim = new Rotateanimation (start, End, Animation.relative_to_self, 0.5f, Animat Ion.
  Relative_to_self, 0.5f);
  Anim.setduration (duration);
  Anim.setfillafter (TRUE);
 V.startanimation (ANIM); /** * Add MenuItem Click Animation * */private void Menuitemanim (int pos) {for (int i = 0; i < Getchildcount ()-1;
   i++) {View Childview = getchildat (i + 1);
   if (i = = pos) {childview.startanimation (Scalebiganim (300)); else {childview.startanimation(Scalesmallanim (300));
   } childview.setclickable (FALSE);

  Childview.setfocusable (FALSE); }/** * Set smaller and more transparent animation for the currently clicked Item * @param duration * @return/private Animation scalesmallanim (int duratio

  N) {Animationset animationset = new Animationset (true); Scaleanimation Scaleanim = new Scaleanimation (1.0f, 0.0f, 1.0f, 0.0f, Animation.relative_to_self, 0.5f, Animation.rela
  Tive_to_self, 0.5f);
  Alphaanimation Alphaanim = new Alphaanimation (1f, 0.0f);
  Animationset.addanimation (Scaleanim);
  Animationset.addanimation (Alphaanim);
  Animationset.setduration (duration);
  Animationset.setfillafter (TRUE);

 return animationset; /** * For the current click of the item to set a larger and less transparent animation/private Animation Scalebiganim (int duration) {Animationset Animationset = NE

  W Animationset (True); Scaleanimation Scaleanim = new Scaleanimation (1.0f, 4.0f, 1.0f, 4.0f, Animation.relative_to_self, 0.5f, Animation.rela
  Tive_to_self, 0.5f); Alphaanimation Alphaanim = new ALPHaanimation (1f, 0.0f);
  Animationset.addanimation (Scaleanim);

  Animationset.addanimation (Alphaanim);
  Animationset.setduration (duration);
  Animationset.setfillafter (TRUE);

 return animationset; /** * Toggle Menu state */private void Changestatus () {mstatus = (Mstatus = = Status.close?
 Status.OPEN:Status.CLOSE);
 /** * is in the expanded state * @return * * public boolean IsOpen () {return mstatus = = Status.open; }
 
 
}

3. Using the Satellite menu class

 package Com.xc.xcskin;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.view.View;

Import Android.widget.Toast;
Import Com.xc.xcskin.view.XCArcMenuView;
Import Com.xc.xcskin.view.XCArcMenuView.OnMenuItemClickListener;
Import Com.xc.xcskin.view.XCGuaguakaView;

Import Com.xc.xcskin.view.XCGuaguakaView.OnCompleteListener; /** * Use and test the custom Satellite menu View * @author caizhiming * * */public class Xcarcmenuviewdemo extends activity{@Override Protec
  Ted void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
  Setcontentview (R.layout.xc_arcmenu_view_demo);
  Xcarcmenuview view = (Xcarcmenuview) Findviewbyid (R.id.arcmenu); View.setonmenuitemclicklistener (New Onmenuitemclicklistener () {@Override public void OnClick (view view, int pos
    {//TODO auto-generated method Stub String tag = (string) view.gettag ();
   Toast.maketext (xcarcmenuviewdemo.this, Tag, Toast.length_short). Show ();
 }
  }); }
}

Third, summary

Android implementation of the customized satellite menu (curved menu) content to this is basically over, interested friends can start to operate, only their own practice to a deeper understanding, I hope this article can help.

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.