在Android中,ViewAnimator是FrameLayout的一个子类,用来做Views之间的切换。它是一个变换控件的
元素,帮助我们在Views之间(如TextView, ImageView或者其他layout)添加变换。它有助于在屏幕view添加动画。ViewAnimator可以在两个及以上Views上平滑的切换,通过合适动画,提供从一个View到另外一个View变换的方式。
XML属性 | 说明 |
---|---|
android:animateFirstView | 显示第一个View组件时是否使用动画 |
android:inAnimation | 显示子View组件时的动画 |
android:outAnimation | 隐藏子View组件时的动画 |
package com.example.ip_d.viewanimatorexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ViewAnimator;
public class MainActivity extends AppCompatActivity {
private ViewAnimator simpleViewAnimator;
Button btnNext;
/**
* array of images
*/
int[] images = {
R.drawable.lion,
R.drawable.cat,
R.drawable.dog,
R.drawable.bird1,
R.drawable.bird2};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get The references of Button and ViewAnimator
btnNext = (Button) findViewById(R.id.buttonNext);
// get the reference of ViewAnimator
simpleViewAnimator = (ViewAnimator) findViewById(R.id.simpleViewAnimator);
for (int i = 0; i < images.length; i++) {
// create a new object for ImageView
ImageView imageView = new ImageView(getApplicationContext());
// set image resource for ImageView
imageView.setImageResource(images[i]);
// add child view in ViewAnimator
simpleViewAnimator.addView(imageView);
}
// Declare in and out animations and load them using AnimationUtils class
Animation in = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
Animation out = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
// set the animation type to ViewAnimator
simpleViewAnimator.setInAnimation(in);
simpleViewAnimator.setOutAnimation(out);
// set false value for setAnimateFirstView
simpleViewAnimator.setAnimateFirstView(false);
// ClickListener for NEXT button
// When clicked on Button ViewSwitcher will switch between views
// The current view will go out and next view will come in with specified animation
btnNext.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
// show the next view of ViewAnimator ` `
simpleViewAnimator.showNext();
}
});
}
}
ViewSwitcher继承自ViewAnimator,代表了视图切换组件,大体上与ViewAnimator差不多。与ViewAnimator最大不同就是ViewSwitcher的子view最多只能有两个,多余两个将会报错。还有就是ViewSwitcher可以通过setFactory(ViewFactory factory)生成两个相同的子view,也可以通过addView(View view)方法添加子view。
package com.xiayutian.widgettest;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ViewSwitcher;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ViewSwitcherActivity extends AppCompatActivity {
@BindView(R.id.btn_switch)
Button btnSwitch;
@BindView(R.id.view_switcher)
ViewSwitcher viewSwitcher;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_switcher_activity);
ButterKnife.bind(this);
initSwitcher();
}
private void initSwitcher() {
Animation slide_in_left = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
Animation slide_out_right = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
viewSwitcher.setInAnimation(slide_in_left);
viewSwitcher.setOutAnimation(slide_out_right);
}
@OnClick(R.id.btn_switch)
void switchView() {
viewSwitcher.showNext();
}
}
package com.xiayutian.widgettest;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.ViewSwitcher;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ViewSwitcherActivity extends AppCompatActivity {
@BindView(R.id.btn_switch)
Button btnSwitch;
@BindView(R.id.view_switcher)
ViewSwitcher viewSwitcher;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_switcher_activity);
ButterKnife.bind(this);
initSwitcher();
}
private void initSwitcher() {
Animation slide_in_left = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
Animation slide_out_right = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
viewSwitcher.setInAnimation(slide_in_left);
viewSwitcher.setOutAnimation(slide_out_right);
/**
* 通过setFactory可以给ViewSwitcher添加两个基本相同的子view
*/
viewSwitcher.setFactory(() -> {
TextView textView = new TextView(ViewSwitcherActivity.this);
textView.setLayoutParams(new FrameLayout.LayoutParams(300,300));
textView.setBackgroundResource(R.color.colorAccent);
textView.setText("我是第一个文本");
return textView;
});
}
@OnClick(R.id.btn_switch)
void switchView() {
viewSwitcher.showNext();
/**
* 当viewSwitcher.getDisplayedChild() == 0时就是第一个子view,否者就是第二个子view
* 分别给他们设置不同的内容
*/
((TextView)viewSwitcher.getCurrentView()).setText(viewSwitcher.getDisplayedChild() == 0 ? "我是第一个文本" : "我是第二个文本");
}
}
ImageSwitcher是ViewSwitcher的子类,大多特性和ViewSwitcher一样,也可以当成一个ViewSwitcher使用。不过ImageSwicher添加setImageResource(@DrawableRes int resid),
setImageURI(Uri uri),setImageDrawable(Drawable drawable)等方法在切换到下一次时,同时也把要显示的图片资源设置。从下面的源码可以看出,调用这几个setImagexxx方法时,必须保证ImageSwitcher的子view是ImageView,否者程序无法正常运行。
public void setImageResource(@DrawableRes int resid)
{
ImageView image = (ImageView)this.getNextView();
image.setImageResource(resid);
showNext();
}
这个例子和前面的ViewSwitcher有点不一样,在这里给子view设置不同的图片资源,实现了一个图片轮播的场景。
package com.xiayutian.widgettest;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ImageSwitcherActivity extends AppCompatActivity {
@BindView(R.id.btn_next)
Button btnNext;
@BindView(R.id.image_switcher)
ImageSwitcher imageSwitcher;
private int position = 0;
private int[] images = {R.drawable.screen1, R.drawable.screen2, R.drawable.screen3, R.drawable.screen4,
R.drawable.screen5, R.drawable.screen6, R.drawable.screen7, R.drawable.screen8};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_switcher_activity);
ButterKnife.bind(this);
initSwitcher();
}
private void initSwitcher() {
Animation slide_in_left = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
Animation slide_out_right = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
imageSwitcher.setInAnimation(slide_in_left);
imageSwitcher.setOutAnimation(slide_out_right);
/**
* 通过setFactory可以给ViewSwitcher添加两个基本相同的子view
*/
imageSwitcher.setFactory(() -> {
ImageView imageView = new ImageView(ImageSwitcherActivity.this);
imageView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
imageView.setImageResource(images[0]);
return imageView;
});
}
@OnClick(R.id.btn_next)
void switchView() {
position++;
if (position > 7) {
position = 0;
}
imageSwitcher.setImageResource(images[position]);
}
}
TextSwitcher与ImageSwitcher基本相同,只是子view必须是TextView,然后有一个setText(CharSequence text)方法可以切换到下一个子view并设置文本内容。还有一点要注意的,从下面代码可以看出TextSwitcher限制更加严格,在添加子view的时候就必须是TextView,而ImageSwitcher只有在使用setImagexxx方法时才限制是ImageView,所以TextSwitcher不能当成普通的ViewSwitcher使用。
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (!(child instanceof TextView)) {
throw new IllegalArgumentException(
"TextSwitcher children must be instances of TextView");
}
super.addView(child, index, params);
}
ViewFlipper继承了ViewAnimator,主要区别在于它添加了一些方法和属性可以实现自动循环播放的效果。而且ViewFlipper和AdapterViewFlipper基本相似,区别在于ViewFlipper通过addView(View v)添加数据,而AdapterViewFlipper是通过设置adapter来实现数据配置。
关键xml属性
关键方法
package com.xiayutian.widgettest;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ViewFlipper;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ViewFlipperActivity extends AppCompatActivity {
@BindView(R.id.view_flipper)
ViewFlipper viewFlipper;
@BindView(R.id.btn_pre)
Button btnPre;
@BindView(R.id.btn_next)
Button btnNext;
@BindView(R.id.btn_start_or_stop)
Button btnStartOrStop;
private int[] images = {R.drawable.screen1, R.drawable.screen2, R.drawable.screen3, R.drawable.screen4,
R.drawable.screen5, R.drawable.screen6, R.drawable.screen7, R.drawable.screen8};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_flipper_activity);
ButterKnife.bind(this);
initViewFlipper();
}
private void initViewFlipper() {
Animation slide_in_left = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
Animation slide_out_right = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
viewFlipper.setInAnimation(slide_in_left);
viewFlipper.setOutAnimation(slide_out_right);
for (int resId : images) {
ImageView imageView = new ImageView(ViewFlipperActivity.this);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT));
imageView.setImageResource(resId);
viewFlipper.addView(imageView);
}
}
@OnClick(R.id.btn_pre)
void pre() {
viewFlipper.showPrevious();
}
@OnClick(R.id.btn_next)
void next() {
viewFlipper.showNext();
}
@OnClick(R.id.btn_start_or_stop)
void auto() {
if (viewFlipper.isFlipping()) {
viewFlipper.stopFlipping();
} else {
viewFlipper.startFlipping();
}
}
}