只绘制了一个自定义视图

时间:2012-09-04 23:31:06

标签: java android

我试图在屏幕上显示几个相同的自定义视图。这是我的View类:

public class DraggableText extends View {
private int cStart;
private int cEnd;
private Paint mTextPaint, mBgPaint;
private RectF mRect;
private Point mPos;

public DraggableText(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
            R.styleable.DraggableText, 0, 0);

    try {
        cStart = Color.parseColor(a
                .getString(R.styleable.DraggableText_gradientStart));
        cEnd = Color.parseColor(a
                .getString(R.styleable.DraggableText_gradientEnd));
    } finally {
        a.recycle();
    }
    init();
}

private void init() {
    mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    Shader s = new LinearGradient(0, 0, 0, getHeight(), cStart, cEnd,
            Shader.TileMode.CLAMP);
    mBgPaint.setShader(s);

    mRect = new RectF();
    mPos = new Point(0, 0);
}

public void setPos(Point p){
    mPos = p;
    invalidate();
    requestLayout();
}

public Point getPos(){
    return mPos;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int desiredWidth = (widthSize / 2) - 80;
    int desiredHeight = 65;

    int width;
    int height;

    if (widthMode == MeasureSpec.EXACTLY) {
        width = widthSize;
    } else if (widthMode == MeasureSpec.AT_MOST) {
        width = Math.min(desiredWidth, widthSize);
    } else {
        width = desiredWidth;
    }

    if (heightMode == MeasureSpec.EXACTLY) {
        height = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
        height = Math.min(desiredHeight, heightSize);
    } else {
        height = desiredHeight;
    }

    setMeasuredDimension(width, height);
}

@Override
protected void onDraw(Canvas c) {
    super.onDraw(c);
     mRect.set(mPos.x, mPos.y, getWidth(), getHeight());
     c.drawRoundRect(mRect, 8, 8, mBgPaint);
}

}

onCreate回调中的活动中,我这样做:

    word1 = (DraggableText) findViewById(R.id.word1);
    word2 = (DraggableText) findViewById(R.id.word2);
    word3 = (DraggableText) findViewById(R.id.word3);
    word4 = (DraggableText) findViewById(R.id.word4);

    word1.post(new Runnable() {
        @Override
        public void run() {
            word1.setPos(new Point(20, 20));
            word2.setPos(new Point(word1.getWidth() + 20, 20));
            word3.setPos(new Point(20, word1.getHeight() + 10));
            word4.setPos(new Point(word1.getWidth() + 20, word1.getHeight() + 10));
        }
    });

我发布此runnable可以访问getWidthgetHeight个视图。这不是重点。如果我删除此代码并只使用setPos的任何值,我总是得到相同的。屏幕上只有一个视图(或所有视图,但在模板之上)。

导致只绘制一个视图的bug在哪里?

1 个答案:

答案 0 :(得分:0)

问题是,在post()runnable执行时,您的视图实际上没有完成通胀和初始布局。您希望与ViewTreeObserver进行交互。在Activity的onResume中,试试这个:

@Override
public void onResume(){
    super.onResume();
    findViewById(R.id.word1).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @Override public void onGlobalLayout() {
                        DraggableText word1 = (DraggableText) findViewById(R.id.word1);
                        DraggableText word2 = (DraggableText) findViewById(R.id.word2);
                        DraggableText word3 = (DraggableText) findViewById(R.id.word3);
                        DraggableText word4 = (DraggableText) findViewById(R.id.word4);
                        word1.setPos(new Point(20, 20));
                        word2.setPos(new Point(word1.getWidth() + 20, 20));
                        word3.setPos(new Point(20, word1.getHeight() + 10));
                        word4.setPos(new Point(word1.getWidth() + 20, word1.getHeight() + 10));
                        word1.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                }
            });
}

以下是ViewTreeObserver的更多信息。

跟进:啊,我的坏。我猜,我没有彻底阅读你的代码。我实际上不确定是否有一种方便的100%框架方式来做你所要求的。 requestLayout()只排队视图的下一个布局,它不会同步强制它。你可以尝试两件事:

1 - 创建两个不同的runnable:第一个将位置更改发布到word1。第二个发布剩余的职位变化。

2 - 不依赖于框架的getWidth \ getHeight,而是在自定义视图中跟踪自己的成员变量中的位置和维度。这样,您可以在调用setPos()时手动更新它们。

此外,您可以考虑完全使用不同的布局机制。尝试使用RelativeLayout容器,而不是进入这么多细节。然后,例如,您可以只更改word1的边距,其他单词将相应地跟随。