android -- 如何在圆中画一个矩形

android -- How to draw a rect in circle

我需要如下视图:

蓝色高度会根据语音更新

我知道用可以画出那个圆角矩形

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@color/bg_send_text" />
    <corners android:radius="100dip" />
</shape>

然后我写了一个 VoiceDrawable extends GradientDrawable,并使用这个代码:

public void setVoice(int voice) {
    level = (float) 1.0 * voice / 100;
}

@Override
public void draw(Canvas canvas) {
    super.draw(canvas);

    rect = getBounds();
    canvas.drawRect(rect.left, rect.top + (rect.bottom - rect.top) * 
        (1 - level), rect.right, rect.bottom, paint);
}

但结果是:

虽然我使用:

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

那么如何实现这个视图呢?我能做什么?

您应该更改您的 PorterDuff 模式:

全部

我已经实现了这个视图:

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.GradientDrawable;

public class VoiceDrawable extends GradientDrawable {
    private static final float DEFAULT_LEVEL = 0.5f;

    private Paint levelPaint;
    private Paint viewPaint;
    private BitmapShader bitmapShader;
    private Matrix shaderMatrix;
    private float radius;

    private float level;

    public VoiceDrawable() {
        super();
        init();
    }

    private void init() {
        levelPaint = new Paint();
        levelPaint.setStyle(Paint.Style.FILL);

        viewPaint = new Paint();
        shaderMatrix = new Matrix();
    }

    public void setCornerRadius(float radius) {
        super.setCornerRadius(radius);

        this.radius = radius;
    }

    public void setVoice(float level) {
        this.level = level;

        invalidateSelf();
    }

    public void setLevelColor(int color) {
        levelPaint.setColor(color);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        Rect rect = getBounds();
        if (bitmapShader == null) {
            initLevel(rect);
        }
        float scale = level == 0 ? 100 : (1 - level) / (1 - DEFAULT_LEVEL);
        shaderMatrix.setScale(1, scale, 0, DEFAULT_LEVEL);
        bitmapShader.setLocalMatrix(shaderMatrix);

        float rad = Math.min(radius, Math.min(rect.width(), rect.height()) * 0.5f);
        canvas.drawRoundRect(new RectF(rect), rad, rad, viewPaint);
    }

    private void initLevel(Rect rect) {
        Bitmap bitmap = Bitmap.createBitmap(rect.width(), rect.height(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawRect(rect.left, rect.top + rect.height() * (1 - DEFAULT_LEVEL), rect.right, rect.bottom, levelPaint);

        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        viewPaint.setShader(bitmapShader);
    }
}

主要思想是使用着色器。 我从 https://github.com/gelitenight/WaveView

得到灵感