編輯:關於android開發
1- 整個自定義控件其實就是一個ArcMenu .(半圓形那一圈),左下角的圖標沒有加入進控件中。
2- 我基於他的類改了點。
他是將左下角的關閉icon都加入到整個自定義menu的layout中的,我是獨立出來
我menu中的item添加的思路是首先都給它固定在界面的最左邊,往屏幕左邊外面便宜半個item的寬度。然後在draw時,將每一個item的位置根據自身的角度,設置rotate值,不但外面要rotate到item本身應該所在的位置(pivot要設置為左下角為原點),它自身也得根據偏移的角度rotate到一個正確的向上的角度。其實在初始化時都給它們偏移過了。
3- 當然現在6.0、7.0上的那些自帶效果比我這漂亮多了,不過為了完成設計師給的設計稿,不得不這樣寫。所以輕噴。
4- 下面po上實現步驟。
a,自定義一個類ArcMenu繼承自FrameLayout.重載三個構造方法。
public class ArcMenu extends FrameLayout {
public ArcMenu(Context context) {super(context);}
public ArcMenu(Context context, AttributeSet attrs) {super(context, attrs);}
b,重寫 onSizeChanged方法,確定控件的高寬,並初始化控件中的一些參數
private void init() { if (!isInEditMode()) { for (int i = 0; i < ICON_COUNT; i++) {
//初始化默認和點擊的圖片bitmap m_iconGrayBitmaps[i] = DrawableManager.instance().getAssetBitmap(s_iconNamePrefixes[i] + "_gray.png"); m_iconWhiteBitmaps[i] = DrawableManager.instance().getAssetBitmap(s_iconNamePrefixes[i] + "_white.png"); // m_tangent[i] = Math.tan(90.0f / ICON_COUNT * i); } } m_arcWidth = m_height / 4;//弧形的寬度 // m_itemIndex = 0; m_startDegree = 90.0f / ICON_COUNT / 2; //第一個item初始化時應該待的位置的偏移角度 m_stepDegree = 90.0f / ICON_COUNT; //每一個item相對前一個item所偏移的角度
//新建一個矩形,中心點為左下角
m_arcRect = new RectF(-(m_width - m_arcWidth / 2), m_arcWidth / 2, m_width - m_arcWidth / 2, 2 * m_height - m_arcWidth / 2); int shadow_arc_width = Utils.dp2px(SHADOW_ARC_WIDTH); m_arcShadow = new RectF(-(m_width - m_arcWidth - shadow_arc_width / 2), m_arcWidth + shadow_arc_width / 2, (m_width - m_arcWidth - shadow_arc_width / 2), 2 * m_height - m_arcWidth - shadow_arc_width / 2); m_arcbgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); m_arcbgPaint.setStyle(Paint.Style.STROKE); m_arcbgPaint.setStrokeWidth(m_arcWidth); m_arcbgPaint.setColor(getResources().getColor(R.color.bg_menu_arc)); m_arcfgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); m_arcfgPaint.setStyle(Paint.Style.STROKE); m_arcfgPaint.setStrokeWidth(m_arcWidth); m_arcfgPaint.setColor(getResources().getColor(R.color.fg_menu_arc)); m_shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); m_shadowPaint.setStyle(Paint.Style.STROKE); m_shadowPaint.setStrokeWidth(shadow_arc_width); m_shadowPaint.setColor(getResources().getColor(R.color.default_black)); setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { int index = pointInArc(event.getX(), event.getY()); if (index >= 0) { Logger.debug("click on icon " + index); m_itemIndex = index; invalidate(); m_itemClickedListener.onMenuItemClicked(index); return true; } } return false; } }); }
上面圖畫錯了。。綠色框其實就是外面的m_arcRect
shadowArc其實是 那一層黑色的arc..我懶得再畫了。。
接下來就是畫圖了。把那些item要畫上去,還得畫上這兩層弧形
用到dipatchDraw
@Override protected void dispatchDraw(Canvas canvas) { Path path = new Path(); /// draw out arc path.arcTo(m_arcRect, 270.0f, 90.0f); canvas.drawPath(path, m_arcbgPaint); canvas.drawArc(m_arcRect, 270.0f + m_stepDegree * m_itemIndex, m_stepDegree, false, m_arcfgPaint); /// draw shadow arc canvas.drawArc(m_arcShadow, 270.0f, 90.0f, false, m_shadowPaint); /// draw bitmaps for (int i = 0; i < ICON_COUNT; i++) { Bitmap bitmap; if (i == m_itemIndex) { /// selected icon bitmap = m_iconWhiteBitmaps[i]; } else { /// not selected bitmap = m_iconGrayBitmaps[i]; } if (bitmap != null) { Matrix matrix = new Matrix(); matrix.postTranslate(-bitmap.getWidth() / 2, (m_arcWidth - bitmap.getHeight()) / 2); matrix.postRotate(-m_startDegree - m_stepDegree * i, 0, m_arcWidth / 2); matrix.postRotate(m_startDegree + m_stepDegree * i, 0, m_height); canvas.drawBitmap(bitmap, matrix, null); } } super.dispatchDraw(canvas); }
寫到這裡不知道怎麼說了。。干脆貼代碼算了。
/** * check if point (x, y) is within arc icon * * @param x * @param y * @return index of the icon clicked, or -1 */ private int pointInArc(float x, float y) { float[] pts = {x, y}; float[] target_pts = new float[2]; Matrix matrix = new Matrix(); matrix.postRotate(-m_startDegree, 0, m_height); for (int i = 0; i < ICON_COUNT; i++) { matrix.mapPoints(target_pts, pts); if (pointInStartRectOfIcon(target_pts)) { return i; } matrix.postRotate(-m_stepDegree, 0, m_height); } return -1; } /** * check if (target_pts[0], target_pts[1]) is in the start position of icons * * @param target_pts * @return */ private boolean pointInStartRectOfIcon(float[] target_pts) { return target_pts[0] > -m_arcWidth / 2 && target_pts[0] < m_arcWidth / 2 && target_pts[1] > 0 && target_pts[1] < m_arcWidth; }
/** * Sets the click listener for menu items. */ public void setOnItemClickedListener(ArcMenuItemClickedListener itemClickedListener) { this.m_itemClickedListener = itemClickedListener; } public void setSelectedIcon(int index, boolean bInvalidate) { m_itemIndex = index; if(bInvalidate) { invalidate(); } }就醬吧。。。寫個博客煩球死。
APK瘦身記,如何實現高達53%的壓縮效果,apk53%作者:非戈@阿裡移動安全 1、我是怎麼思考這件事情的 APK是Android系統安裝包的文件格式,關於這個話題其實
Android EditText只有下面有一條橫線問題 android 4.0以後EditText的風格默認變成了只有下面有一條橫線。如圖: &nbs
[FastDev4Android框架開發]神器ViewGragHelper完全解析,媽媽再也不擔心我自定義ViewGroup滑動View操作啦~(三十三) &nbs
Fresco,frescoandroid1、簡介 Fresco是Facebook最新推出的一款用於Android應用中展示圖片的強大圖片庫,可以從網絡、本地存儲和本地資源