2015-12-10 151 views
0

我對我的佈局有一個複雜的自定義邏輯,它依賴於子狀態:如果有任何孩子沒有足夠的空間,則要求每個孩子使用自定義濃縮狀態。我應該在android中使用getMeasuredState()嗎?

如何我希望它是

正如 getMeasuredState()說:

只返回狀態getMeasuredWidthAndState()和getMeasuredHeightAndState()位,結合成一個整數。寬度分量位於常規位MEASURED_STATE_MASK中,高度分量位於位移MEASURED_HEIGHT_STATE_SHIFT >> MEASURED_STATE_MASK位。

我想,我們可以在每次測量後詢問每個孩子,如果它在測量狀態的幫助下過於受限制。所以,我的佈局實現從LinearLayout延伸,並增加了以下內容:

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    expand(); 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    if (isTooSmall()) { 
     condense(); 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 
} 

/** 
* return true if any child has TOO_SMALL flag 
*/ 
private boolean isTooSmall(){ 
    for (int i = 0; i < getChildCount(); i++){ 
     View child = getChildAt(i); 
     if (child != null){ 
      //I'm interested in width only     
      int measuredState = child.getMeasuredState() & MEASURED_STATE_TOO_SMALL; 
      if (measuredState != 0) return true; 
     } 
    } 
    return false; 
} 

什麼它竟然是

child.getMeasuredState()返回0,沒有問題,如果他們修剪與否(佈局有確切的寬度)。我的所有孩子的觀點都是從TextView擴展而來,仔細查看源代碼,我發現TextView根本不使用測量狀態位!爲什麼會這樣,我應該從哪裏知道?

的問題

我們什麼時候應該依賴於這個MEASURED_STATE_MASK?如果連框架組件(api 23)都可以輕易忽略它,那麼我們怎麼能確定它會起作用?我想任何View完全沒有保證,佈局的真實狀態和getMeasuredState()的結果是相同的東西。或者它只是一個類似於TextView的類,它應該從未具有TOO_SMALL狀態(如果是這樣,那麼爲什麼)?

回答

1

也許它返回0因爲它的onLayout()onMeasure()方法被錯誤地實現?

當它們沒有被正確實現時,它需要一段時間才能找到它的實際大小 - 如果它甚至「發現」它並將值從0更改爲其他值。

嘗試這兩種方法:

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 

    int desiredWidth = 100; 
    int desiredHeight = 100; 

    int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
    int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
    int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
    int heightSize = MeasureSpec.getSize(heightMeasureSpec); 

    int width; 
    int height; 

    //Measure Width 
    if(widthMode == MeasureSpec.EXACTLY) { 
     //Must be this size 
     width = widthSize; 
    } else if(widthMode == MeasureSpec.AT_MOST) { 
     //Can't be bigger than... 
     width = Math.min(desiredWidth, widthSize); 
    } else { 
     //Be whatever you want 
     width = desiredWidth; 
    } 

    //Measure Height 
    if(heightMode == MeasureSpec.EXACTLY) { 
     //Must be this size 
     height = heightSize; 
    } else if(heightMode == MeasureSpec.AT_MOST) { 
     //Can't be bigger than... 
     height = Math.min(desiredHeight, heightSize); 
    } else { 
     //Be whatever you want 
     height = desiredHeight; 
    } 

    //MUST CALL THIS 
    setMeasuredDimension(width, height); 

    linear_rootLayout.measure(MeasureSpec.makeMeasureSpec(width, widthMode), MeasureSpec.makeMeasureSpec(height, heightMode)); 
    measureChildren(MeasureSpec.makeMeasureSpec(width, widthMode), MeasureSpec.makeMeasureSpec(height, heightMode)); 
    super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), MeasureSpec.makeMeasureSpec(height, heightMode)); 
} 

    @Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    // TODO Auto-generated method stub 
    final int count = getChildCount(); 
    int curWidth, curHeight, curLeft, curTop, maxHeight; 

    //get the available size of child view 
    int childLeft = this.getPaddingLeft(); 
    int childTop = this.getPaddingTop(); 
    int childRight = this.getMeasuredWidth() - this.getPaddingRight(); 
    int childBottom = this.getMeasuredHeight() - this.getPaddingBottom(); 
    int childWidth = childRight - childLeft; 
    int childHeight = childBottom - childTop; 

    maxHeight = 0; 
    curLeft = childLeft; 
    curTop = childTop; 
    //walk through each child, and arrange it from left to right 
    for(int i = 0; i < count; i++) { 
     View child = getChildAt(i); 
     if(child.getVisibility() != GONE) { 
      //Get the maximum size of the child 
      child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST)); 
      curWidth = child.getMeasuredWidth(); 
      curHeight = child.getMeasuredHeight(); 
      //wrap is reach to the end 
      if(curLeft + curWidth >= childRight) { 
       curLeft = childLeft; 
       curTop += maxHeight; 
       maxHeight = 0; 
      } 
      //do the layout 
      child.layout(curLeft, curTop, curLeft + curWidth, curTop + curHeight); 
      //store the max height 
      if(maxHeight < curHeight) maxHeight = curHeight; 
      curLeft += curWidth; 
     } 
    } 
} 

也許他們改變一些東西給你。也許你需要實現measure()layout()方法。

我不太清楚你想用你的用例中的這些方法來實現什麼。

+0

我沒有觸及度量本身的過程 - 它是在LinearLayout中實現的,我在我的佈局中擴展,在TextView中我使用它,因此它是100%正確的。 「你試圖達到的目標......」 - 我需要知道孩子是否會被裁剪。事實證明,這是不可能的,通過'getMeasuredState()'方式' –

+0

順便說一句,我們正在談論狀態,而不是大小 - 返回的大小值是正確的,但是,我確實希望顯示「MEASURED_STATE_TOO_SMALL」位,當你的'TextView'在中間句子 –

+1

中被中斷時,感謝這個提示需要花費一點時間進行測量 - 需要試驗一下)) –