如何在自定义视图中绘制具有确切大小的drawable?

时间:2013-09-04 20:16:21

标签: android android-custom-view

已解决:以下解决方案作为答案。

我有一个带有TransitionDrawable的自定义视图,当我在onDraw()方法中绘制它时,它会自动缩放以填充整个父布局,即使它在xml中设置为wrap_content也是如此。图片是mdpi和hdpi以及我的测试设备(三星galaxy s)我认为它不过是hdpi。

package com.adyrsoft.pronunciationtrainer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class RecordButton extends View {
    private static final String TAG = "RecordButton";
    private TransitionDrawable mDrawable;
    private boolean mActivated;

    private OnClickListener mOnClickListenerInternal = new OnClickListener() {

        @Override
        public void onClick(View v) {
            toggleState();
            if(mOnClickListener != null) {
                mOnClickListener.onClick(v);
            }
        }

    };

    private OnClickListener mOnClickListener = null;

    public RecordButton(Context context) {
        super(context);
        init();
    }

    public RecordButton(Context context, AttributeSet attrib) {
        super(context, attrib);
        init();
    }

    public RecordButton(Context context, AttributeSet attrib, int defStyle) {
        super(context, attrib, defStyle);
        init();
    }

    public void setState(boolean activated) { 
        mActivated = activated;
        if(mActivated){
            mDrawable.startTransition(300);
        }
        else {
            mDrawable.reverseTransition(300);
        }
    }

    public void toggleState() {
        if(mActivated) {
            setState(false);
        }
        else {
            setState(true);
        }
    }

    @SuppressWarnings("deprecation")
    private void init() {
        mActivated = false;
        mDrawable = (TransitionDrawable) getResources().getDrawable(R.drawable.btnrecord);

        Log.d(TAG, "Drawable intrinsic width and height are: " + 
                Integer.toString(mDrawable.getIntrinsicWidth()) + " " +
                Integer.toString(mDrawable.getIntrinsicHeight()));

        mDrawable.setBounds(0,0,mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());



        Log.d(TAG, "The bounds for the button are: "+mDrawable.getBounds().flattenToString());
        super.setBackgroundDrawable(mDrawable);
        setClickable(true);
        super.setOnClickListener(mOnClickListenerInternal);
        invalidate();
    }

    public void setOnClickListener(View.OnClickListener listener) {
        mOnClickListener = listener;
    }

    protected void onDraw (Canvas canvas) {
        super.onDraw(canvas);
    }

}

我做错了什么? 感谢。

1 个答案:

答案 0 :(得分:0)

在尝试了解如何在自定义视图中使用drawables以便以原始大小显示之后数小时,我已经找到了如何做到这一点。

首先,我不知道但必须知道的一些事情是:

  1. 背景drawable应留给父类 使用View作为父级时绘制。如果没有,则不能看到TransitionDrawable在图片之间消失。
  2. 只有当我要绘制背景drawable时,我才应该覆盖onDraw()并在那里进行绘图。
  3. 最后但同样重要的是我应该覆盖onMeasure()来指定视图的大小。如果我不这样做,它将填充父布局中的所有可用空间,就像发生在我身上一样。
  4. 我已经使用setBackgroundDrawable()将TransitionDrawable传递给父类,并且因为我没有在后台绘制可绘制的内容,所以我删除了onDraw()方法。我还在onMeasure()上实现了一个快速而肮脏的解决方案,指定了我正在绘制的图片的大小。

    这是最终结果:

    public class RecordButton extends View {
        private static final String TAG = "RecordButton";
        private static final int DESIRED_WIDTH = 180;
        private static final int DESIRED_HEIGHT = 66;
        private TransitionDrawable mDrawable;
        private Rect mViewRect;
        private boolean mActivated;
    
        private OnClickListener mOnClickListenerInternal = new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                toggleState();
                if(mOnClickListener != null) {
                    mOnClickListener.onClick(v);
                }
            }
    
        };
    
        private OnClickListener mOnClickListener = null;
    
        public RecordButton(Context context) {
            this(context, null, 0);
    
        }
    
        public RecordButton(Context context, AttributeSet attrib) {
            this(context, attrib, 0);
        }
    
        public RecordButton(Context context, AttributeSet attrib, int defStyle) {
            super(context, attrib, defStyle);
            init();
        }
    
        public void setState(boolean activated) { 
            mActivated = activated;
            if(mActivated){
                mDrawable.startTransition(300);
            }
            else {
                mDrawable.reverseTransition(300);
            }
        }
    
        public void toggleState() {
            if(mActivated) {
                setState(false);
            }
            else {
                setState(true);
            }
        }
    
        @SuppressWarnings("deprecation")
        private void init() {
            mActivated = false;
            mDrawable = (TransitionDrawable) getResources().getDrawable(R.drawable.btnrecord);
    
            setBackgroundDrawable(mDrawable);
    
            setClickable(true);
            super.setOnClickListener(mOnClickListenerInternal);
            invalidate();
        }
    
        public void setOnClickListener(View.OnClickListener listener) {
            mOnClickListener = listener;
        }
    
        @Override
        protected void onMeasure(int m, int n) {
            setMeasuredDimension(DESIRED_WIDTH, DESIRED_HEIGHT);
        }
    
    }