2015-10-10 76 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);