VYakushev
@VYakushev
Разработчик Android в Nowtaxi

Как сделать View с прозрачной областью?

Задача следующая: есть фоновое изображение, поверх него нужно наложить полупрозрачный фон в центре которого полностью прозрачный круг. При этом фоновое изображение - это отображение карты с текущими координатами. Т.е. карта должна жить своей жизнью. А сверху карты получаем что-то в виде полупрозрачной пленки с вырезанным кругом в центре.
Написан следующий код:
public class CircleView extends View {

    private Paint srcPaint;
    private Paint dstPaint;

    public CircleView(Context context) {
        this(context, null, 0);
    }

    public CircleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        float centerX = width / 2;
        float centerY = height / 2;
        float circleRadius = Math.min(width, height) / 5;

        canvas.drawRect(0, 0, width, height, dstPaint);
        canvas.drawCircle(centerX, centerY, circleRadius, srcPaint);
    }

    private void init() {
        srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        srcPaint.setColor(Color.WHITE);
        srcPaint.setStyle(Paint.Style.FILL);
        srcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

        dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        dstPaint.setColor(Color.argb(221, 255, 217, 32));
        dstPaint.setStyle(Paint.Style.FILL);
    }
}

Почему-то вместо прозрачной области получается черный непрозрачный круг. Что сделано не так или чего не хватает?
  • Вопрос задан
  • 1702 просмотра
Решения вопроса 1
VYakushev
@VYakushev Автор вопроса
Разработчик Android в Nowtaxi
В результате долгих поисков удалось найти причину проблемы и её решение. Решение нашел здесь: stackoverflow.com/questions/18387814/drawing-on-ca... Необходимо создавать новое растровое изображение, поддерживающее прозрачность, рисовать на нём, а уже потом рисовать это растровое изображение на холсте. Результирующий код получается таким:
public class CircleView extends View {

    private Paint srcPaint;

    public CircleView(Context context) {
        this(context, null, 0);
    }

    public CircleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        float centerX = width / 2;
        float centerY = height / 2;
        float circleRadius = Math.min(width, height) / 5;

        Bitmap background = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        Canvas layer = new Canvas(background);
        layer.drawColor(getResources().getColor(R.color.transparent_yellow));
        layer.drawCircle(centerX, centerY, circleRadius, srcPaint);

        canvas.drawBitmap(background, 0, 0, null);
    }

    private void init() {
        srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        srcPaint.setColor(Color.WHITE);
        srcPaint.setStyle(Paint.Style.FILL);
        srcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    }
}

Есть только один минус: создание Bitmap и Canvas при каждой перерисовке View.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы