我试图在屏幕上显示几个相同的自定义视图。这是我的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可以访问getWidth
和getHeight
个视图。这不是重点。如果我删除此代码并只使用setPos
的任何值,我总是得到相同的。屏幕上只有一个视图(或所有视图,但在模板之上)。
导致只绘制一个视图的bug在哪里?
答案 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的边距,其他单词将相应地跟随。