Android Custom view realizes circular and semicircular menu _android

Source: Internet
Author: User
Tags commit

Recently saw the big large round menu, want to start imitation, because it is too cool, and then according to others (brother ZW) to tell me some ideas, some analysis, began to transform their own round menu.

Article structure: 1. function introduction and display; 2. Part of the code to explain; 3. The UI effects can be demonstrated in general. 4. Source code comes in.

I. Introduction and presentation of functions

The first display is the original of this control. But we can use a lot of tricks to achieve our business UI effect.

Here is the display of this blog works demo and the 3rd linkage show, visible is a round menu, compared to the Yu Hongyang big round menu More than a few needs:

1. The display only needs a semicircle turntable.

2. Do not allow them to rotate automatically at the specified angle (some mathematical calculations involving extension will be explained in detail).

3. To bind fragment.

4. A buffering angle, that is, we're going to fix a few positions, not anywhere. We want to design a possible angle to automatically help him choose.

second, the code to explain :

The actual use of the way to explain. Divided into: 1. Calling mode; 2. The Onmeasure method of this control, the function of 3.onLayout method, 4. Use of this control event mechanism dispatchtouchevent; 5. Mathematical calculation-a buffer angle.

(1) Mode of invocation: (Code is the effect code below the display area)

Adopt is linkage, use Fragment manager fragmenttransaction to realize fragment management package com.fuzhucheng.circlemenu;
Import Android.os.Bundle;
Import android.support.v4.app.FragmentTransaction;
Import android.support.v7.app.AppCompatActivity;
Import android.view.KeyEvent;
Import Android.view.View;

Import Android.widget.Toast;

 public class Mainactivity extends Appcompatactivity {private upcirclemenulayout mycirclemenulayout;
 Four fragment pages private homepagefragment homepagefragment;
 Private Settingfragment settingfragment;
 Private Historyfragment historyfragment;
 Private Fourthfragment fourthfragment;

 Private Fifthfragment fifthfragment; Private string[] mitemtexts = new string[]{"Security Center", "Special services", "investment banking", "Transfer remittance", "My Account", "Security Center", "Special services", "investment banking", "Transfer remittance", "my
 Account "}; Private int[] Mitemimgs = new Int[]{r.drawable.home_mbank_1_normal, R.drawable.home_mbank_2_normal, R.drawable.home_ Mbank_3_normal, R.drawable.home_mbank_4_normal, R.drawable.home_mbank_5_normal, R.drawable.home_mbank_1_normal, R.Drawable.home_mbank_2_normal, R.drawable.home_mbank_3_normal, R.drawable.home_mbank_4_normal, R.drawable.home_

 Mbank_5_normal};
  @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);

  Setcontentview (R.layout.activity_main);
  First initialization home default display first fragment InitFragment1 ();
  Mycirclemenulayout = (upcirclemenulayout) Findviewbyid (r.id.id_mymenulayout); Mycirclemenulayout.setmenuitemiconsandtexts (MITEMIMGS)//Set Picture Mycirclemenulayout.setonmenuitemclicklistener ( New Upcirclemenulayout.onmenuitemclicklistener () {@Override public void ItemClick (int pos) {Toast.maketext (Ma
    Inactivity.this, Mitemtexts[pos], Toast.length_short). Show ();
      Switch (POS) {case 0:initfragment1 ();
      Settitle ("Security Centre");
     Break
      Case 1:initfragment2 ();
      Settitle ("Special Service");
     Break
      Case 2:initfragment3 ();
      Settitle ("Investment and financial management");
     Break
      Case 3:initfragment4 (); Settitle ("Transfer remittance");
     Break
      Case 4:INITFRAGMENT5 ();
      Settitle ("My Account");
     Break
      Case 5:initfragment1 ();
      Settitle ("Security Centre");
     Break
      Case 6:initfragment2 ();
      Settitle ("Special Service");
     Break
      Case 7:initfragment3 ();
      Settitle ("Investment and financial management");
     Break
      Case 8:initfragment4 ();
      Settitle ("Transfer remittance");
     Break
      Case 9:INITFRAGMENT5 ();
      Settitle ("My Account");
    Break } @Override public void Itemcenterclick (view view) {Toast.maketext (Mainactivity.this, "the Can do s
   Omething just like CCB ", Toast.length_short). Show ();

 }
  }); //Show first fragment private void InitFragment1 () {//Open transaction, fragment control is implemented by transaction homepagefragment = new Homepagefragment
  ();
  Fragmenttransaction transaction = Getsupportfragmentmanager (). BeginTransaction ();
  Transaction.replace (r.id.fragment_tv,homepagefragment);
  Transaction.addtobackstack (NULL);
 Transaction.commit (); }//Show second FRAgment private void InitFragment2 () {//Open transaction, fragment control is implemented by transaction settingfragment = new Settingfragment ();
  Fragmenttransaction transaction = Getsupportfragmentmanager (). BeginTransaction ();
  Transaction.replace (r.id.fragment_tv,settingfragment);
  Transaction.addtobackstack (NULL);
 Transaction.commit ();
  private void InitFragment3 () {//Open transaction, fragment control is implemented by transaction historyfragment = new Historyfragment ();
  Fragmenttransaction transaction = Getsupportfragmentmanager (). BeginTransaction ();
  Transaction.replace (r.id.fragment_tv,historyfragment);
  Transaction.addtobackstack (NULL);
 Transaction.commit ();
  private void InitFragment4 () {//Open transaction, fragment control is implemented by transaction fourthfragment = new Fourthfragment ();
  Fragmenttransaction transaction = Getsupportfragmentmanager (). BeginTransaction ();
  Transaction.replace (r.id.fragment_tv,fourthfragment);
  Transaction.addtobackstack (NULL);
 Transaction.commit (); private void InitFragment5 () {//Open transaction, fragment control is implemented by transaction Fifthfragment = new Fifthfragment ();
  Fragmenttransaction transaction = Getsupportfragmentmanager (). BeginTransaction ();
  Transaction.replace (r.id.fragment_tv,fifthfragment);
  Transaction.addtobackstack (NULL);
 Transaction.commit (); public boolean onKeyDown (int keycode, keyevent event) {if (keycode = = Keyevent.keycode_back && event.g
   Etrepeatcount () = = 0) {finish ();
  return true;
 Return Super.onkeydown (KeyCode, event);

 }
}

(2) This control Onmeasure method: Focus on iterative measurement

/** * Sets the width of the layout and the Policy menu item is wide/high/@Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
  int reswidth = 0;
  int resheight = 0;

  Double startangle = Mstartangle; Double angle = 360/10;
  We've got 10 kids in there./** * According to the incoming parameters, respectively, obtain the measurement mode and measurement value/int width = measurespec.getsize (widthmeasurespec);

  int widthmode = Measurespec.getmode (Widthmeasurespec);
  int height = measurespec.getsize (heightmeasurespec);

  int heightmode = Measurespec.getmode (Heightmeasurespec); /** * If the width or height of the measurement mode is not the exact value of/if (Widthmode!= measurespec.exactly | | | heightmode!= measurespec.exactly) {//Main

   Height reswidth = getdefaultwidth () set as background image;

  Resheight = (int) (reswidth * default_banner_heigth/default_banner_width);
  else {//If all are set to the exact value, take the decimal value directly; reswidth = Resheight = math.min (width, height);

  } setmeasureddimension (Reswidth, resheight);

  Obtain diameter Mradius = Math.max (Getmeasuredwidth (), Getmeasuredheight ()); menu item Quantity Final int couNT = Getchildcount ();

  menu item size int childsize;

  menu item measurement mode int childmode = measurespec.exactly;
  Iterative measurement: Iterate over the number of children, measure size for each child, and set up a listener callback.
   for (int i = 0; i < count; i++) {final View child = Getchildat (i);
   StartAngle = startangle% 360; if (startangle > MB && startangle < 271 && istouchup) {Monmenuitemclicklistener.itemclick (i);
    Sets the listener callback. Mcurrentposition = i; This time using mcurrentposition, just put him as a temp variable, can have more use, such as dynamically set the angle of each child childsize = densityutil.dip2px (GetContext (), Radio_ top_child_dimension);//Set size} else {childsize = densityutil.dip2px (GetContext (), radio_default_child_dimension);
   Set size} if (child.getvisibility () = = GONE) {continue;

   //Calculate the menu item size, and set the mode to measure the item int makemeasurespec =-1;
   Makemeasurespec = Measurespec.makemeasurespec (childsize, Childmode);
   Child.measure (Makemeasurespec, Makemeasurespec);
  StartAngle + = angle; //item container inner margin mpadding = DensityutIL.DIP2PX (GetContext (), radio_margin_layout);

 }

Onmeasure Depth: View is displayed on the screen first through measure (calculation) and layout (layout). The effect of this method is to compute the width and height of the custom view. The calculation process is based on the size given by the parent layout, and the results are calculated from their own characteristics. Of course, there are related measurements of the size of the model. Here's a good blog: onmeasure understand. In addition, I am also in this method as a listener callback settings!! Setting a picture for a control can directly use the method we designed below: setmenuitemiconsandtexts a word.

(3) OnLayout method of explanation: (Here the circle of mathematical calculation layout icon around the round position can be seen in Hong Yang greatly recommended, speak very clearly, of course, I will explain below)

/** * Set menu item position */@Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {int Layo
  Utradius = Mradius;

  Laying out the "child" views final int childcount = Getchildcount ();
  int left, top;

  The size of the menu item int cwidth;
  According to the number of menu item, calculate angle float angledelay = 360/10;
    Traversal to set the position of the MenuItem for (int i = 0; i < ChildCount; i++) {final View child = Getchildat (i);
   According to the child traversal, set the middle of the top of that size and other picture size. if (Mstartangle > MB && mstartangle < 271 && istouchup) {cwidth = densityutil.dip2px (Getcontex
    T (), radio_top_child_dimension);
   Child.setselected (TRUE);
    else {cwidth = densityutil.dip2px (GetContext (), radio_default_child_dimension);
   Child.setselected (FALSE);
   } if (child.getvisibility () = = GONE) {continue;

   //greater than 360 for the remainder attributable to less than 360 degrees Mstartangle = mstartangle% 360;
   float tmp = 0; Calculates the circle radius of the center point of the picture layout.
   is tmp tmp = LAYOUTRADIUS/2F-CWIDTH/2-mpadding; TMP COSA is the horizontal axis of the menu item's center point.
   Calculates the position of the item, which is the calculated position!!! left = LAYOUTRADIUS/2 + (int) math.round (TMP * MATH.COS (Math.toradians (Mstartangle))-1/2f * Cwid
   TH) + densityutil. dip2px (GetContext (), 1); The ordinate top = LAYOUTRADIUS/2 + (int) math.round (TMP * Math.sin (Math.toradians) for the menu item of TMP Sina (MStar
   Tangle))-1/2f * cwidth) + densityutil. dip2px (GetContext (), 8);

   Then of course is the placement of children, is based on small round to decorate the child.layout (left, top, left + cwidth, top + cwidth);
  Superimposed size mstartangle + = Angledelay;

 }
 }

To give a large calculation of the small circle of the thinking diagram:

(4) The use of this control event mechanism dispatchtouchevent:

Dispatchtouchevent is the handling of touch event distribution, and events (in most cases) begin with the dispatchtouchevent of the activity.
 Executes the super.dispatchtouchevent (EV) and the event is distributed downward. Ontouchevent is the method provided in view, ViewGroup also has this method, the view does not provide onintercepttouchevent.
 The default return true in view indicates that the event was consumed.
  @Override public boolean dispatchtouchevent (Motionevent event) {float x = Event.getx ();

  Float y = event.gety ();
  GetParent (). Requestdisallowintercepttouchevent (True);
    Switch (event.getaction ()) {case Motionevent.action_down://Direct is to get x,y value, there is also a downtime (attached) MLASTX = x;
    Mlasty = y;
    Mdowntime = System.currenttimemillis ();
    Mtmpangle = 0;
   Break Case MotionEvent.ACTION_MOVE:isTouchUp = false;
    Note ISTOUCHUP this marker!!!
    /** * Get the starting angle * * * Float start = Getangle (Mlastx, mlasty);
    /** * Get current angle */float end = Getangle (x, y); If the one or four quadrant, then direct End-start, the angle value is positive if (getquadrant (x, y) = = 1 | | getquadrant (x, y) = 4) {Mstartangle + = End-sta
     Rt Mtmpangle + = end-start;//The angle of rotation at the time of the lift} else//two,Three quadrants, the color angle value is negative {mstartangle + = Start-end;
    Mtmpangle + = Start-end;
    }//re-layout if (mtmpangle!= 0) {requestlayout ();
    } MLASTX = x;

    Mlasty = y;
   Break Case MOTIONEVENT.ACTION_UP://When the finger is up, that's the key, a buffer angle, where we're going to fix a few positions, not anywhere.
    We want to design a possible angle to automatically help him choose.
    Backorpre ();
  Break
 Return Super.dispatchtouchevent (event);

 }

Motionevent Event Mechanism: (This control I only used three) the main event types are: Action_down: Indicates that the user began to touch. Action_move: Indicates that the user is moving (finger or other). ACTION_UP: Indicates that the user raised his finger.

(5) Mathematical calculation-a buffer angle.

 private void Backorpre () {  //buffering angle. That means we're going to fix a few positions, not anywhere. We want to design a possible angle to automatically help him choose.
  istouchup = true;
  float angledelay = 360/10;    This is the angle that each graph is separated from
  //The picture angle of our original upper semicircle should be: 18,54,90,126,162. So here we are: first let the current angle subtract the initial 18 degrees from the angle of each graph. What did you get? is a picture that should be in the pile of angles. So if it's a direct return.
  if ((mStartAngle-18)%angledelay==0) {return
   ;
  }
  float angle = (float) ((mStartAngle-18)%36);     Angle is the one that is not the 18-degree start layout, then the 36-degree integer of the more out part of the angle
  //Below is what we do buffer angle processing, if the more out part of the angle than the picture separated by half of the angle forward into one, if less than to back one.
  if (angledelay/2 > Angle) {
   mstartangle = angle;
  } else if (angledelay/2<angle) {
   Mstartangle = Mstartangle-angle + angledelay;   Mstartangle is the current angle, take more than 36 degrees is more out of the angle, take this more out of the angle to data processing.
  }
  Then rearrange the onlayout
  requestlayout ();
 

As for the other small method details, the visible source code, has the detailed explanation.

Source Code Portal: GitHub Address: android-Custom View Circle and "semicircle" menu like star or fork, thank you!

Okay, android-. The circle of Custom view is finished with the "semicircle" menu. This blog is a careful study of Hong Yang large round menu blog, and here to make further development and write their own understanding.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.