首页 > 代码库 > MaterialDesign设计(下)

MaterialDesign设计(下)

1.转场动画

Android开发过程中提供了一系列的新的过场动画,在旧版本里面,我们切换Activity大多都是使用下面这个api:

overridePendingTransition(enterAnim, exitAnim); 

1.新版本的动画提供了类似的功能,动画效果更加柔顺,代码如下:

ActivityOptionsCompat optionsCompat=ActivityOptionsCompat
        .makeCustomAnimation(this,R.anim.enter_anim,R.anim.exit_anim);
Intent intent=new Intent(this,SecondActivity.class);
ActivityCompat.startActivity(this,intent,optionsCompat.toBundle());

2.还可以从某个控件开始慢慢放大到完全展示新的界面,代码如下:

    ActivityOptionsCompat optionsCompat=ActivityOptionsCompat
        .makeScaleUpAnimation(v,v.getWidth()/2,v.getHeight()/2,0,0);
    Intent intent=new Intent(this,SecondActivity.class);
    ActivityCompat.startActivity(this,intent,optionsCompat.toBundle());

该创建的代码为:

makeScaleUpAnimation (View source, int startX,int startY, int width,int height) 

新的activity产生一个缩放的动画,这个动画的起点是,相对于source这个View 的左上角偏移(startX,startY)位置产生一个动画,新的activity的初始宽度和高度是width 和 height,0为新界面的全屏展示。

3.当然我们也可以通过将某个图片放大至全屏,然后打开新的界面:

BitmapDrawable bmp = (BitmapDrawable) ((ImageView) v).getDrawable();
ActivityOptionsCompat optionsCompat=
        ActivityOptionsCompat
                .makeThumbnailScaleUpAnimation(v,bmp.getBitmap(),0,0);
Intent intent=new Intent(this,SecondActivity.class);
ActivityCompat.startActivity(this,intent,optionsCompat.toBundle());

4.Android5.0后还提供了一个场景转换动画,废话不多说,看效果:

技术分享

首先要给三个按钮一个设置统一的点击事件,代码如下:

BitmapDrawable bmp = (BitmapDrawable) ((ImageView) v).getDrawable();
ActivityOptionsCompat optionsCompat=
        ActivityOptionsCompat
                .makeSceneTransitionAnimation(this,v,"img");
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("img",bmp.getBitmap());
ActivityCompat.startActivity(this,intent,optionsCompat.toBundle());

这里有必要解释下makeSceneTransitionAnimation方法,该方法的第2个参数指定需要从哪个View开始慢慢放大。第三个参数就是新界面的字符串标识,也就是新的SecondActivity布局中 有这样的标签属性transitionName:

<ImageView
    android:id="@+id/iv"
    ...
    android:transitionName="img"  />

在新的SecondActivity中,拿到传过来的数据进行显示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT>=21){
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    }
    setContentView(R.layout.activity_second);

    Bitmap bmp=(Bitmap) getIntent().getParcelableExtra("img");
    ImageView iv = (ImageView) findViewById(R.id.iv);
    iv.setImageBitmap(bmp);
}

除了可以分享2个界面中的同一元素,还可以分享多个控件元素。该操作基于makeSceneTransitionAnimation的另一个方法:

makeSceneTransitionAnimation(Activity activity,Pair<View, String>... sharedElements)

该效果是这样的:

技术分享

首先给2个图片控件添加一个点击事件,并调用如下代码:

//第一个参数指定前一个场景的控件   第二个参数指定下一个场景的控件名称
Pair<View, String> a1 = Pair.create(findViewById(R.id.a1), "a1");
Pair<View, String> a4 = Pair.create(findViewById(R.id.a4), "a4");
ActivityOptionsCompat optionsCompat=
        ActivityOptionsCompat
                .makeSceneTransitionAnimation(this,a1,a4);
Intent intent=new Intent(this,SecondActivity.class);
ActivityCompat.startActivity(this,intent,optionsCompat.toBundle());

新界面的布局如下:

<?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" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:transitionName="a4"
        android:src="http://www.mamicode.com/@drawable/a4" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:transitionName="a1"
        android:src="http://www.mamicode.com/@drawable/a1" />

</LinearLayout>

第2个界面中,为了让界面支持转场动画,代码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT>=21){
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    }
    setContentView(R.layout.activity_second);

}

2.场景动画

技术分享

比如上面的动画,如果我们要实现该效果,就需要创建两个平移动画 写起来特别麻烦。不过我们可以使用21版本的场景动画来代替,只需要创建2个不同的场景就可以完成此事。

技术分享

并且 第一次加载左边图片的时候 需要在容器中指定id.

<RelativeLayout 
        ...
    android:id="@+id/root_view" />

假如第一个布局叫activity_one 第二个布局叫activity_two 那么变换场景的代码可以这么写:

if (Build.VERSION.SDK_INT>=21){
    mRootView = (ViewGroup) findViewById(R.id.root_view);
    Scene scene = Scene
            .getSceneForLayout(mRootView, R.layout.activity_two, this);
    //ChangeBounds指定了变化过程中的动画
    TransitionManager.go(scene,new ChangeBounds());
}

上面的代码靠的是TransitionManager的go方法。而如果你不添加ChangeBounds对象。动画是不会产生的。

Scene的创建也很简单 第一个参数指定需要更改布局的容器,第二个参数指定新的布局文件。

实际上TransitionManager还提供了另一个方法操作动画,下面一个小Demo展示:

技术分享

其代码如下:

if (Build.VERSION.SDK_INT>=21){
    mRootView = (ViewGroup) findViewById(R.id.root_view);
     //指定该mRootView父容器下子控件变化的动画
    TransitionManager.beginDelayedTransition(mRootView,new Slide(Gravity.TOP));
    findViewById(R.id.a5).setVisibility(View.GONE);
 }

通过beginDelayedTransition指定我们要监听布局的容器。只要该该容器下的子控件改变了(比如某个控件不见了/某个控件大小变化/位移改变了),就会执行Slide动画。

其可以指定的动画还有很多种 都在android.transition包下:

技术分享

常见的Transition如下:
1. Slide 划入
2. Explode 爆炸
2. Fade 隐藏
2. changeBounds 位置与大小变化

3.Activity与Transition动画配置

技术分享

以上就是将Transition与Activity跳转相互嵌套而成的动画,对于第一个界面来说 要实现一个所有子控件向外爆炸(Explode)的退出动画,对于第二个界面需要实现一个向右滑动(Slide)的进场动画。

既然要配置动画,当然可以使用代码来配置,也可以使用xml文件来配置。我们让第一个动画使用代码来配置,第二个动画使用xml来配置。

退出的动画

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT>=21){
        //创建一个爆炸动画
        Explode explode=new Explode();
        explode.setDuration(1500);
        //对TRANSITIONS转场动画的支持
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        //设置退出动画的效果
        getWindow().setExitTransition(explode);
    }
    setContentView(R.layout.activity_one);
    findViewById(R.id.a4).setOnClickListener(this);
    findViewById(R.id.a5).setOnClickListener(this);
}

@Override
public void onClick(View v) {
    Intent intent=new Intent(this,SecondActivity.class);
    //5.0以后才支持
    if (Build.VERSION.SDK_INT>=21){
        startActivity(intent,
                ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle());
    }else{
        startActivity(intent);
    }
}

注意上面的代码需要使用ActivityOptionsCompat.makeSceneTransitionAnimation(this)来实现转场动画,后面的参数可以不传递,因为我们不用分享转场的元素 动画在onCreate()中已经指定了.

进场动画

接下来在新的界面中,使用xml来配置从右向左滑动的进场动画。transition动画的xml配置需要在res 下创建一个transition文件夹。并在内部创建一个文件。该文件我命名为enter_anim.xml:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000" >
    <fade android:interpolator="@android:interpolator/accelerate_decelerate"/>
    <slide android:slideEdge="right" />
</transitionSet>

transitionSet标签类似补间动画的set标签。内部的标签大概有fade渐变标签,slide滑动标签,changebounds标签,explode标签等。至于其标签的属性很可能工具没提示哈。这里我以slide抛砖引玉。直接找到官网查找Slide,每个类大概都有提示:

技术分享

其代码引用如下:

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT>=21){
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        Transition transition = TransitionInflater.from(this)
                         .inflateTransition(R.transition.enter_anim);
            getWindow().setEnterTransition(transition);
        }
        setContentView(R.layout.activity_second);
    }
}

4.波纹动画

技术分享

首先我们可以在布局文件中创建一个播放动画的容器和一个按钮。

接着当点击按钮的时候执行如下代码:

if (Build.VERSION.SDK_INT>=21){
   //View view 对哪个控件实现波纹动画
   //int centerX,  int centerY 启动动画的起始坐标 相对于上面的view
   //float startRadius, float endRadius 开始&结束的半径
   Animator animator = ViewAnimationUtils
           .createCircularReveal(mContainer, 0, 0, 0, 800);
   animator.setDuration(1500);
   //默认动画如果没设置背景 是看不出效果的
   mContainer.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_bright));
   animator.start();
}


:) 本文由小码哥教育Android学院提供,谢绝转载

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    MaterialDesign设计(下)