├── README.md
├── sample_zhy_CircleMenu
├── ccb.gif
├── screen_shot.gif
├── ic_launcher-web.png
├── res
│ ├── drawable-hdpi
│ │ ├── bg.png
│ │ ├── circle_bg.png
│ │ ├── circle_bg2.png
│ │ ├── circle_bg3.png
│ │ ├── ccb_comm_bg0.png
│ │ ├── ic_launcher.png
│ │ ├── turnplate_bg_left.png
│ │ ├── home_mbank_1_clicked.png
│ │ ├── home_mbank_1_normal.png
│ │ ├── home_mbank_2_clicked.png
│ │ ├── home_mbank_2_normal.png
│ │ ├── home_mbank_3_clicked.png
│ │ ├── home_mbank_3_normal.png
│ │ ├── home_mbank_4_clicked.png
│ │ ├── home_mbank_4_normal.png
│ │ ├── home_mbank_5_clicked.png
│ │ ├── home_mbank_5_normal.png
│ │ ├── home_mbank_6_clicked.png
│ │ ├── home_mbank_6_normal.png
│ │ ├── turnplate_bg_right.png
│ │ ├── turnplate_inner_icon.png
│ │ ├── turnplate_center_unlogin.png
│ │ └── turnplate_mask_unlogin_normal.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── drawable-320dpi
│ │ ├── turnplate_bg_left.png
│ │ └── turnplate_bg_right.png
│ ├── values-sw600dp
│ │ └── dimens.xml
│ ├── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── menu
│ │ └── main.xml
│ ├── values-sw720dp-land
│ │ └── dimens.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── layout
│ │ ├── activity_main02.xml
│ │ └── activity_main.xml
├── libs
│ └── android-support-v4.jar
├── project.properties
├── proguard-project.txt
├── AndroidManifest.xml
└── src
│ └── com
│ └── zhy
│ └── sample_circlemenu
│ ├── CCBActivity.java
│ ├── CircleActivity.java
│ └── MainActivity.java
├── library_zhy_CircleMenu
├── ic_launcher-web.png
├── libs
│ └── android-support-v4.jar
├── res
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── values-sw600dp
│ │ └── dimens.xml
│ ├── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ ├── ids.xml
│ │ └── styles.xml
│ ├── menu
│ │ └── main.xml
│ ├── values-sw720dp-land
│ │ └── dimens.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── layout
│ │ └── circle_menu_item.xml
├── AndroidManifest.xml
├── project.properties
├── proguard-project.txt
└── src
│ └── com
│ └── zhy
│ └── view
│ └── CircleMenuLayout.java
├── .gitignore
└── LICENSE
/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/README.md
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/ccb.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/ccb.gif
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/screen_shot.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/screen_shot.gif
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/ic_launcher-web.png
--------------------------------------------------------------------------------
/library_zhy_CircleMenu/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/library_zhy_CircleMenu/ic_launcher-web.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/bg.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/library_zhy_CircleMenu/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/library_zhy_CircleMenu/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/circle_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/circle_bg.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/circle_bg2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/circle_bg2.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/circle_bg3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/circle_bg3.png
--------------------------------------------------------------------------------
/library_zhy_CircleMenu/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/library_zhy_CircleMenu/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/ccb_comm_bg0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/ccb_comm_bg0.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library_zhy_CircleMenu/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/library_zhy_CircleMenu/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library_zhy_CircleMenu/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/library_zhy_CircleMenu/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_bg_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_bg_left.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-320dpi/turnplate_bg_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-320dpi/turnplate_bg_left.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-320dpi/turnplate_bg_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-320dpi/turnplate_bg_right.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_1_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_1_clicked.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_1_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_1_normal.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_2_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_2_clicked.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_2_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_2_normal.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_3_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_3_clicked.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_3_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_3_normal.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_4_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_4_clicked.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_4_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_4_normal.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_5_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_5_clicked.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_5_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_5_normal.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_6_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_6_clicked.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_6_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/home_mbank_6_normal.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_bg_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_bg_right.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_inner_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_inner_icon.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_center_unlogin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_center_unlogin.png
--------------------------------------------------------------------------------
/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_mask_unlogin_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hongyangAndroid/Android-CircleMenu/HEAD/sample_zhy_CircleMenu/res/drawable-hdpi/turnplate_mask_unlogin_normal.png
--------------------------------------------------------------------------------
/library_zhy_CircleMenu/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
12 | * @author zhy 13 | * http://blog.csdn.net/lmj623565791/article/details/43131133 14 | *15 | */ 16 | public class CCBActivity extends Activity 17 | { 18 | 19 | private CircleMenuLayout mCircleMenuLayout; 20 | 21 | private String[] mItemTexts = new String[] { "安全中心 ", "特色服务", "投资理财", 22 | "转账汇款", "我的账户", "信用卡" }; 23 | private int[] mItemImgs = new int[] { R.drawable.home_mbank_1_normal, 24 | R.drawable.home_mbank_2_normal, R.drawable.home_mbank_3_normal, 25 | R.drawable.home_mbank_4_normal, R.drawable.home_mbank_5_normal, 26 | R.drawable.home_mbank_6_normal }; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) 30 | { 31 | super.onCreate(savedInstanceState); 32 | 33 | //自已切换布局文件看效果 34 | // setContentView(R.layout.activity_main02); 35 | setContentView(R.layout.activity_main); 36 | 37 | mCircleMenuLayout = (CircleMenuLayout) findViewById(R.id.id_menulayout); 38 | mCircleMenuLayout.setMenuItemIconsAndTexts(mItemImgs, mItemTexts); 39 | 40 | 41 | 42 | mCircleMenuLayout.setOnMenuItemClickListener(new OnMenuItemClickListener() 43 | { 44 | 45 | @Override 46 | public void itemClick(View view, int pos) 47 | { 48 | Toast.makeText(CCBActivity.this, mItemTexts[pos], 49 | Toast.LENGTH_SHORT).show(); 50 | 51 | } 52 | 53 | @Override 54 | public void itemCenterClick(View view) 55 | { 56 | Toast.makeText(CCBActivity.this, 57 | "you can do something just like ccb ", 58 | Toast.LENGTH_SHORT).show(); 59 | 60 | } 61 | }); 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /sample_zhy_CircleMenu/src/com/zhy/sample_circlemenu/CircleActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhy.sample_circlemenu; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | 8 | import com.zhy.view.CircleMenuLayout; 9 | import com.zhy.view.CircleMenuLayout.OnMenuItemClickListener; 10 | /** 11 | *
12 | * @author zhy 13 | * http://blog.csdn.net/lmj623565791/article/details/43131133 14 | *15 | */ 16 | public class CircleActivity extends Activity 17 | { 18 | 19 | private CircleMenuLayout mCircleMenuLayout; 20 | 21 | private String[] mItemTexts = new String[] { "安全中心 ", "特色服务", "投资理财", 22 | "转账汇款", "我的账户", "信用卡" }; 23 | private int[] mItemImgs = new int[] { R.drawable.home_mbank_1_normal, 24 | R.drawable.home_mbank_2_normal, R.drawable.home_mbank_3_normal, 25 | R.drawable.home_mbank_4_normal, R.drawable.home_mbank_5_normal, 26 | R.drawable.home_mbank_6_normal }; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) 30 | { 31 | super.onCreate(savedInstanceState); 32 | 33 | //自已切换布局文件看效果 34 | setContentView(R.layout.activity_main02); 35 | // setContentView(R.layout.activity_main); 36 | 37 | mCircleMenuLayout = (CircleMenuLayout) findViewById(R.id.id_menulayout); 38 | mCircleMenuLayout.setMenuItemIconsAndTexts(mItemImgs, mItemTexts); 39 | 40 | 41 | 42 | mCircleMenuLayout.setOnMenuItemClickListener(new OnMenuItemClickListener() 43 | { 44 | 45 | @Override 46 | public void itemClick(View view, int pos) 47 | { 48 | Toast.makeText(CircleActivity.this, mItemTexts[pos], 49 | Toast.LENGTH_SHORT).show(); 50 | 51 | } 52 | 53 | @Override 54 | public void itemCenterClick(View view) 55 | { 56 | Toast.makeText(CircleActivity.this, 57 | "you can do something just like ccb ", 58 | Toast.LENGTH_SHORT).show(); 59 | 60 | } 61 | }); 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /sample_zhy_CircleMenu/src/com/zhy/sample_circlemenu/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhy.sample_circlemenu; 2 | 3 | import android.app.ListActivity; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.widget.ArrayAdapter; 11 | import android.widget.ListView; 12 | 13 | /** 14 | *
15 | * @author zhy 16 | * http://blog.csdn.net/lmj623565791/article/details/43131133 17 | *18 | */ 19 | public class MainActivity extends ListActivity 20 | { 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) 23 | { 24 | super.onCreate(savedInstanceState); 25 | 26 | getListView().setAdapter( 27 | new ArrayAdapter
19 | * @author zhy 20 | * http://blog.csdn.net/lmj623565791/article/details/43131133 21 | *22 | */ 23 | public class CircleMenuLayout extends ViewGroup 24 | { 25 | private int mRadius; 26 | /** 27 | * 该容器内child item的默认尺寸 28 | */ 29 | private static final float RADIO_DEFAULT_CHILD_DIMENSION = 1 / 4f; 30 | /** 31 | * 菜单的中心child的默认尺寸 32 | */ 33 | private float RADIO_DEFAULT_CENTERITEM_DIMENSION = 1 / 3f; 34 | /** 35 | * 该容器的内边距,无视padding属性,如需边距请用该变量 36 | */ 37 | private static final float RADIO_PADDING_LAYOUT = 1 / 12f; 38 | 39 | /** 40 | * 当每秒移动角度达到该值时,认为是快速移动 41 | */ 42 | private static final int FLINGABLE_VALUE = 300; 43 | 44 | /** 45 | * 如果移动角度达到该值,则屏蔽点击 46 | */ 47 | private static final int NOCLICK_VALUE = 3; 48 | 49 | /** 50 | * 当每秒移动角度达到该值时,认为是快速移动 51 | */ 52 | private int mFlingableValue = FLINGABLE_VALUE; 53 | /** 54 | * 该容器的内边距,无视padding属性,如需边距请用该变量 55 | */ 56 | private float mPadding; 57 | /** 58 | * 布局时的开始角度 59 | */ 60 | private double mStartAngle = 0; 61 | /** 62 | * 菜单项的文本 63 | */ 64 | private String[] mItemTexts; 65 | /** 66 | * 菜单项的图标 67 | */ 68 | private int[] mItemImgs; 69 | 70 | /** 71 | * 菜单的个数 72 | */ 73 | private int mMenuItemCount; 74 | 75 | /** 76 | * 检测按下到抬起时旋转的角度 77 | */ 78 | private float mTmpAngle; 79 | /** 80 | * 检测按下到抬起时使用的时间 81 | */ 82 | private long mDownTime; 83 | 84 | /** 85 | * 判断是否正在自动滚动 86 | */ 87 | private boolean isFling; 88 | 89 | private int mMenuItemLayoutId = R.layout.circle_menu_item; 90 | 91 | public CircleMenuLayout(Context context, AttributeSet attrs) 92 | { 93 | super(context, attrs); 94 | // 无视padding 95 | setPadding(0, 0, 0, 0); 96 | } 97 | 98 | /** 99 | * 设置布局的宽高,并策略menu item宽高 100 | */ 101 | @Override 102 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 103 | { 104 | int resWidth = 0; 105 | int resHeight = 0; 106 | 107 | /** 108 | * 根据传入的参数,分别获取测量模式和测量值 109 | */ 110 | int width = MeasureSpec.getSize(widthMeasureSpec); 111 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 112 | 113 | int height = MeasureSpec.getSize(heightMeasureSpec); 114 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 115 | 116 | /** 117 | * 如果宽或者高的测量模式非精确值 118 | */ 119 | if (widthMode != MeasureSpec.EXACTLY 120 | || heightMode != MeasureSpec.EXACTLY) 121 | { 122 | // 主要设置为背景图的高度 123 | resWidth = getSuggestedMinimumWidth(); 124 | // 如果未设置背景图片,则设置为屏幕宽高的默认值 125 | resWidth = resWidth == 0 ? getDefaultWidth() : resWidth; 126 | 127 | resHeight = getSuggestedMinimumHeight(); 128 | // 如果未设置背景图片,则设置为屏幕宽高的默认值 129 | resHeight = resHeight == 0 ? getDefaultWidth() : resHeight; 130 | } else 131 | { 132 | // 如果都设置为精确值,则直接取小值; 133 | resWidth = resHeight = Math.min(width, height); 134 | } 135 | 136 | setMeasuredDimension(resWidth, resHeight); 137 | 138 | // 获得半径 139 | mRadius = Math.max(getMeasuredWidth(), getMeasuredHeight()); 140 | 141 | // menu item数量 142 | final int count = getChildCount(); 143 | // menu item尺寸 144 | int childSize = (int) (mRadius * RADIO_DEFAULT_CHILD_DIMENSION); 145 | // menu item测量模式 146 | int childMode = MeasureSpec.EXACTLY; 147 | 148 | // 迭代测量 149 | for (int i = 0; i < count; i++) 150 | { 151 | final View child = getChildAt(i); 152 | 153 | if (child.getVisibility() == GONE) 154 | { 155 | continue; 156 | } 157 | 158 | // 计算menu item的尺寸;以及和设置好的模式,去对item进行测量 159 | int makeMeasureSpec = -1; 160 | 161 | if (child.getId() == R.id.id_circle_menu_item_center) 162 | { 163 | makeMeasureSpec = MeasureSpec.makeMeasureSpec( 164 | (int) (mRadius * RADIO_DEFAULT_CENTERITEM_DIMENSION), 165 | childMode); 166 | } else 167 | { 168 | makeMeasureSpec = MeasureSpec.makeMeasureSpec(childSize, 169 | childMode); 170 | } 171 | child.measure(makeMeasureSpec, makeMeasureSpec); 172 | } 173 | 174 | mPadding = RADIO_PADDING_LAYOUT * mRadius; 175 | 176 | } 177 | 178 | /** 179 | * MenuItem的点击事件接口 180 | * 181 | * @author zhy 182 | * 183 | */ 184 | public interface OnMenuItemClickListener 185 | { 186 | void itemClick(View view, int pos); 187 | 188 | void itemCenterClick(View view); 189 | } 190 | 191 | /** 192 | * MenuItem的点击事件接口 193 | */ 194 | private OnMenuItemClickListener mOnMenuItemClickListener; 195 | 196 | /** 197 | * 设置MenuItem的点击事件接口 198 | * 199 | * @param mOnMenuItemClickListener 200 | */ 201 | public void setOnMenuItemClickListener( 202 | OnMenuItemClickListener mOnMenuItemClickListener) 203 | { 204 | this.mOnMenuItemClickListener = mOnMenuItemClickListener; 205 | } 206 | 207 | /** 208 | * 设置menu item的位置 209 | */ 210 | @Override 211 | protected void onLayout(boolean changed, int l, int t, int r, int b) 212 | { 213 | int layoutRadius = mRadius; 214 | 215 | // Laying out the child views 216 | final int childCount = getChildCount(); 217 | 218 | int left, top; 219 | // menu item 的尺寸 220 | int cWidth = (int) (layoutRadius * RADIO_DEFAULT_CHILD_DIMENSION); 221 | 222 | // 根据menu item的个数,计算角度 223 | float angleDelay = 360 / (getChildCount() - 1); 224 | 225 | // 遍历去设置menuitem的位置 226 | for (int i = 0; i < childCount; i++) 227 | { 228 | final View child = getChildAt(i); 229 | 230 | if (child.getId() == R.id.id_circle_menu_item_center) 231 | continue; 232 | 233 | if (child.getVisibility() == GONE) 234 | { 235 | continue; 236 | } 237 | 238 | mStartAngle %= 360; 239 | 240 | // 计算,中心点到menu item中心的距离 241 | float tmp = layoutRadius / 2f - cWidth / 2 - mPadding; 242 | 243 | // tmp cosa 即menu item中心点的横坐标 244 | left = layoutRadius 245 | / 2 246 | + (int) Math.round(tmp 247 | * Math.cos(Math.toRadians(mStartAngle)) - 1 / 2f 248 | * cWidth); 249 | // tmp sina 即menu item的纵坐标 250 | top = layoutRadius 251 | / 2 252 | + (int) Math.round(tmp 253 | * Math.sin(Math.toRadians(mStartAngle)) - 1 / 2f 254 | * cWidth); 255 | 256 | child.layout(left, top, left + cWidth, top + cWidth); 257 | // 叠加尺寸 258 | mStartAngle += angleDelay; 259 | } 260 | 261 | // 找到中心的view,如果存在设置onclick事件 262 | View cView = findViewById(R.id.id_circle_menu_item_center); 263 | if (cView != null) 264 | { 265 | cView.setOnClickListener(new OnClickListener() 266 | { 267 | @Override 268 | public void onClick(View v) 269 | { 270 | 271 | if (mOnMenuItemClickListener != null) 272 | { 273 | mOnMenuItemClickListener.itemCenterClick(v); 274 | } 275 | } 276 | }); 277 | // 设置center item位置 278 | int cl = layoutRadius / 2 - cView.getMeasuredWidth() / 2; 279 | int cr = cl + cView.getMeasuredWidth(); 280 | cView.layout(cl, cl, cr, cr); 281 | } 282 | 283 | } 284 | 285 | /** 286 | * 记录上一次的x,y坐标 287 | */ 288 | private float mLastX; 289 | private float mLastY; 290 | 291 | /** 292 | * 自动滚动的Runnable 293 | */ 294 | private AutoFlingRunnable mFlingRunnable; 295 | 296 | @Override 297 | public boolean dispatchTouchEvent(MotionEvent event) 298 | { 299 | float x = event.getX(); 300 | float y = event.getY(); 301 | 302 | // Log.e("TAG", "x = " + x + " , y = " + y); 303 | 304 | switch (event.getAction()) 305 | { 306 | case MotionEvent.ACTION_DOWN: 307 | 308 | mLastX = x; 309 | mLastY = y; 310 | mDownTime = System.currentTimeMillis(); 311 | mTmpAngle = 0; 312 | 313 | // 如果当前已经在快速滚动 314 | if (isFling) 315 | { 316 | // 移除快速滚动的回调 317 | removeCallbacks(mFlingRunnable); 318 | isFling = false; 319 | return true; 320 | } 321 | 322 | break; 323 | case MotionEvent.ACTION_MOVE: 324 | 325 | /** 326 | * 获得开始的角度 327 | */ 328 | float start = getAngle(mLastX, mLastY); 329 | /** 330 | * 获得当前的角度 331 | */ 332 | float end = getAngle(x, y); 333 | 334 | // Log.e("TAG", "start = " + start + " , end =" + end); 335 | // 如果是一、四象限,则直接end-start,角度值都是正值 336 | if (getQuadrant(x, y) == 1 || getQuadrant(x, y) == 4) 337 | { 338 | mStartAngle += end - start; 339 | mTmpAngle += end - start; 340 | } else 341 | // 二、三象限,色角度值是付值 342 | { 343 | mStartAngle += start - end; 344 | mTmpAngle += start - end; 345 | } 346 | // 重新布局 347 | requestLayout(); 348 | 349 | mLastX = x; 350 | mLastY = y; 351 | 352 | break; 353 | case MotionEvent.ACTION_UP: 354 | 355 | // 计算,每秒移动的角度 356 | float anglePerSecond = mTmpAngle * 1000 357 | / (System.currentTimeMillis() - mDownTime); 358 | 359 | // Log.e("TAG", anglePrMillionSecond + " , mTmpAngel = " + 360 | // mTmpAngle); 361 | 362 | // 如果达到该值认为是快速移动 363 | if (Math.abs(anglePerSecond) > mFlingableValue && !isFling) 364 | { 365 | // post一个任务,去自动滚动 366 | post(mFlingRunnable = new AutoFlingRunnable(anglePerSecond)); 367 | 368 | return true; 369 | } 370 | 371 | // 如果当前旋转角度超过NOCLICK_VALUE屏蔽点击 372 | if (Math.abs(mTmpAngle) > NOCLICK_VALUE) 373 | { 374 | return true; 375 | } 376 | 377 | break; 378 | } 379 | return super.dispatchTouchEvent(event); 380 | } 381 | 382 | /** 383 | * 主要为了action_down时,返回true 384 | */ 385 | @Override 386 | public boolean onTouchEvent(MotionEvent event) 387 | { 388 | return true; 389 | } 390 | 391 | /** 392 | * 根据触摸的位置,计算角度 393 | * 394 | * @param xTouch 395 | * @param yTouch 396 | * @return 397 | */ 398 | private float getAngle(float xTouch, float yTouch) 399 | { 400 | double x = xTouch - (mRadius / 2d); 401 | double y = yTouch - (mRadius / 2d); 402 | return (float) (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI); 403 | } 404 | 405 | /** 406 | * 根据当前位置计算象限 407 | * 408 | * @param x 409 | * @param y 410 | * @return 411 | */ 412 | private int getQuadrant(float x, float y) 413 | { 414 | int tmpX = (int) (x - mRadius / 2); 415 | int tmpY = (int) (y - mRadius / 2); 416 | if (tmpX >= 0) 417 | { 418 | return tmpY >= 0 ? 4 : 1; 419 | } else 420 | { 421 | return tmpY >= 0 ? 3 : 2; 422 | } 423 | 424 | } 425 | 426 | /** 427 | * 设置菜单条目的图标和文本 428 | * 429 | * @param resIds 430 | */ 431 | public void setMenuItemIconsAndTexts(int[] resIds, String[] texts) 432 | { 433 | mItemImgs = resIds; 434 | mItemTexts = texts; 435 | 436 | // 参数检查 437 | if (resIds == null && texts == null) 438 | { 439 | throw new IllegalArgumentException("菜单项文本和图片至少设置其一"); 440 | } 441 | 442 | // 初始化mMenuCount 443 | mMenuItemCount = resIds == null ? texts.length : resIds.length; 444 | 445 | if (resIds != null && texts != null) 446 | { 447 | mMenuItemCount = Math.min(resIds.length, texts.length); 448 | } 449 | 450 | addMenuItems(); 451 | 452 | } 453 | 454 | /** 455 | * 设置MenuItem的布局文件,必须在setMenuItemIconsAndTexts之前调用 456 | * 457 | * @param mMenuItemLayoutId 458 | */ 459 | public void setMenuItemLayoutId(int mMenuItemLayoutId) 460 | { 461 | this.mMenuItemLayoutId = mMenuItemLayoutId; 462 | } 463 | 464 | /** 465 | * 添加菜单项 466 | */ 467 | private void addMenuItems() 468 | { 469 | LayoutInflater mInflater = LayoutInflater.from(getContext()); 470 | 471 | /** 472 | * 根据用户设置的参数,初始化view 473 | */ 474 | for (int i = 0; i < mMenuItemCount; i++) 475 | { 476 | final int j = i; 477 | View view = mInflater.inflate(mMenuItemLayoutId, this, false); 478 | ImageView iv = (ImageView) view 479 | .findViewById(R.id.id_circle_menu_item_image); 480 | TextView tv = (TextView) view 481 | .findViewById(R.id.id_circle_menu_item_text); 482 | 483 | if (iv != null) 484 | { 485 | iv.setVisibility(View.VISIBLE); 486 | iv.setImageResource(mItemImgs[i]); 487 | iv.setOnClickListener(new OnClickListener() 488 | { 489 | @Override 490 | public void onClick(View v) 491 | { 492 | 493 | if (mOnMenuItemClickListener != null) 494 | { 495 | mOnMenuItemClickListener.itemClick(v, j); 496 | } 497 | } 498 | }); 499 | } 500 | if (tv != null) 501 | { 502 | tv.setVisibility(View.VISIBLE); 503 | tv.setText(mItemTexts[i]); 504 | } 505 | 506 | // 添加view到容器中 507 | addView(view); 508 | } 509 | } 510 | 511 | /** 512 | * 如果每秒旋转角度到达该值,则认为是自动滚动 513 | * 514 | * @param mFlingableValue 515 | */ 516 | public void setFlingableValue(int mFlingableValue) 517 | { 518 | this.mFlingableValue = mFlingableValue; 519 | } 520 | 521 | /** 522 | * 设置内边距的比例 523 | * 524 | * @param mPadding 525 | */ 526 | public void setPadding(float mPadding) 527 | { 528 | this.mPadding = mPadding; 529 | } 530 | 531 | /** 532 | * 获得默认该layout的尺寸 533 | * 534 | * @return 535 | */ 536 | private int getDefaultWidth() 537 | { 538 | WindowManager wm = (WindowManager) getContext().getSystemService( 539 | Context.WINDOW_SERVICE); 540 | DisplayMetrics outMetrics = new DisplayMetrics(); 541 | wm.getDefaultDisplay().getMetrics(outMetrics); 542 | return Math.min(outMetrics.widthPixels, outMetrics.heightPixels); 543 | } 544 | 545 | /** 546 | * 自动滚动的任务 547 | * 548 | * @author zhy 549 | * 550 | */ 551 | private class AutoFlingRunnable implements Runnable 552 | { 553 | 554 | private float angelPerSecond; 555 | 556 | public AutoFlingRunnable(float velocity) 557 | { 558 | this.angelPerSecond = velocity; 559 | } 560 | 561 | public void run() 562 | { 563 | // 如果小于20,则停止 564 | if ((int) Math.abs(angelPerSecond) < 20) 565 | { 566 | isFling = false; 567 | return; 568 | } 569 | isFling = true; 570 | // 不断改变mStartAngle,让其滚动,/30为了避免滚动太快 571 | mStartAngle += (angelPerSecond / 30); 572 | // 逐渐减小这个值 573 | angelPerSecond /= 1.0666F; 574 | postDelayed(this, 30); 575 | // 重新布局 576 | requestLayout(); 577 | } 578 | } 579 | 580 | } 581 | --------------------------------------------------------------------------------