Android:扩展小部件和画布边界 - 扩展按钮

发布于 2024-12-02 08:41:58 字数 3037 浏览 1 评论 0原文

我想要的只是创建一个按钮,在某些情况下该按钮将包含一个“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)。

如果我得到正确的结果并且我想知道小部件的最右角,我需要获取剪辑的最右角或测量的宽度。高度也是如此。

另一个问题是我不知道背景是如何被淹没的,但我确实知道,因为我必须从小部件的右侧删除 5 个像素才能到达它的正确位置,这意味着内部边距或填充。

我检查过,这不是普通的填充物。那么它会是什么?我怎样才能始终获得包括用户设置填充和边距时的右上角相对坐标?我需要在那里画画。

All i wanted was to create a button that in some cases will contain a 'v' image to mark that it's active. not really a check box since not every time you press the button it changes it's state.

But the idea is this.
I need a plain button and i have another small image of 'v' that if i use a toggle() method on that button the button will get extended enough so the 'v' image can squeeze nicely to it's upper right corner.

this is my code:

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 );
    }

}

Please note the -5 and +2 (they cannot remain as such i just wanted to see exact numbers).
What I find problematic here, and will probably be problematic, is in all widgets I cannot use the widget's getRight(), getLeft() etc...

Since they give me the REAL widget location on the canvase, however (in onDraw) when I get the canvas it's clipped and translated to (0,0).

If I get it correctly and I want to know the widget's rightest corner I need to get the clip rightest corner or the measured width. same goes for the height.

Another problem is I have no idea how the background is drown but I do know that since I have to remove 5 pixels from the right of the widget to get to it's exact right position it means inner margins or padding.

It's not regular paddings, I checked. so what can it be ? how can I get, always, including when user set paddings and margins the upper right relative coordinates ? I need to draw there.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烈酒灼喉 2024-12-09 08:41:58

最终我使用填充来解决问题,我只是在右侧添加更多填充所需按钮的宽度,以便我可以绘制覆盖图像。
这是固定的代码快照:

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 );
    }

eventually i used padding to solve the issue, i just add more padding the width of the needed button to the right so i can draw the overlay image.
here's the fixed code snapshot:

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 );
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文