我建立了一个简单的,定制的View
类,显示五个彩色圆圈和/或十字架,即:
它占据Fragment
的顶部,并作为RecyclerView
顶部的固定标题。整个事情放在ViewPager
旁边另一个Fragment
(Fragment
只有两个ViewPager
。这是第一个。{/ p >
我遇到的问题出现在我的Lollipop设备上。无论何时加载UI,无论是第一次还是配置更改,此View
都拒绝呈现。但是很奇怪的是,如果我将ViewPager
移动到第二个Fragment
(以便包含此View
的那个不再可见)并启动配置更改,当我跳转时返回View
突然正常呈现。
我很难过。我已经在布局中尝试了其他自定义View
类,并且它们都正确呈现,因此它表明我的代码对此类特别错误。
以下是我的View
课程的代码:
public class HintTrackerView extends View {
private static final int DEFAULT_NO_OF_CIRCLES = 5;
private static final float DEFAULT_RADIUS_PERCENTAGE = 0.9F;
private static final int[] DEFAULT_ACTIVE_COLOURS = {
PRIMARY_GREEN,
createInterimColor(PRIMARY_GREEN, PRIMARY_ORANGE, 0.25F),
createInterimColor(PRIMARY_GREEN, PRIMARY_ORANGE, 0.5F),
createInterimColor(PRIMARY_GREEN, PRIMARY_ORANGE, 0.75F),
PRIMARY_ORANGE
};
private static final int DEFAULT_INACTIVE_COLOR = PRIMARY_GREY;
private int[] activeColors;
private int inactiveColor;
private Paint mFillPaint, mInactivePaint;
private RectF mRectF;
private float mFillRadius;
private int mNoOfCircles;
public HintTrackerView(Context context) {
super(context, null);
init();
}
public HintTrackerView(Context context, int[] activeColors) {
super(context, null);
init(activeColors);
}
public HintTrackerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
init(DEFAULT_ACTIVE_COLOURS);
}
private void init(int[] colors) {
this.activeColors = colors;
inactiveColor = DEFAULT_INACTIVE_COLOR;
if (mFillRadius == 0) mFillRadius = DEFAULT_RADIUS_PERCENTAGE;
if (mNoOfCircles == 0) mNoOfCircles = DEFAULT_NO_OF_CIRCLES;
if (colors.length != mNoOfCircles)
throw new IllegalArgumentException("Number of colours must match number of circles");
mFillPaint = new Paint();
mFillPaint.setAntiAlias(true);
mFillPaint.setStyle(Paint.Style.FILL);
mFillPaint.setColor(colors[0]);
mInactivePaint = new Paint();
mInactivePaint.setAntiAlias(true);
mInactivePaint.setDither(true);
mInactivePaint.setStyle(Paint.Style.STROKE);
mInactivePaint.setStrokeCap(Paint.Cap.ROUND);
mInactivePaint.setColor(inactiveColor);
mRectF = new RectF();
}
@Override
protected void onDraw(Canvas canvas) {
final int subCanvasSize = getWidth()/ mNoOfCircles;
for (int i = 0; i < mNoOfCircles; i++) {
mRectF.set(mRectF.right, 0, mRectF.right + subCanvasSize, getHeight());
mFillPaint.setColor(activeColors[i]);
//If hint is has been used, replace symbol with cross
if (i<3) {
drawCircle(canvas, mRectF);
} else {
drawCross(canvas, mRectF);
}
}
}
private void drawCross(Canvas canvas, RectF subCanvasBounds) {
mInactivePaint.setStrokeWidth(MathUtils.getHypotenuse(Math.min(subCanvasBounds.width(), subCanvasBounds.height()) * 0.1F));
float innerSubCanvasBounds = Math.min(subCanvasBounds.width(), subCanvasBounds.height());
float crossLength = MathUtils.getLengthOfFourtyFiveDegreeIsosceles(innerSubCanvasBounds);
float startX, startY, stopX, stopY;
startX = subCanvasBounds.centerX() - (crossLength*0.45F);
startY = subCanvasBounds.centerY() - (crossLength*0.45F);
stopX = subCanvasBounds.centerX() + (crossLength*0.45F);
stopY = subCanvasBounds.centerY() + (crossLength*0.45F);
canvas.drawLine(startX, startY, stopX, stopY, mInactivePaint);
startX = subCanvasBounds.centerX() + (crossLength*0.45F);
startY = subCanvasBounds.centerY() - (crossLength*0.45F);
stopX = subCanvasBounds.centerX() - (crossLength*0.45F);
stopY = subCanvasBounds.centerY() + (crossLength*0.45F);
canvas.drawLine(startX, startY, stopX, stopY, mInactivePaint);
}
private void drawCircle(Canvas canvas, RectF subCanvasBounds) {
float centerX, centerY, radius, viewSize;
centerX = subCanvasBounds.centerX();
centerY = subCanvasBounds.centerY();
viewSize = Math.min(getHeight(), subCanvasBounds.width());
radius = (viewSize/2) * mFillRadius;
canvas.drawCircle(centerX, centerY, radius, mFillPaint);
}
}
我的MathUtils
类使用了两种方法:
public static float getHypotenuse(float equalLengths) {
return getHypotenuse(equalLengths, equalLengths);
}
public static float getHypotenuse(float lengthOne, float lengthTwo) {
return (float) (Math.sqrt(Math.pow(lengthOne, 2) + Math.pow(lengthTwo, 2)));
}
public static float getLengthOfFourtyFiveDegreeIsosceles(float hypotenuse) {
return (float) (0.5F*hypotenuse*Math.sqrt(2));
}
为什么这个View
导致问题的任何想法?
答案 0 :(得分:1)
问题是由于onDraw()
在某些情况下被调用了两次。我只是检查以确保onDraw()
被调用,因为我错误地认为每次调用onDraw()
时,类构造函数也被调用。当我添加Log
次调用以查看每个圆圈/十字架如何测量其边界时,我看到了这个输出:
10-12 17:53:30.106 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 115.0
top = 0
Right = 230.0
Bottom = 36
10-12 17:53:30.106 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 230.0
top = 0
Right = 345.0
Bottom = 36
10-12 17:53:30.106 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 345.0
top = 0
Right = 460.0
Bottom = 36
10-12 17:53:30.106 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 460.0
top = 0
Right = 575.0
Bottom = 36
10-12 17:53:30.106 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 575.0
top = 0
Right = 690.0
Bottom = 36
10-12 17:53:30.106 13829-13829/? E/TAG﹕ onDraw
10-12 17:53:30.344 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 690.0
top = 0
Right = 805.0
Bottom = 36
10-12 17:53:30.345 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 805.0
top = 0
Right = 920.0
Bottom = 36
10-12 17:53:30.345 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 920.0
top = 0
Right = 1035.0
Bottom = 36
10-12 17:53:30.345 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 1035.0
top = 0
Right = 1150.0
Bottom = 36
10-12 17:53:30.345 13829-13829/? E/TAG﹕ Dimens for rectF:
left = 1150.0
top = 0
Right = 1265.0
Bottom = 36
View
width
为690px
,但第二次调用onDraw
时,而不是重置mRectF
的值返回0
,使用了之前的值。这意味着所有圆/十字都是在View
的边界之外绘制的。
在onDraw
开头和for
循环之前添加以下行更正了问题:
mRectF.set(0,0,0,0);