敞开成长之旅!这是我参与「日新方案 2 月更文应战」的第 8 天,点击检查活动概况

前言

又没什么好的思路,还是随便写一些,所以这次就来整点活。
咱们都知道Activity的跳转具有默许的跳转动画,或许把这个默许的动画给取消,就会让跳转的作用让人觉得比较僵硬。那咱们能不能做出一些比较好的转场作用呢?本篇只介绍完成的思路,而不去深究某个思路的详细完成,由于有些知识点内容太多了,假如深入去看怕是很难一时半会讲明白。

Activity跳转动画

Activity是能够设置跳转动画的,有了动画之后,跳转的作用的体会就会比之前好一些。

我这儿先写两个动画,跳转时新页面进入的动画

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="0%"
        android:fromYDelta="0%"
        android:toYDelta="0%"
        android:duration="1000"/>
</set>

和旧页面退出的动画

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0%"
        android:toXDelta="-100%"
        android:fromYDelta="0%"
        android:toYDelta="0%"
        android:duration="1000"/>
</set>

然后在跳转时调用办法

Intent intent = new Intent(TwoActivity.this, ThreeActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.activity_start,R.anim.activity_end);

这样就能完成页面切换时的动画作用,可是要有一点需求注意,这个动画一定要合理,由于是动画展现完之后第二个页面才展现,假如你动画的逻辑触及得不合理,会出现动画完毕之后再展现第二个页面这个进程会显得很僵硬。

可是假如仅仅只有页面切换的动画,还是觉得差点意思。这时分就需求发挥自己想象力了。我这儿能够用一个自定义View和这个动画进行联动,让他们看起来是一个全体的作用。

比方我这样写一个View

<RelativeLayout
    android:id="@+id/btn"
    android:layout_width="120dp"
    android:layout_height="60dp"
    android:background="@drawable/test_start"
    android:layout_alignParentEnd="true"
    android:layout_marginTop="50dp"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="下一步"
        android:layout_centerInParent="true"
        android:textColor="#ffff"
        />
</RelativeLayout>

设置一个布景,色彩和第二个页面的色彩相同

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!--布景色彩-->
    <solid android:color="@color/jh_blue" />
    <corners
        android:topLeftRadius="100dp"
        android:bottomLeftRadius="100dp"
        />
</shape>

最终会议现出这样的作用

Android浅谈转场效果

同享元素

在5.0之后,android供给了同享元素的完成。Material Design刚出来的时分我还没毕业,我觉得现在回去看它的这个思想和一些内容,的确能有一些其它的收成,这个概念的提出的确牛逼。

同享元素简略来说作用便是你两个页面之间的跳转,设置了同享的元素会做个动画,会让人感觉是这个页面的View做了一个动画移动到另一个页面,表现出现的作用就很好。

那已然作用好,为什么不普遍运用呢?我觉得有两个原因,第一个是之前不像现在相同根本都是5.0以上的手机,之前要对4.4做适配,然后开发中,没那方面的需求,自然也不会往那个方向去想,甚至都不知道Android有供给这个东西。第二个原因是好用是好用,相对的坑也多。

能够先看看如何完成,我这儿写个简略点的Demo,首先在第一个页面创立一个view

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    >
    <ImageView
        android:id="@+id/iv_test"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_marginTop="500dp"
        android:src="@drawable/aaaaa"
        android:transitionName="test"
        />
</RelativeLayout>

看到这儿有个特点transitionName,这个便是定义同享元素,然后在第二个页面也创立一个view

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/blue"
    android:gravity="center_horizontal"
    >
    <ImageView
        android:id="@+id/iv_test"
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:layout_marginTop="20dp"
        android:src="@drawable/aaaaa"
        android:transitionName="test"
        />
</RelativeLayout>

看到他们的transitionName是相同的,然后在跳转时用ActivityOptions.makeSceneTransitionAnimation就行了,详细的它已经里边帮你封装好了

ImageView imageView = findViewById(R.id.iv_test);
imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(TwoActivity.this, ThreeActivity.class);
        Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(TwoActivity.this, imageView, "test")
                .toBundle();
        startActivity(intent, bundle);
    }
});

就这么简略,其间要注意的是你页面的style假如是用Material的style就没什么问题,但假如不是,你就需求在你的style中设置

<item name="android:windowActivityTransitions">true</item>

当然也能够在代码中动态设置

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

最终的作用便是这样的

Android浅谈转场效果

这个动画作用是默许的,假如你要自己完成,就需求自己去写transition,比方我这儿这样设置时间

<fade xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    />
<style name="test_style" parent="android:Theme.NoTitleBar.Fullscreen">
    <item name="android:windowActivityTransitions">true</item>
    <item name="android:windowEnterTransition">@transition/activity_fade</item>
    <item name="android:windowExitTransition">@transition/activity_fade</item>
</style>

它其实功用很庞大,相同的坑也会许多。我这儿就不往下说了,前面也说了,这篇文章主要是写个思路,你要是能把它玩好了,就和自定义view相同,特点动画相同,想完成什么作用,就完成什么作用,我也不常用,对这个技术点也仅仅入门。

通过window去完成

这个思路是在activity上方有个图层,图层中有个view和下方图层的view的大小和方位相同,然后去改上图层的view。此刻假如下图层做跳转,也不会影响,便是能完成和上面同享元素相同的作用。可是我曾经用的window是系统等级的window,所以能完成作用,其它等级的不知道会不会有问题,得开发时分详细调试才知道,总之主要看思路,先不必在意细节。

还是用一个Demo来举例,先写Activity的页面,两个textview是用做标识看作用的

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    >
    <ImageView
        android:id="@+id/iv_test"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_marginTop="500dp"
        android:src="@drawable/aaaaa"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="在图片上方"
        android:layout_marginTop="480dp"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="在图片下方"
        android:layout_below="@+id/iv_test"
        />
</RelativeLayout>

再写window的布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    >
    <ImageView
        android:id="@+id/iv_test"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_marginTop="500dp"
        android:src="@drawable/aaaaa"
        />
</RelativeLayout>

能够看到两个view的初始方位和大小都相同,然后看看详细的完成

public class TwoActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_two);
        ImageView imageView = findViewById(R.id.iv_test);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playWindow();
            }
        });
    }
    private void playWindow() {
        RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.test_window, null);
        View windowView = relativeLayout.findViewById(R.id.iv_test);
        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
                , PixelFormat.RGBA_8888);
        windowManager.addView(relativeLayout, wlp);
        windowView.post(new Runnable() {
            @Override
            public void run() {
                start(windowView);
            }
        });
    }
    private void start(final View view) {
        int w = view.getWidth();
        int h = view.getHeight();
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 300);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int v = (int) animation.getAnimatedValue();
                RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) view.getLayoutParams();
                rlp.width = w + v;
                rlp.height = h + v;
                view.setLayoutParams(rlp);
                view.invalidate();
            }
        });
        valueAnimator.setDuration(700).start();
    }
}

demo里边我为了方便用了TYPE_APPLICATION,但实践我这边开发用的是FIRST_SYSTEM_WINDOW以上的系统层级弹窗。

然后咱们来看看最终的作用

Android浅谈转场效果

这儿是做了个扩大的作用,但实践你能够扩大后跳转Activity然后移动方位,再缩小,就有无缝转场的作用,其实和上面的同享元素的作用类似。

总结

能完成转场的方式许多,不必拘束于调用原生的办法,比方假如真依赖原生供给的办法,要是真要适配5.0以下的怎么做?最重要的是要发挥自己的想象力,去考虑。当然,这个原生供给的系统的确也有许多学问在里边,想要玩得登峰造极,也是需求不断的去测验,不断的去踩坑。