2014-01-04 3 views
1

Я создаю пользовательскую группу ViewGroup. Если добавить свой собственный ViewGroup в макет без указания LayoutParams (как показано ниже), он отображает правильно:Высота дочерних высот ViewGroup равна 0, когда родительский параметр установлен на WRAP_CONTENT

... 
MyCustomViewGroup myViewGroup = new MyCustomViewGroup(this); 
myRelativeLayout.addView(myViewGroup); 
... 

Если я указываю LayoutParams и установить ширину MATCH_PARENT и высоту до WRAP_CONTENT (как показано ниже) , оно не отображается:

... 
MyCustomViewGroup myViewGroup = new MyCustomViewGroup(this); 
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
     RelativeLayout.LayoutParams.MATCH_PARENT, 
     RelativeLayout.LayoutParams.WRAP_CONTENT); 
myRelativeLayout.addView(myViewGroup, params); 
... 

Я запустил Debug для обоих сценариев.

Сценарий 1
Если я не указать LayoutParams, мнения ребенка измерения правильно, и когда метод перебирает все мнения ребенка, чтобы определить максимальную высоту, child.getMeasuredHeight() возвращает правильные значения каждый раз.

Сценарий 2
Если я указать LayoutParams с шириной, как MATCH_PARENT, и высоты, как WRAP_CONTENT, система делает два прохода через onMeasure, как описано ниже.

Pass 1
widthSpecMode = ТОЧНО
ширина = widthSpecSize = 758, которая является ширина родительского RelativeLayout
heightSpecMode = ТОЧНО
высота = heightSpecSize = 1055, которая равна высоте родителя RelativeLayout

Pass 2
widthSpecMode = ТОЧНО
ширина = widthSpecSize = 758 Вт hich - ширина родительского RelativeLayout
heightSpecMode = AT_MOST
Затем метод выполняет итерацию по всем дочерним представлениям для определения максимальной высоты, но child.getMeasuredHeight() возвращает 0 каждый раз.

Представления для детей представляют собой несколько ImageButtons и TextView. Все они имеют контент, и этот контент отображается правильно в первом сценарии. Почему во втором сценарии это получается как высота 0, и как я могу его исправить?

`' Я написал упрощенное тестовое приложение для воссоздания проблемы. Все необходимые коды показаны ниже. Если кто-то захочет попробовать, вы можете просто вырезать и вставить.

MainActivity.java

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     RelativeLayout rootLayout = (RelativeLayout)findViewById(R.id.LayoutRoot); 

     // Create an instance of MyViewGroup 
     MyViewGroup viewGroupOne = new MyViewGroup(this); 
     viewGroupOne.setId(1); 
     rootLayout.addView(viewGroupOne); 

     // Create a second instance and set layout width and height both to WRAP_CONTENT 
     MyViewGroup viewGroupTwo = new MyViewGroup(this); 
     viewGroupTwo.setId(2); 
     RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
       RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
     params.addRule(RelativeLayout.BELOW, 1); 
     rootLayout.addView(viewGroupTwo, params); 

     // Create a third Instance. Set layout width to MATCH_PARENT and height to WRAP_CONTENT 
     MyViewGroup viewGroupThree = new MyViewGroup(this); 
     params = new RelativeLayout.LayoutParams(
       RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
     params.addRule(RelativeLayout.BELOW, 2); 
     rootLayout.addView(viewGroupThree, params);  
    } 
} 

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/LayoutRoot" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context=".MainActivity" > 

</RelativeLayout> 

MyViewGroup.Java

public class MyViewGroup extends ViewGroup { 

    private static int instanceCounter; 

    public MyViewGroup(Context context) { 
     super(context); 

     instanceCounter++; 

     // Add a TextView 
     TextView textView = new TextView(context); 
     String text = "Instance " + instanceCounter; 
     textView.setText(text); 
     addView(textView); 

     // Add an ImageView 
     ImageView imageView = new ImageView(context); 
     imageView.setImageResource(android.R.drawable.ic_menu_add); 
     addView(imageView); 

    } 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     int childCount = getChildCount(); 
     int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); 
     int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 
     int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); 
     int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 
     int width = 0; 
     int height = 0; 
     int childState = 0; 

     // Measure Width 
     if (widthSpecMode == MeasureSpec.EXACTLY) { 
      width = widthSpecSize;   
     } else { 
      for (int i = 0; i < childCount; i++) { 
       final View child = getChildAt(i); 
       if (child.getVisibility() != GONE) { 
        measureChild(child, widthMeasureSpec, heightMeasureSpec); 
        width += child.getMeasuredWidth(); 
       } 
      } 
     } 
     if (widthSpecMode == MeasureSpec.AT_MOST) { 
      width = Math.min(width, widthSpecSize); 
     } 

     // Measure Height 
     if (heightSpecMode == MeasureSpec.EXACTLY) { 
      height = heightSpecSize;    
     } else { 
      for (int i = 0; i < childCount; i++) { 
       final View child = getChildAt(i); 
       if (child.getVisibility() != GONE) { 
        height = Math.max(height, child.getMeasuredHeight()); 
       } 
      } 
     } 
     if (heightSpecMode == MeasureSpec.AT_MOST) { 
      height = Math.min(height, heightSpecSize); 
     } 

     // Combine child states 
     for (int i = 0; i < childCount; i++) { 
      final View child = getChildAt(i); 
      if (child.getVisibility() != GONE) { 
       childState = combineMeasuredStates(childState, child.getMeasuredState()); 
      } 
     } 

     // Check against minimum width and height 
     width = Math.max(width, getSuggestedMinimumWidth()); 
     height = Math.max(height, getSuggestedMinimumHeight()); 

     // Report final dimensions 
     setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, childState), 
       resolveSizeAndState(height, heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT)); 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     int childCount = getChildCount(); 
     int leftPos = 0; 

     for (int i = 0; i < childCount; i++) { 
      final View child = getChildAt(i); 
      final int childWidth = child.getMeasuredWidth(); 

      if (child.getVisibility() != GONE) { 
       child.layout(leftPos, 0, leftPos + childWidth, getMeasuredHeight()); 
       leftPos += childWidth;    
      } 
     } 
    } 
} 
+0

сообщение MyCustomViewGroup.onLayout – pskink

+0

@pskink Привет. Спасибо, что посмотрели. Я обновил свой пост по запросу. –

+0

извините, но ничего не могу поделать, так как я вижу обратное: wirhout params я ничего не вижу, с параметрами wrap_content, weapon_content я вижу что-то – pskink

ответ

7

нормально зоИ кажется, вы забыли назвать measureChild (ребенок, widthMeasureSpec, heightMeasureSpec); при расчете высоты в onMeasure