1. 程式人生 > >Android頁面翻轉動畫(模仿CSDN賬號登入的翻轉效果)

Android頁面翻轉動畫(模仿CSDN賬號登入的翻轉效果)

昨天下載了CSDN的APP,進入多種方式選擇登入的頁面,然後我選擇用CSDN賬號登入,發現有頁面翻轉的效果進入登入頁面。瞬時感覺好炫,自己感覺效果很好。平時別的APP登入的時候,就是直接進入登入頁面,沒有任何效果。這次看到旋轉的效果,頓時眼前一亮,所以我就研究了一下,想做個類似的效果。這邊我主要用了兩個Fragment和自定義的動畫效果。下面上幾張圖,按照CSDN登入UI做的,UI做的比較粗糙,可還能將就看。

                                               多種方式選擇登入介面

點選CSDN賬號登入後的旋轉介面,(因為不會用動畫展示,只能截圖看看了)

                                                                        登入介面


接下來,我們開始這個Android程式的建立。

第一步,新建民名為RotationLoginDemo的Android專案,從圖我們可以看到翻轉前後有兩個介面,那麼這兩個介面從用什麼做的呢?我不知道他們是怎麼實現的,這裡我用了兩個Fragment,分別為SelectLoginFragment和LoginFragment。接著就開始建這兩個Fragment所對應的佈局檔案fragment_select_login和fragment_login,下面的就是這兩個佈局檔案的程式碼。

fragment_select_login.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/layout_bottom" >

        <LinearLayout
            android:id="@+id/text_sdn"
            android:layout_width="match_parent"
            android:layout_height="80dip"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="horizontal" >

            <TextView
                android:id="@+id/text_c"
                android:layout_width="wrap_content"
                android:layout_height="80dip"
                android:gravity="center"
                android:text="C "
                android:textColor="#CC0000"
                android:textSize="60sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="80dip"
                android:gravity="center"
                android:text="S D N"
                android:textColor="#000000"
                android:textSize="60sp" />
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dip"
            android:layout_below="@id/text_sdn"
            android:gravity="center"
            android:text="全 球 最 大 的 中 文 IT 社 區"
            android:textColor="#000000"
            android:textSize="20sp" />
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/layout_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"
        android:paddingLeft="10dip"
        android:paddingRight="10dip" >

        <Button
            android:id="@+id/btn_csdn_login"
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="match_parent"
            android:layout_height="50dip"
            android:background="@drawable/bg_btn"
            android:text="CSDN賬號登入"
            android:textColor="#666666"
            android:textSize="16sp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dip"
            android:orientation="horizontal" >

            <Button
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="0dip"
                android:layout_height="40dip"
                android:layout_marginRight="10dip"
                android:layout_weight="1"
                android:background="@drawable/bg_btn"
                android:text="微博"
                android:textColor="#666666"
                android:textSize="16sp" />

            <Button
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="0dip"
                android:layout_height="40dip"
                android:layout_marginRight="10dip"
                android:layout_weight="1"
                android:background="@drawable/bg_btn"
                android:text="微信"
                android:textColor="#666666"
                android:textSize="16sp" />

            <Button
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="0dip"
                android:layout_height="40dip"
                android:layout_weight="1"
                android:background="@drawable/bg_btn"
                android:text="QQ"
                android:textColor="#666666"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dip"
                android:layout_marginTop="30dip"
                android:gravity="center"
                android:text="建立賬號"
                android:textColor="#666666"
                android:textSize="16sp" />
        </LinearLayout>
    </LinearLayout>

</RelativeLayout>


fragment_login.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:orientation="vertical"
    android:padding="16dp" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/text_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="取消"
            android:textColor="#000000"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_gravity="center_horizontal"
            android:lineSpacingMultiplier="1.2"
            android:text="登入"
            android:textColor="#000000"
            android:textSize="18sp"
            android:textStyle="bold" />
    </RelativeLayout>

    <EditText
        style="@android:style/Widget.TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dip"
        android:background="@null"
        android:hint="輸入使用者名稱"
        android:textSize="16sp" />

    <EditText
        style="@android:style/Widget.TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="30dip"
        android:layout_marginTop="10dip"
        android:background="@null"
        android:hint="輸入密碼"
        android:textSize="16sp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_btn"
        android:text="登 錄" />

</LinearLayout>
第二步,自定義動畫:

在res資料夾下新建檔名為animator,下面具體結構如下圖:

下面為四個動畫的xml的程式碼:

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="1000" />

    <!-- 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="500"
        android:duration="1" />
</set>

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="1000" />

    <!-- 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="500"
        android:duration="1" />
</set>

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="1000" />

    <!-- 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="500"
        android:duration="1" />
</set>

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="1000" />

    <!-- 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="500"
        android:duration="1" />
</set>

第三步,建立Activity
package com.example.rotationcarddemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;

@SuppressLint("NewApi")
public class MainActivity extends Activity implements FragmentManager.OnBackStackChangedListener
{

    private boolean mShowingBack = false;
    private int left_in = R.animator.left_in;
    private int left_out = R.animator.left_out;
    private int right_in = R.animator.right_in;
    private int right_out = R.animator.right_out;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        
        //判斷<span style="font-family: Arial, Helvetica, sans-serif;">savedInstanceState 是否為null,如果為null,則說明這是建立的全新的物件,如果不為null,則是重建上一次銷燬的物件</span>
        if (savedInstanceState == null)
        {
            getFragmentManager().beginTransaction().add(R.id.container, new SelectLoginFragment())
                    .commit();
        }
        else
        {
            mShowingBack = getFragmentManager().getBackStackEntryCount() > 0;
        }
        getFragmentManager().addOnBackStackChangedListener(this);
    }

    /**
     * 選擇登入方式介面
     */
    public class SelectLoginFragment extends Fragment
    {

        public SelectLoginFragment()
        {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                @Nullable Bundle savedInstanceState)
        {
            View rootView = (View) inflater.inflate(R.layout.fragment_select_login, container,
                    false);

            rootView.findViewById(R.id.btn_csdn_login).setOnClickListener(new OnClickListener()
            {

                @Override
                public void onClick(View v)
                {
                    AnimationRotate(new LoginFragment(), left_in, left_out, right_in, right_out);
                }
            });
            return rootView;
        }
    }

    /**
     * 登入頁面
     */
    public class LoginFragment extends Fragment
    {

        public LoginFragment()
        {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                @Nullable Bundle savedInstanceState)
        {
            View rootView = (View) inflater.inflate(R.layout.fragment_login, container, false);
            rootView.findViewById(R.id.text_cancel).setOnClickListener(new OnClickListener()
            {

                @Override
                public void onClick(View v)
                {
                    AnimationRotate(new SelectLoginFragment(), right_in, right_out, left_in,
                            left_out);
                }
            });
            return rootView;
        }
    }

    /**
     * 旋轉動畫
     */
    private void AnimationRotate(Fragment fragment, int x, int y, int z, int f)
    {
        if (mShowingBack)
        {
            getFragmentManager().popBackStack();
            return;
        }
        mShowingBack = true;

        getFragmentManager().beginTransaction().setCustomAnimations(x, y, z, f)
                .replace(R.id.container, fragment).addToBackStack(null).commit();
    }

    @Override
    public void onBackStackChanged()
    {
        mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
    }
}