自訂橢圓控制介面,自訂橢圓介面
其它的先不說,我們先看看,如下:
這東西,其實不難,就是要計算各個點的位置是比較蛋疼的,還有一個地方就是畫扇形的時候,不知道為什麼得不到我想要的效果,具體描述,可以看My Code:
package com.example.a;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Paint.Style;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;/** * 一個橢圓分區的按鈕集介面,沒有寫成控制項的形式,畢竟自訂這東西,還是得按照項目需求來 * * @author zhoudailiang * @since 2015-3-24 17:49 */public class ShapeView extends View implements OnTouchListener{private int radius = 40; // 中間小圓的半徑private Paint mPaint;private RectF oval;private int width, height;private boolean top, right, bottom, left, center;private ShapeViewListener onShapListener;//回調,進行各個部分的事件監聽public interface ShapeViewListener {public void onTopListener();public void onRightListener();public void onBottomListener();public void onLeftListener();public void onCenterListener();}public void setOnShapeListener(ShapeViewListener onShapListener) {this.onShapListener = onShapListener;}public ShapeView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public ShapeView(Context context, AttributeSet attrs) {super(context, attrs);init();}public ShapeView(Context context) {super(context);init();}private void init() {mPaint = new Paint();//設定背景為天藍色setBackgroundColor(0xFF436EEE);setOnTouchListener(this);}@SuppressLint("DrawAllocation")@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//得到布局的寬度width = this.getMeasuredWidth();height = 2 * width / 3;//畫橢圓的矩形地區oval = new RectF(5, 5, width - 5, height - 5);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPaint.setStrokeWidth(2);mPaint.setAntiAlias(true);mPaint.setStyle(Style.STROKE);mPaint.setColor(0xffffffff);canvas.drawArc(oval, 0, 360, false, mPaint);canvas.drawCircle(width / 2, height / 2, radius, mPaint);if (center) {mPaint.setStyle(Style.FILL);mPaint.setColor(0xaaffffff);canvas.drawCircle(width / 2, height / 2, radius, mPaint);}//下面這裡的扇形範圍-56, 112是我調試出來的,MD,不知道為什麼-45, 90這樣的寫法就是有問題,//各位看官,如果知道為什麼,還望不吝指教if (right) {mPaint.setStyle(Style.FILL);mPaint.setColor(0xaaffffff);canvas.drawArc(oval, -56, 112, true, mPaint);}if (bottom) {mPaint.setStyle(Style.FILL);mPaint.setColor(0xaaffffff);canvas.drawArc(oval, 57, 66, true, mPaint);}if (left) {mPaint.setStyle(Style.FILL);mPaint.setColor(0xaaffffff);canvas.drawArc(oval, 124, 112, true, mPaint);}if (top) {mPaint.setStyle(Style.FILL);mPaint.setColor(0xaaffffff);canvas.drawArc(oval, 237, 66, true, mPaint);}//如果上下左右被按了,為了中間的部分不顯示,這裡畫圓遮住了那部分白色if (right || top || bottom || left) {mPaint.setStyle(Style.FILL);mPaint.setColor(0xFF436EEE);canvas.drawCircle(width / 2, height / 2, 38, mPaint);}mPaint.setStyle(Style.STROKE);mPaint.setColor(0xffffffff);mPaint.setStrokeWidth(1);mPaint.setAlpha(100);//根據標準橢圓公式,求得的一個量,我們這裡只用再進行座標變換,就可以得到四個在橢圓上的點了float t = getCoordinate(width - 10, height - 10);//四條地區分割線的起始座標float[] pts = {width / 2 + getSF(radius), height / 2 + getSF(radius), width / 2 + t, height / 2 + t,width / 2 - getSF(radius), height / 2 + getSF(radius), width / 2 - t, height / 2 + t,width / 2 + getSF(radius), height / 2 - getSF(radius), width / 2 + t, height / 2 - t,width / 2 - getSF(radius), height / 2 - getSF(radius), width / 2 - t, height / 2 - t};canvas.drawLines(pts, mPaint);}private float getCoordinate(int w, int h) {return (float) ((w * h) / (Math.sqrt(w*w + h*h) * 2));}/** 得到圓形的直角邊的長度 */private float getSF(int a) {return (float) (a / Math.sqrt(2));}@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:float x = event.getX();float y = event.getY();//不在橢圓內,什麼處理都不做if (!isInOval(x, y)) {return false;}if (isInCricle(x,y)) {center = true;if (onShapListener != null) {onShapListener.onCenterListener();}} else {float a = x - y - (width - height) / 2;float b = x + y - (width + height) / 2;if (a > 0) {if (b > 0) {right = true;if (onShapListener != null) {onShapListener.onRightListener();}} else {top = true;if (onShapListener != null) {onShapListener.onTopListener();}}} else {if (b > 0) {bottom = true;if (onShapListener != null) {onShapListener.onBottomListener();}} else {left = true;if (onShapListener != null) {onShapListener.onLeftListener();}}}}invalidate();break;case MotionEvent.ACTION_UP:top = false;right = false;bottom = false;left = false;center = false;invalidate();break;}return true;}/** (x, y)是否在橢圓內部 */private boolean isInOval(float x, float y) {float tmp = (2*x/width - 1) * (2*x/width - 1) + (2*y/height - 1) * (2*y/height - 1);if (tmp <= 1) {return true;} else {return false;}}/** (x, y)是否在中間圓裡面 */private boolean isInCricle(float x, float y) {float tmp = (x - width/2) * (x - width/2) + (y - height/2) * (y - height/2);if (tmp <= radius * radius) {return true;} else {return false;}}}
這裡是調用的代碼:
private ShapeView.ShapeViewListener listener;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ShapeView view = new ShapeView(this);FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);view.setLayoutParams(lp);setContentView(view);listener = new ShapeView.ShapeViewListener() {@Overridepublic void onTopListener() {show("top");}@Overridepublic void onRightListener() {show("right");}@Overridepublic void onLeftListener() {show("left");}@Overridepublic void onCenterListener() {show("center");}@Overridepublic void onBottomListener() {show("bottom");}};view.setOnShapeListener(listener);}
上面的show函數,是一個封裝了的Toast顯示。
OK,這篇文章結束了。