在圆圈内创建右箭头

Creating right arrow inside circle

我想使用 android 如下所示绘制图像:

我可以做箭头,但是当我添加圆圈时,图像会变形。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
    <shape>
        <solid android:color="@android:color/transparent"/>
        <size android:width="2dp" android:height="50dp"/>
    </shape>
</item>

<item android:bottom="20dp">
    <rotate
        android:fromDegrees="45"
        android:toDegrees="45">
        <shape android:shape="rectangle">
            <solid android:color="#F0AD4E"/>
            <corners
                android:radius="0dp"
                android:bottomRightRadius="0dp"
                android:bottomLeftRadius="0dp"/>
        </shape>
    </rotate>
</item>

<item android:top="20dp">
    <rotate
        android:fromDegrees="-45"
        android:toDegrees="45">
        <shape android:shape="rectangle">
            <solid android:color="#F0AD4E"/>
            <corners
                android:radius="0dp"
                android:topRightRadius="0dp"
                android:topLeftRadius="0dp"/>
        </shape>
    </rotate>
</item>

谁能帮我补图

谢谢。

不要为此使用可绘制对象,使用自定义视图和 canvas。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Bojan on 17.5.2015.
 */

public class CircleRightArrow extends View {

    private int circleColor = 0xFF505070;
    private int arrowColor = 0xFF505070;
    private int measuredSize;
    private int strokeWidth;

    private Paint mCirclePiant, mArrowPaint;

    public CircleRightArrow(Context context) {
        super(context);
        init(context, null, 0);
    }

    public CircleRightArrow(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public CircleRightArrow(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attributeSet, int defStyle) {
        mCirclePiant = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePiant.setColor(circleColor);
        mCirclePiant.setStyle(Paint.Style.STROKE);

        mArrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mArrowPaint.setColor(arrowColor);
        mArrowPaint.setStyle(Paint.Style.STROKE);
        mArrowPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

        measuredSize = Math.min(measuredHeight, measuredWidth);
        strokeWidth = Math.round(measuredSize * 0.05f);
        mCirclePiant.setStrokeWidth(strokeWidth);
        mArrowPaint.setStrokeWidth(strokeWidth);
        // Make a square
        setMeasuredDimension(measuredSize + strokeWidth, measuredSize + strokeWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (measuredSize <= 0) {
            // Not much we can draw, can we
            return;
        }

        float center = (measuredSize + strokeWidth) * 0.5f;
        canvas.drawCircle(center, center, measuredSize * 0.5f, mCirclePiant);

        canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center + 0.2f * measuredSize, mArrowPaint);
        canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center - 0.2f * measuredSize, mArrowPaint);
    }
}

1920x1080p 下 50x50dp 的结果

根据 Bojan 的回答,我编辑了视图以根据触摸事件重绘并添加了 OnClickListener 部分。欢迎提出任何改进建议。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by noorul.ahmed on 5/18/2015.
 */
public class CircleRightArrow extends View {

    private int viewColor;
    private int backgroundColor;
    private int normalColor = 0xFFF0AD4E;
    private int normalBackground = 0xFFFFFFFF;
    private int touchBackground = 0xFFEC971F;
    private int touchColor = 0xFFFFFFFF;
    private int disabledBackground = 0xFFFFFFFF;
    private int disabledColor = 0xFFCECECE;
    private int measuredSize;
    private int strokeWidth;
    private boolean touched = false;
    private float startX, startY, endX, endY;
    private OnClickListener listener;

    private Paint mCirclePiant, mArrowPaint;

    public CircleRightArrow(Context context) {
        super(context);
        init(context, null, 0);
        setInitialColor();
    }

    public CircleRightArrow(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
        setInitialColor();
    }

    public CircleRightArrow(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
        setInitialColor();
    }

    private void init(Context context, AttributeSet attributeSet, int defStyle) {
        mCirclePiant = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePiant.setColor(viewColor);
        mCirclePiant.setStyle(Paint.Style.STROKE);

        mArrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mArrowPaint.setColor(viewColor);
        mArrowPaint.setStyle(Paint.Style.STROKE);
        mArrowPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

        measuredSize = Math.min(measuredHeight, measuredWidth);
        strokeWidth = Math.round(measuredSize * 0.025f);
        mCirclePiant.setStrokeWidth(strokeWidth);
        mArrowPaint.setStrokeWidth(strokeWidth);
        // Make a square
        setMeasuredDimension(measuredSize + strokeWidth, measuredSize + strokeWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
            if (measuredSize <= 0) {
                // Not much we can draw, can we
                return;
            }

            float center = (measuredSize + strokeWidth) * 0.5f;
            canvas.drawCircle(center, center, measuredSize * 0.5f, mCirclePiant);

            canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center + 0.2f * measuredSize, mArrowPaint);
            canvas.drawLine(center + 0.2f * measuredSize, center, center - 0.1f * measuredSize, center - 0.2f * measuredSize, mArrowPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean result = super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN :
                touched = true;
                startX = event.getX();
                startY = event.getY();
                togglePaintColor(event);
                postInvalidate();
                return true;
            case MotionEvent.ACTION_UP :
                endX = event.getX();
                endY = event.getY();
                togglePaintColor(event);
                postInvalidate();
                float diffX = Math.abs(startX - endX);
                float diffY = Math.abs(startY - endY);

                if (diffX <= 5 && diffY <= 5 && touched ) {
                    dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,1));
                }
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if(event.getAction() == KeyEvent.ACTION_UP) {
            touched = false;
            if(listener != null) listener.onClick(this);
        }
        return super.dispatchKeyEvent(event);
    }

    public void setListener(OnClickListener listener) {
        this.listener = listener;
    }

    public void setInitialColor(){
        if (isClickable()){
            viewColor = normalColor;
            backgroundColor = normalBackground;
        }
        else {
            viewColor = disabledColor;
            backgroundColor = disabledBackground;
            this.listener = null;
        }
        mCirclePiant.setColor(viewColor);
        mCirclePiant.setStyle(Paint.Style.STROKE);
        mArrowPaint.setColor(viewColor);
    }

    @Override
    public void setClickable(boolean isClickable){
        super.setClickable(isClickable);
        if (isClickable){
            viewColor = normalColor;
            backgroundColor = normalBackground;
        }
        else {
            viewColor = disabledColor;
            backgroundColor = disabledBackground;
            this.listener = null;
        }
        mCirclePiant.setColor(viewColor);
        mCirclePiant.setStyle(Paint.Style.STROKE);
        mArrowPaint.setColor(viewColor);
        postInvalidate();
    }

    private void togglePaintColor(MotionEvent event) {
        if (isClickable()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                viewColor = touchColor;
                backgroundColor = touchBackground;
                mCirclePiant.setColor(backgroundColor);
                mCirclePiant.setStyle(Paint.Style.FILL);
                mArrowPaint.setColor(viewColor);

            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                viewColor = normalColor;
                backgroundColor = normalBackground;
                mCirclePiant.setColor(viewColor);
                mCirclePiant.setStyle(Paint.Style.STROKE);
                mArrowPaint.setColor(viewColor);
            }
        }
    }
}

三种按钮状态是:

  1. 正常状态
  2. 按下状态
  3. 禁用状态