-1

私が欲しかったのは、場合によってはアクティブであることを示す「v」画像を含むボタンを作成することでした。ボタンを押すたびに状態が変わるわけではないので、実際にはチェックボックスではありません。

しかし、アイデアはこれです。プレーンなボタンが必要です。「v」の別の小さな画像があります。そのボタンでtoggle()メソッドを使用すると、ボタンが十分に拡張されるため、「v」の画像が右上隅にうまく収まります。

これは私のコードです:

public class ButtonWithV extends Button {
    private Drawable mVImageDrawable;
    private int mImageWidth;
    private boolean mIsMarked;

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

    public ButtonWithV(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.ButtonWithVStyle);
    }

    public ButtonWithV(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mImageWidth = 0;
        TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.ButtonWithV, defStyle, 0);
        Drawable d = a.getDrawable(R.styleable.ButtonWithV_button_v_drawable);
        if( d != null){
            setVImageDrawable(d);
        }
//      setPadding(getPaddingLeft(), getPaddingTop(),
//              getPaddingRight(), getPaddingBottom());
        mIsMarked = false;
    }

    public void setMarked(boolean marked){
        if( marked != mIsMarked){
            mIsMarked = marked;
            requestLayout();
//          invalidate();
        }
    }

    private void setVImageDrawable(Drawable d) {
        mVImageDrawable = d;
        mImageWidth = mVImageDrawable.getIntrinsicWidth();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Rect temp = canvas.getClipBounds();
        System.out.println(String.format("top: %d, bottom: %d, left: %d, right: %d",
                temp.top, temp.bottom, temp.left, temp.right));
        super.onDraw(canvas);
        System.out.println(String.format("top: %d, bottom: %d, left: %d, right: %d",
                temp.top, temp.bottom, temp.left, temp.right));

        if( mVImageDrawable != null && mIsMarked){
            Rect bounds = canvas.getClipBounds();
            int right = bounds.right - 5;
            int left = right - mImageWidth;
            int top = bounds.top + 2;
            int bottom = top + mVImageDrawable.getIntrinsicHeight();
            mVImageDrawable.setBounds(left, top, right, bottom);
            mVImageDrawable.draw(canvas);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if( mIsMarked ){
            setMeasuredDimension(getMeasuredWidth() + mImageWidth, getMeasuredHeight());
        }
    }

    public void toggle(){
        setMarked(! mIsMarked );
    }

}

-5と+2に注意してください(正確な数値を見たかったので、そのままにしておくことはできません)。ここで問題があると思うのは、おそらく問題になるでしょうが、すべてのウィジェットで、ウィジェットのgetRight()、getLeft()などを使用できないことです...

ただし、キャンバス上の実際のウィジェットの場所が表示されるため、(でonDraw)キャンバスを取得すると、クリップされて(0,0)に変換されます。

正しく取得し、ウィジェットの右隅を知りたい場合は、クリップの右隅または測定された幅を取得する必要があります。高さも同じです。

もう1つの問題は、背景がどのように描画されるかわからないことですが、ウィジェットの右側から5ピクセルを削除して正確な位置に到達する必要があるため、内側の余白またはパディングを意味することはわかっています。

通常のパディングではないので、確認しました。それで、それは何でしょうか?ユーザーが右上の相対座標にパディングとマージンを設定する場合を含め、常にどのように取得できますか?そこに描く必要があります。

4

1 に答える 1

-1

最終的には、パディングを使用して問題を解決しました。必要なボタンの幅を右側に追加するだけで、オーバーレイ画像を描画できます。修正されたコードのスナップショットは次のとおりです。

public void setMarked(boolean marked){
        if( marked != mIsMarked){
            mIsMarked = marked;
            requestLayout();
        }
    }


    private void setVImageDrawable(Drawable d) {
        mVImageDrawable = d;
        mImageWidth = mVImageDrawable.getIntrinsicWidth();
    }

    @Override
    public int getCompoundPaddingRight() {
        int orig = super.getCompoundPaddingRight();
        int res = orig;
        if( mIsMarked ){
            res += mImageWidth;
        }
        return res;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if( mVImageDrawable != null && mIsMarked){
            Rect bounds = canvas.getClipBounds();
            int right = bounds.right;
            int left = right - mImageWidth;
            int top = bounds.top;
            int bottom = top + mVImageDrawable.getIntrinsicHeight();
            mVImageDrawable.setBounds(left, top, right, bottom);
            mVImageDrawable.draw(canvas);
        }
    }

    public void toggle(){
        setMarked(! mIsMarked );
    }
于 2011-11-08T13:14:24.090 に答える