Force ViewAnimator使用第一个孩子布局大小

问题描述:

我有一个ViewAnimator包含两个子视图。我希望ViewAnimator成为第一个孩子的大小,不管哪个孩子目前处于活动状态。这是可能的一点点配置,或者我必须实现我自己的子类和覆盖onMeasure等?Force ViewAnimator使用第一个孩子布局大小

我最终解决了这个问题,扩展ViewAnimator,覆盖onMeasure并将布局的尺寸设置为第一个孩子的尺寸。这是我想出来的。这基本上是对FrameLayout.onMeasure方法的一个小修改。

/** 
* Overrides the default {@link android.widget.FrameLayout#onMeasure(int, int)} 
* behavior to allow a main child to be defined which determines the size of the 
* layout. By default, the max size of all children is used as the layout size. 
*/ 
public class SizePinnedViewAnimator extends ViewAnimator { 
    private final int mainChildIndex; 

    @SuppressWarnings("UnusedDeclaration") 
    public SizePinnedViewAnimator(final Context context) { 
     super(context); 
     mainChildIndex = 0; 
    } 

    @SuppressWarnings("UnusedDeclaration") 
    public SizePinnedViewAnimator(final Context context, final AttributeSet attrs) { 
     super(context, attrs); 

     TypedArray a = context.obtainStyledAttributes(
       attrs, 
       R.styleable.SizePinnedViewAnimator); 
     mainChildIndex = a.getInt(R.styleable.SizePinnedViewAnimator_mainChild, 0); 
     a.recycle(); 
    } 

    /** 
    * {@inheritDoc} 
    * 
    * Copied from {@link android.widget.FrameLayout#onMeasure(int, int)} 
    */ 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     final int count = getChildCount(); 

     View mainChild = getChildAt(mainChildIndex); 
     if(mainChild == null) { 
      throw new IllegalStateException("No child at index " + mainChildIndex); 
     } 

     measureChildWithMargins(mainChild, widthMeasureSpec, 0, heightMeasureSpec, 0); 

     int maxHeight = mainChild.getMeasuredHeight(); 
     int maxWidth = mainChild.getMeasuredWidth(); 

     widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST); 
     heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); 

     // Find rightmost and bottommost child 
     for (int i = 0; i < count; i++) { 
      if(i == mainChildIndex) continue; 

      final View child = getChildAt(i); 
      if (getConsiderGoneChildrenWhenMeasuring() || child.getVisibility() != GONE) { 
       measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); 
      } 
     } 

     // Don't have access to the foreground padding numbers, but we're not 
     // using a foreground drawable anyway, so ignore it. 

     // Account for padding too 
     maxWidth += getPaddingLeft() + getPaddingRight(); 
     maxHeight += getPaddingTop() + getPaddingBottom(); 

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

     setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), 
       resolveSize(maxHeight, heightMeasureSpec)); 
    } 
} 

而在res/values/attrs.xml定义的属性:

<declare-styleable name="SizePinnedViewAnimator"> 
    <attr name="mainChild" format="integer" /> 
</declare-styleable>