2015-10-10 42 views
-1

我建立了一个简单的,自定义View类显示五个彩色圆圈和/或十字架,即呈现Fragment,并充当RecyclerView顶部的固定标题。整个事件放在ViewPager里面,另外一个Fragment(在ViewPager里有两个Fragment,这是第一个)。自定义视图棒棒糖ViewPager内,只有当不可见

我遇到的问题发生在我的棒棒糖设备上。无论何时加载UI,无论是第一次还是从配置更改,这View拒绝呈现。但奇怪的是,如果我将ViewPager移动到第二个Fragment(以便包含此View的那个不再可见)并启动配置更改,则当我跳回View时突然显示为正常。

我很难过。我已经在布局中试过其他自定义的View类,并且它们都可以正确渲染,所以它暗示了我的代码对于这个类特别错误。

这里是我的View类的代码:

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导致的问题:从我MathUtils类使用的两种方法

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

} 

}

而且?

+0

是'的onDraw()'被称为在所有的时候,你所得到的无效输出?如果您尝试在层次结构视图或** uiautomatorviewer **中查看输出结果,那么该视图会在该点呈现?如果不是,这些工具发现的视图状态有没有什么有趣的地方(例如,它被定位在屏幕外)? – CommonsWare

+0

@CommonsWare调用'onDraw()',对于'getWidth()','getHeight()','radius'等调用相同的结果,不管圆圈是否出现。该视图每次都在Hierarchy View中呈现,但结果与屏幕上的内容不一致。有时候会说在离线时(在配置更改后的ViewPager的第一页),这些圆形在层次视图中呈现,但当我选择第一页时消失。 – PPartisan

+0

@CommonsWare我也注意到,如果我设置了背景颜色,那么它每次都会出现。只有在我的'HintTrackerView'不在屏幕上的情况下开始配置更改时才会出现圆形和十字形。 – PPartisan

回答

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 

Viewwidth690px,但是当onDraw被称为第二次,而不是将mRectF的值重新设置为0,则使用先前的值。这意味着所有的圆圈/十字都被绘制在View的边界之外。

添加下面一行在onDrawfor循环之前开始纠正问题:

mRectF.set(0,0,0,0);