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>