Пользовательский вид Android отрисовывает BitmapDrawable в разделе предварительного просмотра неправильно

На этот пример есть два взгляда. Слева — мой пользовательский вид, а справа — ImageView. ImageView, кажется, правильно рисует на экране предварительного просмотра. Однако оба вида правильно рисуют на работающем устройстве.

Но я хочу, чтобы он отображал правильный предварительный просмотр, как это делает ImageView. Что я сделал не так ?

ПРЕДВАРИТЕЛЬНЫЙ ПРОСМОТР

введите здесь описание изображения

РАБОТАЮЩЕЕ УСТРОЙСТВО

введите здесь описание изображения

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.apg.mobile.repeatlayout.MainActivity">

    <com.my.CustomView
        android:id="@+id/aa"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@color/colorPrimary"
        app:src="@drawable/samplebg" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:layout_marginTop="10dp"
        android:layout_toEndOf="@+id/aa"
        android:background="@color/colorPrimary"
        android:src="@drawable/samplebg" />

</RelativeLayout>

Пользовательский вид

public class CustomView extends View {

    private BitmapDrawable bitmapDrawable;

    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        readAttribute(context, attrs, 0);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        readAttribute(context, attrs, defStyleAttr);
    }

    @TargetApi(23)
    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        readAttribute(context, attrs, defStyleAttr);
    }

    private void readAttribute(Context context, AttributeSet attrs, int defStyleAttr) {

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
        Drawable drawable = a.getDrawable(R.styleable.CustomView_src);

        if (drawable == null)
            throw new NullPointerException("You have to set src first..");

        bitmapDrawable = drawableToBitmapDrawable(drawable);

        a.recycle();
    }

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

        int wm, hm;
        int viewHeightMode = MeasureSpec.getMode(heightMeasureSpec);
        int viewWidthMode = MeasureSpec.getMode(widthMeasureSpec);

        Log.d("VIEW WIDTH-MODE", getMode(viewWidthMode));
        Log.d("VIEW HEIGHT-MODE", getMode(viewHeightMode));

        // 1: find user desired dimension
        int desiredWidth = measureDesiredSize(widthMeasureSpec, bitmapDrawable.getIntrinsicWidth());
        int desiredHeight = measureDesiredSize(heightMeasureSpec, bitmapDrawable.getIntrinsicHeight());

        wm = MeasureSpec.makeMeasureSpec(desiredWidth, viewWidthMode);
        hm = MeasureSpec.makeMeasureSpec(desiredHeight, viewHeightMode);
        setMeasuredDimension(wm, hm);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        bitmapDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        bitmapDrawable.draw(canvas);
    }

    private int measureDesiredSize(int measureSpec, int imageSize) {

        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);

        if (mode == MeasureSpec.EXACTLY) {
            return size;
        } else if (mode == MeasureSpec.AT_MOST) {
            return Math.min(size, imageSize);
        } else {
            return imageSize;
        }
    }

    public BitmapDrawable drawableToBitmapDrawable(Drawable drawable) {

        if (drawable instanceof BitmapDrawable) {

            return (BitmapDrawable) drawable;
        } else if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {

            // Single color bitmap will be created of 1x1 pixel
            Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
            return new BitmapDrawable(getResources(), bitmap);
        } else {

            Bitmap bitmap = Bitmap.createBitmap(
                    drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(),
                    Bitmap.Config.ARGB_8888);
            return new BitmapDrawable(getResources(), bitmap);
        }
    }


    private String getMode(int mode) {

        if (MeasureSpec.AT_MOST == mode) {
            return "AT_MOST";
        } else if (MeasureSpec.EXACTLY == mode) {
            return "EXACTLY";
        } else {
            return "UNSPECIFIED";
        }
    }
}

Атрибут

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CustomView">
        <attr name="src" format="reference" />    
    </declare-styleable>

</resources>

Ресурс

Образец для рисования, пожалуйста, поместите его в папку для рисования.


person Jongz Puangput    schedule 11.03.2017    source источник


Ответы (1)


Мне удалось решить мою проблему, используя форму ширины и высоты onSizeChanged.

    @Override
    protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
        super.onSizeChanged(xNew, yNew, xOld, yOld);

        mViewWidth = xNew;
        mViewHeight = yNew;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        bitmapDrawable.setBounds(0, 0, mViewWidth, mViewHeight);
        bitmapDrawable.draw(canvas);
    }
person Jongz Puangput    schedule 11.03.2017