转盘按钮。

 1 package com.lixu.circlemenu;
 2 
 3 
 4 import android.app.Activity;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.widget.TextView;
 8 import android.widget.Toast;
 9 
10 import com.lixu.circlemenu.view.CircleImageView;
11 import com.lixu.circlemenu.view.CircleLayout;
12 import com.lixu.circlemenu.view.CircleLayout.OnItemClickListener;
13 import com.lixu.circlemenu.view.CircleLayout.OnItemSelectedListener;
14 import com.szugyi.circlemenu.R;
15 
16 public class MainActivity extends Activity implements OnItemSelectedListener, OnItemClickListener{
17     
18     private    TextView selectedTextView;
19     
20     @Override
21     protected void onCreate(Bundle savedInstanceState) {
22         super.onCreate(savedInstanceState);
23         setContentView(R.layout.activity_main);
24         
25         CircleLayout circleMenu = (CircleLayout)findViewById(R.id.main_circle_layout);
26         circleMenu.setOnItemSelectedListener(this);
27         circleMenu.setOnItemClickListener(this);
28 
29         //这个TextView仅仅作为演示转盘按钮以何为默认的选中项,
30         //默认的最底部的那一条被选中,然后显示到该TextView中。
31         selectedTextView = (TextView)findViewById(R.id.main_selected_textView);
32         selectedTextView.setText(((CircleImageView)circleMenu.getSelectedItem()).getName());
33     }
34 
35     //圆盘转动到底部,则认为该条目被选中
36     @Override
37     public void onItemSelected(View view, int position, long id, String name) {        
38         selectedTextView.setText(name);
39     }
40 
41     //选择了转盘中的某一条。
42     @Override
43     public void onItemClick(View view, int position, long id, String name) {
44         Toast.makeText(getApplicationContext(), getResources().getString(R.string.start_app) + " " + name, Toast.LENGTH_SHORT).show();
45     }
46 }

引用两个开源类:

 1 package com.lixu.circlemenu.view;
 2 
 3 /*
 4  * Copyright 2013 Csaba Szugyiczki
 5  *
 6  * Licensed under the Apache License, Version 2.0 (the "License");
 7  * you may not use this file except in compliance with the License.
 8  * You may obtain a copy of the License at
 9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 import android.content.Context;
20 import android.content.res.TypedArray;
21 import android.util.AttributeSet;
22 import android.widget.ImageView;
23 
24 import com.szugyi.circlemenu.R;
25 
26 /**
27  * 
28  * @author Szugyi
29  * Custom ImageView for the CircleLayout class.
30  * Makes it possible for the image to have an angle, position and a name.
31  * Angle is used for the positioning in the circle menu.
32  */
33 public class CircleImageView extends ImageView {
34 
35     private float angle = 0;
36     private int position = 0;
37     private String name;
38 
39     public float getAngle() {
40         return angle;
41     }
42 
43     public void setAngle(float angle) {
44         this.angle = angle;
45     }
46 
47     public int getPosition() {
48         return position;
49     }
50 
51     public void setPosition(int position) {
52         this.position = position;
53     }
54     
55     public String getName(){
56         return name;
57     }
58     
59     public void setName(String name){
60         this.name = name;
61     }
62 
63     /**
64      * @param context
65      */
66     public CircleImageView(Context context) {
67         this(context, null);
68     }
69 
70     /**
71      * @param context
72      * @param attrs
73      */
74     public CircleImageView(Context context, AttributeSet attrs) {
75         this(context, attrs, 0);
76     }
77 
78     /**
79      * @param context
80      * @param attrs
81      * @param defStyle
82      */
83     public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
84         super(context, attrs, defStyle);
85         if (attrs != null) {
86             TypedArray a = getContext().obtainStyledAttributes(attrs,
87                     R.styleable.CircleImageView);
88             
89             name = a.getString(R.styleable.CircleImageView_name);
90         }
91     }
92 
93 }
  1 package com.lixu.circlemenu.view;
  2 
  3 import com.szugyi.circlemenu.R;
  4 
  5 /*
  6  * Copyright 2013 Csaba Szugyiczki
  7  *
  8  * Licensed under the Apache License, Version 2.0 (the "License");
  9  * you may not use this file except in compliance with the License.
 10  * You may obtain a copy of the License at
 11  *
 12  *      http://www.apache.org/licenses/LICENSE-2.0
 13  *
 14  * Unless required by applicable law or agreed to in writing, software
 15  * distributed under the License is distributed on an "AS IS" BASIS,
 16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 17  * See the License for the specific language governing permissions and
 18  * limitations under the License.
 19  */
 20 
 21 import android.content.Context;
 22 import android.content.res.TypedArray;
 23 import android.graphics.Bitmap;
 24 import android.graphics.BitmapFactory;
 25 import android.graphics.Canvas;
 26 import android.graphics.Matrix;
 27 import android.util.AttributeSet;
 28 import android.view.GestureDetector;
 29 import android.view.GestureDetector.SimpleOnGestureListener;
 30 import android.view.MotionEvent;
 31 import android.view.View;
 32 import android.view.ViewGroup;
 33 
 34 
 35 /**
 36  * 
 37  * @author Szugyi
 38  * Creates a rotatable circle menu which can be parameterized by custom attributes.
 39  * Handles touches and gestures to make the menu rotatable, and to make the 
 40  * menu items selectable and clickable.
 41  * 
 42  */
 43 public class CircleLayout extends ViewGroup {
 44     // Event listeners
 45     private OnItemClickListener mOnItemClickListener = null;
 46     private OnItemSelectedListener mOnItemSelectedListener = null;
 47     private OnCenterClickListener mOnCenterClickListener = null;
 48     
 49     // Background image
 50     private Bitmap imageOriginal, imageScaled;
 51     private Matrix matrix;
 52 
 53     private int mTappedViewsPostition = -1;
 54     private View mTappedView = null;
 55     private int selected = 0;
 56 
 57     // Child sizes
 58     private int mMaxChildWidth = 0;
 59     private int mMaxChildHeight = 0;
 60     private int childWidth = 0;
 61     private int childHeight = 0;
 62 
 63     // Sizes of the ViewGroup
 64     private int circleWidth, circleHeight;
 65     private int radius = 0;
 66 
 67     // Touch detection
 68     private GestureDetector mGestureDetector;
 69     // needed for detecting the inversed rotations
 70     private boolean[] quadrantTouched;
 71 
 72     // Settings of the ViewGroup
 73     private boolean allowRotating = true;
 74     private float angle = 90;
 75     private float firstChildPos = 90;
 76     private boolean rotateToCenter = true;
 77     private boolean isRotating = true;
 78 
 79     /**
 80      * @param context
 81      */
 82     public CircleLayout(Context context) {
 83         this(context, null);
 84     }
 85 
 86     /**
 87      * @param context
 88      * @param attrs
 89      */
 90     public CircleLayout(Context context, AttributeSet attrs) {
 91         this(context, attrs, 0);
 92     }
 93     
 94     /**
 95      * @param context
 96      * @param attrs
 97      * @param defStyle
 98      */
 99     public CircleLayout(Context context, AttributeSet attrs, int defStyle) {
100         super(context, attrs, defStyle);
101         init(attrs);
102     }
103 
104     /**
105      * Initializes the ViewGroup and modifies it's default behavior by the passed attributes
106      * @param attrs    the attributes used to modify default settings
107      */
108     protected void init(AttributeSet attrs) {
109         mGestureDetector = new GestureDetector(getContext(),
110                 new MyGestureListener());
111         quadrantTouched = new boolean[] { false, false, false, false, false };
112 
113         if (attrs != null) {
114             TypedArray a = getContext().obtainStyledAttributes(attrs,
115                     R.styleable.Circle);
116             
117             // The angle where the first menu item will be drawn
118             angle = a.getInt(R.styleable.Circle_firstChildPosition, 90);
119             firstChildPos = angle;
120 
121             rotateToCenter = a.getBoolean(R.styleable.Circle_rotateToCenter,
122                     true);            
123             isRotating = a.getBoolean(R.styleable.Circle_isRotating, true);
124             
125             // If the menu is not rotating then it does not have to be centered
126             // since it cannot be even moved
127             if (!isRotating) {
128                 rotateToCenter = false;
129             }
130 
131             if (imageOriginal == null) {
132                 int picId = a.getResourceId(
133                         R.styleable.Circle_circleBackground, -1);
134                 
135                 // If a background image was set as an attribute, 
136                 // retrieve the image
137                 if (picId != -1) {
138                     imageOriginal = BitmapFactory.decodeResource(
139                             getResources(), picId);
140                 }
141             }
142 
143             a.recycle();
144 
145             // initialize the matrix only once
146             if (matrix == null) {
147                 matrix = new Matrix();
148             } else {
149                 // not needed, you can also post the matrix immediately to
150                 // restore the old state
151                 matrix.reset();
152             }
153             // Needed for the ViewGroup to be drawn
154             setWillNotDraw(false);
155         }
156     }
157 
158     /**
159      * Returns the currently selected menu
160      * @return the view which is currently the closest to the start position
161      */
162     public View getSelectedItem() {
163         return (selected >= 0) ? getChildAt(selected) : null;
164     }
165 
166     @Override
167     protected void onDraw(Canvas canvas) {
168         // the sizes of the ViewGroup
169         circleHeight = getHeight();
170         circleWidth = getWidth();
171 
172         if (imageOriginal != null) {
173             // Scaling the size of the background image
174             if (imageScaled == null) {
175                 matrix = new Matrix();
176                 float sx = (((radius + childWidth / 4) * 2) / (float) imageOriginal
177                         .getWidth());
178                 float sy = (((radius + childWidth / 4) * 2) / (float) imageOriginal
179                         .getHeight());
180                 matrix.postScale(sx, sy);
181                 imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0,
182                         imageOriginal.getWidth(), imageOriginal.getHeight(),
183                         matrix, false);
184             }
185 
186             if (imageScaled != null) {
187                 // Move the background to the center
188                 int cx = (circleWidth - imageScaled.getWidth()) / 2;
189                 int cy = (circleHeight - imageScaled.getHeight()) / 2;
190 
191                 Canvas g = canvas;
192                 canvas.rotate(0, circleWidth / 2, circleHeight / 2);
193                 g.drawBitmap(imageScaled, cx, cy, null);
194 
195             }
196         }
197     }
198 
199     @Override
200     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
201         mMaxChildWidth = 0;
202         mMaxChildHeight = 0;
203 
204         // Measure once to find the maximum child size.
205         int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
206                 MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
207         int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
208                 MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
209 
210         final int count = getChildCount();
211         for (int i = 0; i < count; i++) {
212             final View child = getChildAt(i);
213             if (child.getVisibility() == GONE) {
214                 continue;
215             }
216 
217             child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
218 
219             mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth());
220             mMaxChildHeight = Math.max(mMaxChildHeight,
221                     child.getMeasuredHeight());
222         }
223 
224         // Measure again for each child to be exactly the same size.
225         childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildWidth,
226                 MeasureSpec.EXACTLY);
227         childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildHeight,
228                 MeasureSpec.EXACTLY);
229 
230         for (int i = 0; i < count; i++) {
231             final View child = getChildAt(i);
232             if (child.getVisibility() == GONE) {
233                 continue;
234             }
235 
236             child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
237         }
238 
239         setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec),
240                 resolveSize(mMaxChildHeight, heightMeasureSpec));
241     }
242 
243     @Override
244     protected void onLayout(boolean changed, int l, int t, int r, int b) {
245         int layoutWidth = r - l;
246         int layoutHeight = b - t;
247 
248         // Laying out the child views
249         final int childCount = getChildCount();
250         int left, top;
251         radius = (layoutWidth <= layoutHeight) ? layoutWidth / 3
252                 : layoutHeight / 3;
253         
254         childWidth = (int) (radius / 1.5);
255         childHeight = (int) (radius / 1.5);
256         
257         float angleDelay = 360 / getChildCount();
258         
259         for (int i = 0; i < childCount; i++) {
260             final CircleImageView child = (CircleImageView) getChildAt(i);
261             if (child.getVisibility() == GONE) {
262                 continue;
263             }
264 
265             if (angle > 360) {
266                 angle -= 360;
267             } else {
268                 if (angle < 0) {
269                     angle += 360;
270                 }
271             }
272 
273             child.setAngle(angle);
274             child.setPosition(i);
275 
276             left = Math
277                     .round((float) (((layoutWidth / 2) - childWidth / 2) + radius
278                             * Math.cos(Math.toRadians(angle))));
279             top = Math
280                     .round((float) (((layoutHeight / 2) - childHeight / 2) + radius
281                             * Math.sin(Math.toRadians(angle))));
282 
283             child.layout(left, top, left + childWidth, top + childHeight);
284             angle += angleDelay;
285         }
286     }
287 
288     /**
289      * Rotate the buttons.
290      * 
291      * @param degrees The degrees, the menu items should get rotated.
292      */
293     private void rotateButtons(float degrees) {
294         int left, top, childCount = getChildCount();
295         float angleDelay = 360 / childCount;
296         angle += degrees;
297         
298         if (angle > 360) {
299             angle -= 360;
300         } else {
301             if (angle < 0) {
302                 angle += 360;
303             }
304         }
305 
306         for (int i = 0; i < childCount; i++) {
307             if (angle > 360) {
308                 angle -= 360;
309             } else {
310                 if (angle < 0) {
311                     angle += 360;
312                 }
313             }
314 
315             final CircleImageView child = (CircleImageView) getChildAt(i);
316             if (child.getVisibility() == GONE) {
317                 continue;
318             }
319             left = Math
320                     .round((float) (((circleWidth / 2) - childWidth / 2) + radius
321                             * Math.cos(Math.toRadians(angle))));
322             top = Math
323                     .round((float) (((circleHeight / 2) - childHeight / 2) + radius
324                             * Math.sin(Math.toRadians(angle))));
325 
326             child.setAngle(angle);
327 
328             if (Math.abs(angle - firstChildPos) < (angleDelay / 2)
329                     && selected != child.getPosition()) {
330                 selected = child.getPosition();
331 
332                 if (mOnItemSelectedListener != null && rotateToCenter) {
333                     mOnItemSelectedListener.onItemSelected(child, selected,
334                             child.getId(), child.getName());
335                 }
336             }
337 
338             child.layout(left, top, left + childWidth, top + childHeight);
339             angle += angleDelay;
340         }
341     }
342 
343     /**
344      * @return The angle of the unit circle with the image view's center
345      */
346     private double getAngle(double xTouch, double yTouch) {
347         double x = xTouch - (circleWidth / 2d);
348         double y = circleHeight - yTouch - (circleHeight / 2d);
349 
350         switch (getQuadrant(x, y)) {
351         case 1:
352             return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
353 
354         case 2:
355         case 3:
356             return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
357 
358         case 4:
359             return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
360 
361         default:
362             // ignore, does not happen
363             return 0;
364         }
365     }
366 
367     /**
368      * @return The selected quadrant.
369      */
370     private static int getQuadrant(double x, double y) {
371         if (x >= 0) {
372             return y >= 0 ? 1 : 4;
373         } else {
374             return y >= 0 ? 2 : 3;
375         }
376     }
377 
378     private double startAngle;
379 
380     @Override
381     public boolean onTouchEvent(MotionEvent event) {
382         if (isEnabled()) {
383             if (isRotating) {
384                 switch (event.getAction()) {
385                 case MotionEvent.ACTION_DOWN:
386 
387                     // reset the touched quadrants
388                     for (int i = 0; i < quadrantTouched.length; i++) {
389                         quadrantTouched[i] = false;
390                     }
391 
392                     allowRotating = false;
393 
394                     startAngle = getAngle(event.getX(), event.getY());
395                     break;
396                 case MotionEvent.ACTION_MOVE:
397                     double currentAngle = getAngle(event.getX(), event.getY());
398                     rotateButtons((float) (startAngle - currentAngle));
399                     startAngle = currentAngle;
400                     break;
401                 case MotionEvent.ACTION_UP:
402                     allowRotating = true;
403                     rotateViewToCenter((CircleImageView) getChildAt(selected),
404                             false);
405                     break;
406                 }
407             }
408 
409             // set the touched quadrant to true
410             quadrantTouched[getQuadrant(event.getX() - (circleWidth / 2),
411                     circleHeight - event.getY() - (circleHeight / 2))] = true;
412             mGestureDetector.onTouchEvent(event);
413             return true;
414         }
415         return false;
416     }
417 
418     private class MyGestureListener extends SimpleOnGestureListener {
419         @Override
420         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
421                 float velocityY) {
422             if (!isRotating) {
423                 return false;
424             }
425             // get the quadrant of the start and the end of the fling
426             int q1 = getQuadrant(e1.getX() - (circleWidth / 2), circleHeight
427                     - e1.getY() - (circleHeight / 2));
428             int q2 = getQuadrant(e2.getX() - (circleWidth / 2), circleHeight
429                     - e2.getY() - (circleHeight / 2));
430 
431             // the inversed rotations
432             if ((q1 == 2 && q2 == 2 && Math.abs(velocityX) < Math
433                     .abs(velocityY))
434                     || (q1 == 3 && q2 == 3)
435                     || (q1 == 1 && q2 == 3)
436                     || (q1 == 4 && q2 == 4 && Math.abs(velocityX) > Math
437                             .abs(velocityY))
438                     || ((q1 == 2 && q2 == 3) || (q1 == 3 && q2 == 2))
439                     || ((q1 == 3 && q2 == 4) || (q1 == 4 && q2 == 3))
440                     || (q1 == 2 && q2 == 4 && quadrantTouched[3])
441                     || (q1 == 4 && q2 == 2 && quadrantTouched[3])) {
442 
443                 CircleLayout.this.post(new FlingRunnable(-1
444                         * (velocityX + velocityY)));
445             } else {
446                 // the normal rotation
447                 CircleLayout.this
448                         .post(new FlingRunnable(velocityX + velocityY));
449             }
450 
451             return true;
452 
453         }
454 
455         @Override
456         public boolean onSingleTapUp(MotionEvent e) {
457             mTappedViewsPostition = pointToPosition(e.getX(), e.getY());
458             if (mTappedViewsPostition >= 0) {
459                 mTappedView = getChildAt(mTappedViewsPostition);
460                 mTappedView.setPressed(true);
461             } else {
462                 float centerX = circleWidth / 2;
463                 float centerY = circleHeight / 2;
464 
465                 if (e.getX() < centerX + (childWidth / 2)
466                         && e.getX() > centerX - childWidth / 2
467                         && e.getY() < centerY + (childHeight / 2)
468                         && e.getY() > centerY - (childHeight / 2)) {
469                     if (mOnCenterClickListener != null) {
470                         mOnCenterClickListener.onCenterClick();
471                         return true;
472                     }
473                 }
474             }
475 
476             if (mTappedView != null) {
477                 CircleImageView view = (CircleImageView) (mTappedView);
478                 if (selected != mTappedViewsPostition) {
479                     rotateViewToCenter(view, false);
480                     if (!rotateToCenter) {
481                         if (mOnItemSelectedListener != null) {
482                             mOnItemSelectedListener.onItemSelected(mTappedView,
483                                     mTappedViewsPostition, mTappedView.getId(), view.getName());
484                         }
485 
486                         if (mOnItemClickListener != null) {
487                             mOnItemClickListener.onItemClick(mTappedView,
488                                     mTappedViewsPostition, mTappedView.getId(), view.getName());
489                         }
490                     }
491                 } else {
492                     rotateViewToCenter(view, false);
493 
494                     if (mOnItemClickListener != null) {
495                         mOnItemClickListener.onItemClick(mTappedView,
496                                 mTappedViewsPostition, mTappedView.getId(), view.getName());
497                     }
498                 }
499                 return true;
500             }
501             return super.onSingleTapUp(e);
502         }
503     }
504 
505     /**
506      * Rotates the given view to the center of the menu.
507      * @param view            the view to be rotated to the center
508      * @param fromRunnable    if the method is called from the runnable which animates the rotation
509      *                         then it should be true, otherwise false 
510      */
511     private void rotateViewToCenter(CircleImageView view, boolean fromRunnable) {
512         if (rotateToCenter) {
513             float velocityTemp = 1;
514             float destAngle = (float) (firstChildPos - view.getAngle());
515             float startAngle = 0;
516             int reverser = 1;
517 
518             if (destAngle < 0) {
519                 destAngle += 360;
520             }
521 
522             if (destAngle > 180) {
523                 reverser = -1;
524                 destAngle = 360 - destAngle;
525             }
526 
527             while (startAngle < destAngle) {
528                 startAngle += velocityTemp / 75;
529                 velocityTemp *= 1.0666F;
530             }
531 
532             CircleLayout.this.post(new FlingRunnable(reverser * velocityTemp,
533                     !fromRunnable));
534         }
535     }
536 
537     /**
538      * A {@link Runnable} for animating the menu rotation.
539      */
540     private class FlingRunnable implements Runnable {
541 
542         private float velocity;
543         float angleDelay;
544         boolean isFirstForwarding = true;
545 
546         public FlingRunnable(float velocity) {
547             this(velocity, true);
548         }
549 
550         public FlingRunnable(float velocity, boolean isFirst) {
551             this.velocity = velocity;
552             this.angleDelay = 360 / getChildCount();
553             this.isFirstForwarding = isFirst;
554         }
555 
556         public void run() {
557             if (Math.abs(velocity) > 5 && allowRotating) {
558                 if (rotateToCenter) {
559                     if (!(Math.abs(velocity) < 200 && (Math.abs(angle
560                             - firstChildPos)
561                             % angleDelay < 2))) {
562                         rotateButtons(velocity / 75);
563                         velocity /= 1.0666F;
564 
565                         CircleLayout.this.post(this);
566                     }
567                 } else {
568                     rotateButtons(velocity / 75);
569                     velocity /= 1.0666F;
570 
571                     CircleLayout.this.post(this);
572                 }
573             } else {
574                 if (isFirstForwarding) {
575                     isFirstForwarding = false;
576                     CircleLayout.this.rotateViewToCenter(
577                             (CircleImageView) getChildAt(selected), true);
578                 }
579             }
580         }
581     }
582 
583     private int pointToPosition(float x, float y) {
584 
585         for (int i = 0; i < getChildCount(); i++) {
586 
587             View item = (View) getChildAt(i);
588             if (item.getLeft() < x && item.getRight() > x & item.getTop() < y
589                     && item.getBottom() > y) {
590                 return i;
591             }
592 
593         }
594         return -1;
595     }
596 
597     public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
598         this.mOnItemClickListener = onItemClickListener;
599     }
600 
601     public interface OnItemClickListener {
602         void onItemClick(View view, int position, long id, String name);
603     }
604 
605     public void setOnItemSelectedListener(
606             OnItemSelectedListener onItemSelectedListener) {
607         this.mOnItemSelectedListener = onItemSelectedListener;
608     }
609 
610     public interface OnItemSelectedListener {
611         void onItemSelected(View view, int position, long id, String name);
612     }
613 
614     public interface OnCenterClickListener {
615         void onCenterClick();
616     }
617 
618     public void setOnCenterClickListener(
619             OnCenterClickListener onCenterClickListener) {
620         this.mOnCenterClickListener = onCenterClickListener;
621     }
622 }

xml文件:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:circle="http://schemas.android.com/apk/res/com.szugyi.circlemenu"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     tools:context=".MainActivity" >
 7 
 8     <com.lixu.circlemenu.view.CircleLayout
 9         android:id="@+id/main_circle_layout"
10         android:layout_width="fill_parent"
11         android:layout_height="fill_parent"
12         android:layout_above="@+id/main_selected_textView"
13         android:layout_gravity="center_horizontal"
14         circle:firstChildPosition="South" 
15         circle:rotateToCenter="true" 
16         circle:isRotating="true" >       
17 <!--         circle:circleBackground="@drawable/green"  > -->
18 
19 
20         <com.lixu.circlemenu.view.CircleImageView
21             android:id="@+id/main_facebook_image"
22             android:layout_width="35dp"
23             android:layout_height="35dp"
24             android:src="@drawable/icon_facebook"
25             circle:name="@string/facebook" />
26 
27         <com.lixu.circlemenu.view.CircleImageView
28             android:id="@+id/main_myspace_image"
29             android:layout_width="wrap_content"
30             android:layout_height="wrap_content"
31             android:src="@drawable/icon_myspace"
32             circle:name="@string/myspace" />
33 
34         <com.lixu.circlemenu.view.CircleImageView
35             android:id="@+id/main_google_image"
36             android:layout_width="wrap_content"
37             android:layout_height="wrap_content"
38             android:src="@drawable/icon_google"
39             circle:name="@string/google" />
40 
41         <com.lixu.circlemenu.view.CircleImageView
42             android:id="@+id/main_linkedin_image"
43             android:layout_width="wrap_content"
44             android:layout_height="wrap_content"
45             android:src="@drawable/icon_linkedin"
46             circle:name="@string/linkedin" />
47 
48         <com.lixu.circlemenu.view.CircleImageView
49             android:id="@+id/main_twitter_image"
50             android:layout_width="wrap_content"
51             android:layout_height="wrap_content"
52             android:src="@drawable/icon_twitter"
53             circle:name="@string/twitter" />
54 
55         <com.lixu.circlemenu.view.CircleImageView
56             android:id="@+id/main_wordpress_image"
57             android:layout_width="wrap_content"
58             android:layout_height="wrap_content"
59             android:src="@drawable/icon_wordpress"
60             circle:name="@string/wordpress" />
61     </com.lixu.circlemenu.view.CircleLayout>
62 
63     <TextView
64         android:id="@+id/main_selected_textView"
65         android:layout_width="wrap_content"
66         android:layout_height="wrap_content"
67         android:layout_alignParentBottom="true"
68         android:layout_centerHorizontal="true"
69         android:layout_marginBottom="50dp"
70         android:textAppearance="?android:attr/textAppearanceLarge" />
71 
72 </RelativeLayout>

 运行效果:

原文地址:https://www.cnblogs.com/labixiaoxin/p/5046614.html