1. ViewAnimator相关
1.1 ViewAnimator的作用
在Android中,ViewAnimator是FrameLayout的一个子类,用来做Views之间的切换。它是一个变换控件的
元素,帮助我们在Views之间(如TextView, ImageView或者其他layout)添加变换。它有助于在屏幕view添加动画。ViewAnimator可以在两个及以上Views上平滑的切换,通过合适动画,提供从一个View到另外一个View变换的方式。
1.2 ViewAnimator及其子类关系继承图
1.3 常用的xml属性
XML属性 | 说明 |
---|---|
android:animateFirstView | 显示第一个View组件时是否使用动画 |
android:inAnimation | 显示子View组件时的动画 |
android:outAnimation | 隐藏子View组件时的动画 |
1.4 常用方法
- showNext() 这个方法用于展示ViewAnimator的下一个view。,viewanimator可以有两个或者更多的子视图,一次只显示一个子视图,所以这个方法用于展示下一个视图。
- showPrevious() 这个方法用于展示ViewAnimator的上一个view。viewanimator可以有两个或者更多的子视图,一次只显示一个子视图,所以这个方法用于展示上一个视图。
- setInAnimation(Animation inAnimation) 这个方法用于设置对象进入屏幕的动画。
- setOutAnimation(Animation outAnimation) 这个方法用于设置对象从屏幕上消失的动画
- addView(View child) 这个方法用于运行时在ViewAnimator添加view
- getCurrentView() 这个用于获取ViewAnimator当前显示的子view
- getDisplayedChild() 这个方法用于获取ViewAnimator当前显示的子View的索引,返回一个int值。
- getInAnimation() 此方法用于获取当前用于进入屏幕的View动画。
- getOutAnimation() 此方法用于获取当前用于退出屏幕的View动画。
- removeAllViews() 这个方法用于从ViewGroup移除所有的子view。
- removeView(View view) 这个方法用于移除ViewAnimator的子View。
- removeViewAt(int index) 这个用于移除在布局里特定位置的view。
- setDisplayedChild(int whichChild)这个方法用于设置在ViewAnimator显示的子View。
- setAnimateFirstView(boolean animate) 这个方法用于设置当前视图是否应在第一次显示ViewAnimator时进行动画。
- getAnimateFirstView()这个方法检查当前view是否在第一次viewanimator显示时进行动画。
1.5 代码示意
1.5.1 activity代码
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();
}
});
}
}
1.5.2 layout代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical">
<ViewAnimator
android:id="@+id/simpleViewAnimator"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ViewAnimator>
<Button
android:id="@+id/buttonNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="150dp"
android:background="#055"
android:text="NEXT"
android:textColor="#fff"
android:textStyle="bold" />
</LinearLayout>
2. ViewSwitcher相关
2.1 基本介绍
ViewSwitcher继承自ViewAnimator,代表了视图切换组件,大体上与ViewAnimator差不多。与ViewAnimator最大不同就是ViewSwitcher的子view最多只能有两个,多余两个将会报错。还有就是ViewSwitcher可以通过setFactory(ViewFactory factory)生成两个相同的子view,也可以通过addView(View view)方法添加子view。
2.2 代码示例
2.2.1 直接在xml添加子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();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="切换"/>
<ViewSwitcher
android:id="@+id/view_switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是第一个子View"
android:layout_gravity="center"
android:background="@color/colorAccent"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/screen2"/>
</ViewSwitcher>
</LinearLayout>
2.2.2 通过ViewFactory添加子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.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 ? "我是第一个文本" : "我是第二个文本");
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="切换" />
<ViewSwitcher
android:id="@+id/view_switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
3. ImageSwitcher相关
3.1 基本介绍
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();
}
3.2 代码示例
这个例子和前面的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]);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下一个" />
<ImageSwitcher
android:id="@+id/image_switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
4. TextSwitcher相关
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);
}
5. ViewFlipper相关
5.1 基本介绍
ViewFlipper继承了ViewAnimator,主要区别在于它添加了一些方法和属性可以实现自动循环播放的效果。而且ViewFlipper和AdapterViewFlipper基本相似,区别在于ViewFlipper通过addView(View v)添加数据,而AdapterViewFlipper是通过设置adapter来实现数据配置。
关键xml属性
- flipInterval 自动播放的事件间隔
- autoStart 是否自动播放
关键方法
- setFlipInterval(int milliseconds) 设置自动播放的时间间隔
- startFlipping() 开始自动播放
- stopFlipping() 停止播放
- isFlipping() 判断是否正在播放
- setAutoStart(boolean autoStart) 设置是否自动播放
- isAutoStart() 判断是否自动播放
5.2 代码示例
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();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewFlipper
android:id="@+id/view_flipper"
android:layout_width="0dp"
android:layout_height="0dp"
android:autoStart="true"
android:flipInterval="2000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btn_pre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上一个"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一个"
app:layout_constraintBottom_toBottomOf="@+id/view_flipper"
app:layout_constraintEnd_toEndOf="parent" />
<Button
android:id="@+id/btn_start_or_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始/停止"
app:layout_constraintBottom_toBottomOf="@+id/view_flipper"
app:layout_constraintEnd_toStartOf="@+id/btn_next"
app:layout_constraintStart_toEndOf="@+id/btn_pre" />
</androidx.constraintlayout.widget.ConstraintLayout>