在Android 23源码RecyclerView的demo中见到了ViewAnimator这么一个组件:
<ViewAnimator
android:id="@+id/sample_output"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1">
<ScrollView
style="@style/Widget.SampleMessageTile"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
style="@style/Widget.SampleMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/horizontal_page_margin"
android:paddingRight="@dimen/horizontal_page_margin"
android:paddingTop="@dimen/vertical_page_margin"
android:paddingBottom="@dimen/vertical_page_margin"
android:text="@string/intro_message" />
</ScrollView>
<fragment
android:name="com.example.android.common.logger.LogFragment"
android:id="@+id/log_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ViewAnimator>
以前没用过这个控件,不知道它是干什么的?查了查源代码发现它实际上是一个viewGroup容器,就是控制显示它的某个ChildView(i),部分源码如下:
public class ViewAnimator extends FrameLayout {
int mWhichChild = 0; // 当前显示view的位置
Animation mInAnimation; // 显示view时加载的动画
Animation mOutAnimation; // 隐藏view时加载的动画
public ViewAnimator(Context context) {
super(context);
initViewAnimator(context, null);
}
public ViewAnimator(Context context, AttributeSet attrs) {
super(context, attrs);
.........................................
initViewAnimator(context, attrs);
}
/**
* 设置显示的view视图,一般使用这个方法来切换视图
*
* @param whichChild view的位置"0,1,2........
*/
@android.view.RemotableViewMethod
public void setDisplayedChild(int whichChild) {
mWhichChild = whichChild;
if (whichChild >= getChildCount()) {// 如果传入的数值大于childview的总数,显示第一个view
mWhichChild = 0;
} else if (whichChild < 0) {// 如果传入的数值是负数,显示最后一个view
mWhichChild = getChildCount() - 1;
}
boolean hasFocus = getFocusedChild() != null;//判断当前viewGroup中是否有view获取焦点
// This will clear old focus if we had it
showOnly(mWhichChild);
if (hasFocus) {
// Try to retake focus if we had it
requestFocus(FOCUS_FORWARD);
}
}
public void showNext() {
setDisplayedChild(mWhichChild + 1);
}
public void showPrevious() {
setDisplayedChild(mWhichChild - 1);
}
/**
* 切换显示的childview,判断是否使用动画
*/
void showOnly(int childIndex, boolean animate) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (i == childIndex) {
if (animate && mInAnimation != null) {
child.startAnimation(mInAnimation);
}
child.setVisibility(View.VISIBLE);
mFirstTime = false;
} else {
if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) {
child.startAnimation(mOutAnimation);
} else if (child.getAnimation() == mInAnimation)
child.clearAnimation();
child.setVisibility(View.GONE);
}
}
}
// 添加视图
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
super.addView(child, index, params);
if (getChildCount() == 1) {
child.setVisibility(View.VISIBLE);
} else {
child.setVisibility(View.GONE);
}
if (index >= 0 && mWhichChild >= index) {
// Added item above current one, increment the index of the displayed child
setDisplayedChild(mWhichChild + 1);
}
}
// 删除视图
@Override
public void removeViewAt(int index) {
super.removeViewAt(index);
final int childCount = getChildCount();
if (childCount == 0) {
mWhichChild = 0;
mFirstTime = true;
} else if (mWhichChild >= childCount) {
// Displayed is above child count, so float down to top of stack
setDisplayedChild(childCount - 1);
} else if (mWhichChild == index) {
// Displayed was removed, so show the new child living in its place
setDisplayedChild(mWhichChild);
}
}
// 设置view加载和退出的动画
public void setInAnimation(Animation inAnimation) {
mInAnimation = inAnimation;
}
public void setOutAnimation(Animation outAnimation) {
mOutAnimation = outAnimation;
}
}