0

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

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

我发布此可运行文件以访问getWidthgetHeight查看视图。这不是重点。如果我删除此代码并仅使用setPos任何值,我总是会得到相同的值。屏幕上只有一个视图(或全部,但在模型之上)。

导致仅绘制一个视图的错误在哪里?

4

1 回答 1

0

问题是您的视图在您的 post() 可运行文件执行时实际上还没有完成膨胀和初始布局。您想与 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 - 创建两个不同的可运行文件:第一个将位置更改发布到 word1。第二张贴剩余的位置变化。

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

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

于 2012-09-04T23:46:56.703 回答