概要
在使用您的应用程序时,需要在屏幕上显示新信息,同时删除旧信息。立即切换显示的内容可能会显得很刺耳,或者用户可能很容易错过屏幕上的新内容。利用动画可以减缓变化并以概念吸引用户的眼球,因此更新更加明显。
显示或隐藏视图时使用三种常用动画。您可以使用圆形透视动画,交叉淡入淡出动画或卡片式动画。
创建一个淡入淡出动画
交叉淡化动画(也称为“溶解”)会逐渐淡出View或ViewGroup同时淡入另一个淡入淡出。此动画适用于您想在应用中切换内容或视图的情况。此处显示的淡入淡出动画使用ViewPropertyAnimator了Android 3.1(API级别12)及更高版本。
以下是从进度指示器到某些文本内容的交叉淡入淡出示例。
交叉淡入淡出动画 视频地址
创建视图
首先,你需要创建你想交叉淡入淡出的两个视图。以下示例创建一个进度指示器和一个可滚动文本视图:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum"
android:padding="16dp" />
</ScrollView>
<ProgressBar android:id="@+id/loading_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
设置交叉淡入淡出动画
要设置交叉淡入淡出动画:
- 为要交叉淡入淡出的视图创建成员变量。稍后在动画期间修改视图时需要这些参考。
- 对于正在淡入的视图,请将其可见性设置为GONE。这样可以防止视图占用布局空间并从布局计算中省略布局空间,加快处理速度。
- 将config_shortAnimTime 系统属性缓存在成员变量中。该属性为动画定义了一个标准的“短”持续时间。此持续时间对于频繁发生的微妙动画或动画非常理想。config_longAnimTime而 config_mediumAnimTime如果你想使用它们也是可用的
以下是使用前面的代码片段中的布局作为活动内容视图的示例:
public class CrossfadeActivity extends Activity {
private View mContentView;
private View mLoadingView;
private int mShortAnimationDuration;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crossfade);
mContentView = findViewById(R.id.content);
mLoadingView = findViewById(R.id.loading_spinner);
// Initially hide the content view.
mContentView.setVisibility(View.GONE);
// Retrieve and cache the system's default "short" animation time.
mShortAnimationDuration = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}
...
}
交叉淡化观点
现在视图已正确设置,通过执行以下操作交叉淡入淡出:
- 对于淡入的视图,请将alpha值设置为,0并将其可见性设置为VISIBLE。(请记住,它最初设置为GONE。)这使视图可见,但完全透明。
- 对于淡入的视图,将其alpha值设置为0to 1。对于正在淡出的视图,请将1to 的alpha值动画化0。
- onAnimationEnd() 在an中使用Animator.AnimatorListener,设置淡出的视图的可见性GONE。即使alpha值是0,设置视图的可见性以GONE防止视图占用布局空间并从布局计算中省略,从而加快处理速度。
以下方法显示了如何执行此操作的示例:
public class CrossfadeActivity extends Activity {
private View mContentView;
private View mLoadingView;
private int mShortAnimationDuration;
...
private void crossfade() {
// Set the content view to 0% opacity but visible, so that it is visible
// (but fully transparent) during the animation.
mContentView.setAlpha(0f);
mContentView.setVisibility(View.VISIBLE);
// Animate the content view to 100% opacity, and clear any animation
// listener set on the view.
mContentView.animate()
.alpha(1f)
.setDuration(mShortAnimationDuration)
.setListener(null);
// Animate the loading view to 0% opacity. After the animation ends,
// set its visibility to GONE as an optimization step (it won't
// participate in layout passes, etc.)
mLoadingView.animate()
.alpha(0f)
.setDuration(mShortAnimationDuration)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mLoadingView.setVisibility(View.GONE);
}
});
}
}
创建一个卡片翻转动画
通过显示模拟卡片翻转的动画,卡片在内容视图之间翻转为动画。此处显示的卡片翻转动画使用FragmentTransaction了Android 3.0(API级别11)及更高版本。
以下是一张翻转卡的外观:
效果视频
创建Animator对象
为了创建卡片翻转动画,您总共需要四位动画师。两张动画卡片用于卡片正面向左和向左以及向左和向右的动画。您还需要两名动画师,以便卡片的背面从右向右进行动画处理。
card_flip_left_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="-180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Half-way through the rotation (see startOffset), set the alpha to 1. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
card_flip_left_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Half-way through the rotation (see startOffset), set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
card_flip_right_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Half-way through the rotation (see startOffset), set the alpha to 1. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
card_flip_right_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="-180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Half-way through the rotation (see startOffset), set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
创建视图
“卡片”的每一面都是一个单独的布局,可以包含您想要的任何内容,例如两个文本视图,两个图像或任意视图组合之间的翻转。然后,您将在片段中使用稍后设置动画的两个布局。以下布局创建显示文字的卡片的一面:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#a6c"
android:padding="16dp"
android:gravity="bottom">
<TextView android:id="@android:id/text1"
style="?android:textAppearanceLarge"
android:textStyle="bold"
android:textColor="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_title" />
<TextView style="?android:textAppearanceSmall"
android:textAllCaps="true"
android:textColor="#80ffffff"
android:textStyle="bold"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_description" />
</LinearLayout>
卡的另一面显示ImageView:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image1"
android:scaleType="centerCrop"
android:contentDescription="@string/description_image_1" />
创建片段
为卡的正面和背面创建片段类。这些类将返回之前在onCreateView()每个片段的方法中创建的布局。然后,您可以在要显示该卡片的父级活动中创建此片段的实例。以下示例显示使用它们的父活动内部的嵌套片段类:
public class CardFlipActivity extends Activity {
...
/**
* A fragment representing the front of the card.
*/
public class CardFrontFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_card_front, container, false);
}
}
/**
* A fragment representing the back of the card.
*/
public class CardBackFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_card_back, container, false);
}
}
}
动画卡片翻转
现在,您需要在父活动中显示片段。为此,请首先为您的活动创建布局。以下示例创建一个FrameLayout可以在运行时添加片段的示例 :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在活动代码中,将内容视图设置为您刚刚创建的布局。在创建活动时显示默认片段也是一个好主意,因此以下示例活动显示默认情况下如何显示卡片的正面:
public class CardFlipActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_card_flip);
if (savedInstanceState == null) {
getFragmentManager()
.beginTransaction()
.add(R.id.container, new CardFrontFragment())
.commit();
}
}
...
}
现在您已经显示了卡的正面,您可以在适当的时候用翻转动画显示卡的背面。创建一个方法来显示卡的另一面,它执行以下操作:
- 设置您之前为片段转换创建的自定义动画。
- 用新片段替换当前显示的片段,并使用您创建的自定义动画为此事件设置动画。
- 将之前显示的片段添加到片段返回堆栈,以便当用户按下后退按钮时,卡片翻转回来。
public class CardFlipActivity extends Activity {
...
private void flipCard() {
if (mShowingBack) {
getFragmentManager().popBackStack();
return;
}
// Flip to the back.
mShowingBack = true;
// Create and commit a new fragment transaction that adds the fragment for
// the back of the card, uses custom animations, and is part of the fragment
// manager's back stack.
getFragmentManager()
.beginTransaction()
// Replace the default fragment animations with animator resources
// representing rotations when switching to the back of the card, as
// well as animator resources representing rotations when flipping
// back to the front (e.g. when the system Back button is pressed).
.setCustomAnimations(
R.animator.card_flip_right_in,
R.animator.card_flip_right_out,
R.animator.card_flip_left_in,
R.animator.card_flip_left_out)
// Replace any fragments currently in the container view with a
// fragment representing the next page (indicated by the
// just-incremented currentPage variable).
.replace(R.id.container, new CardBackFragment())
// Add this transaction to the back stack, allowing users to press
// Back to get to the front of the card.
.addToBackStack(null)
// Commit the transaction.
.commit();
}
}
创建一个圆形显示动画
显示或隐藏一组UI元素时,显示动画为用户提供视觉连续性。该ViewAnimationUtils.createCircularReveal()方法使您可以动画剪辑圈以显示或隐藏视图。此类动画在ViewAnimationUtils课程中提供, 适用于Android 5.0(API级别21)及更高版本。
以下是显示如何显示以前不可见视图的示例:
// previously invisible view
View myView = findViewById(R.id.my_view);
// Check if the runtime version is at least Lollipop
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the final radius for the clipping circle
float finalRadius = (float) Math.hypot(cx, cy);
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
} else {
// set the view to visible without a circular reveal animation below Lollipop
myView.setVisibility(View.VISIBLE);
}
该ViewAnimationUtils.createCircularReveal()动画有五个参数。第一个参数是您要隐藏或显示在屏幕上的视图。接下来的两个参数是裁剪圆中心的x和y坐标。通常这将是视图的中心,但您也可以使用用户触摸的点,以便动画从他们所选的位置开始。第四个参数是剪切圆的起始半径。
在上例中,初始半径设置为0,因此要显示的视图将被圆圈隐藏。最后一个参数是圆的最终半径。在显示视图时,请确保最终半径大于视图本身,以便在动画完成之前完全显示视图。
隐藏以前可见的视图:
// previously visible view
final View myView = findViewById(R.id.my_view);
// Check if the runtime version is at least Lollipop
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the initial radius for the clipping circle
float initialRadius = (float) Math.hypot(cx, cy);
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
} else {
// set the view to visible without a circular reveal animation below Lollipop
myView.setVisibility(View.VISIBLE);
}
在这种情况下,剪切圆的初始半径设置为与视图一样大,以便在动画开始之前视图将可见。最终半径设置为0,以便动画结束时隐藏视图。向动画添加侦听器非常重要,以便INVISIBLE在动画完成时将视图的可见性设置为。
Lastest Update:2018.04.23
联系我
QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ
公众号推荐:
转载于:https://blog.51cto.com/4789781/2120975