0

我在我的 XML 布局中嵌入了 3 个相同的画布元素。不幸的是,Android 中的布局编辑器在布局中显示了错误的形状和错误的元素位置,这使得布局设计非常困难。

在这里,您可以看到布局编辑器中的内容:

Screenshot_LayoutEditor

在这里您可以看到 Android 模拟器中的输出:

截图_AndroidEmulator

有两件事很奇怪。

  1. 首先,在布局编辑器中,画布元素的形状没有正确显示。只显示了温度计的一小部分。XML 布局文件中画布元素的大小越小,分数就越小。
  2. 位置不对。您可以在布局编辑器中清楚地看到 3 个元素没有重叠,而在模拟器中它们重叠。

有谁知道为什么会发生这种情况以及如何解决这两个问题?

这是 XML 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <com.nikhiljain.canvasdrawingsample.Thermometer
        android:id="@+id/thermometer_1"
        android:layout_width="122dp"
        android:layout_height="130dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.546"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.912" />

    <com.nikhiljain.canvasdrawingsample.Thermometer
        android:id="@+id/thermometer_2"
        android:layout_width="222dp"
        android:layout_height="230dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.628" />

    <com.nikhiljain.canvasdrawingsample.Thermometer
        android:id="@+id/thermometer_3"
        android:layout_width="322dp"
        android:layout_height="330dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />




</androidx.constraintlayout.widget.ConstraintLayout>

这是画布元素的代码:

package com.nikhiljain.canvasdrawingsample;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class Thermometer extends View {
    private Paint mInnerCirclePaint;
    private int mInnerRadius;
    private int mThermometerColor = Color.RED;
    private Bitmap bitmap;
    private int left;
    private int top;
    private int innerCircleCenter;
    private int circleHeight;
    private int lineEndY;
    private int lineStartY;

    public Thermometer(Context context) {
        this(context, null);
    }

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

    public Thermometer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        if (attrs != null) {

            final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Thermometer, defStyle, 0);

            mThermometerColor = a.getColor(R.styleable.Thermometer_therm_color, mThermometerColor);

            a.recycle();
        }

        init();
    }

    private void init() {
        mInnerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mInnerCirclePaint.setColor(mThermometerColor);
        mInnerCirclePaint.setStyle(Paint.Style.FILL);

        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.thermometer_container);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        // init bitmap
        int scaledHeight;
        int scaledWidth;
        int width = getWidth();
        int height = getHeight();
        if (width > height) {
            scaledHeight = (int) (height * 0.98);
            scaledWidth = scaledHeight * bitmap.getWidth() / bitmap.getHeight();
        } else {
            scaledWidth = (int) (width * 0.98);
            scaledHeight = scaledWidth * bitmap.getHeight() / bitmap.getWidth();
        }

        bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true);

        mInnerRadius = bitmap.getWidth() / 8;

        mInnerCirclePaint.setStrokeWidth((int)(bitmap.getWidth() / 10));
        left = (getWidth() - bitmap.getWidth()) / 2;
        top = (int)(0.9 * getHeight()  - bitmap.getHeight()) / 2;
        innerCircleCenter = (left + left + bitmap.getWidth() + (Math.min(width, height) / 72)) / 2;
        circleHeight = (top + bitmap.getHeight()) - (int)(bitmap.getHeight() / 4.6f);
        Log.e("LogTag", "getHeight(): " + getHeight());
        Log.e("LogTag", "bitmap.getHeight(): " + bitmap.getHeight());
        //Parameter Values for lineStartY: 0.8=upper limit, 1.1=22 °C, 3.05=20 °C, 3.4=lower limit
        lineStartY = (int)(4.4*((int)(bitmap.getHeight() / 4.6f) + top));
        lineEndY = (int)(1.0* ((top + bitmap.getHeight()) - (int)(bitmap.getHeight() / 4f)));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawThermometer(canvas);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        //takes care of paddingTop and paddingBottom
        int paddingY = getPaddingBottom() + getPaddingTop();

        //get height and width
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        height += paddingY;

        setMeasuredDimension(width, height);
    }

    private void drawThermometer(Canvas canvas) {
        canvas.drawCircle(innerCircleCenter, circleHeight, mInnerRadius, mInnerCirclePaint);
        canvas.drawLine(innerCircleCenter, lineStartY, innerCircleCenter, lineEndY, mInnerCirclePaint);
        canvas.drawBitmap(bitmap, left, top, new Paint());
    }

    public void setThermometerColor(int thermometerColor) {
        this.mThermometerColor = thermometerColor;
        mInnerCirclePaint.setColor(mThermometerColor);
        invalidate();
    }
}

提醒:有意见吗?

4

0 回答 0