android-卡片旋轉特效


 直接看圖:

 

實現此功能,會用到屬性動畫;

但是具體做起來,有兩種途徑:

1)純java代碼來寫:

  1 package com.example.cardrotation;
  2 
  3 import android.animation.Animator;
  4 import android.animation.AnimatorListenerAdapter;
  5 import android.animation.AnimatorSet;
  6 import android.animation.ObjectAnimator;
  7 import android.os.Bundle;
  8 import android.support.v7.app.AppCompatActivity;
  9 import android.view.View;
 10 import android.widget.FrameLayout;
 11 
 12 /**
 13  * 旋轉卡片特效
 14  * 第1種寫法
 15  * <p>
 16  * 用純java代碼來寫動畫特效以及 執行動畫
 17  */
 18 public class MainActivity2 extends AppCompatActivity {
 19 
 20     private FrameLayout mFlCardBack, mFlCardFront, mFlContainer;
 21 
 22     @Override
 23     protected void onCreate(Bundle savedInstanceState) {
 24         super.onCreate(savedInstanceState);
 25         setContentView(R.layout.activity_main);
 26 
 27         mFlCardBack = findViewById(R.id.fl_back);
 28         mFlCardFront = findViewById(R.id.fl_front);
 29         mFlContainer = findViewById(R.id.main_fl_container);
 30         mFlContainer.setOnClickListener(new View.OnClickListener() {
 31             @Override
 32             public void onClick(View v) {
 33                 flipCard();
 34             }
 35         });
 36 
 37         initAnimatorSet();
 38         setCameraDistance(); // 設置鏡頭距離
 39     }
 40 
 41     // 改變視角距離, 貼近屏幕,這個必須設置,因為如果不這么做,沿着Y軸旋轉的過程中有可能產生超出屏幕的3D效果。
 42     private void setCameraDistance() {
 43         int distance = 16000;
 44         float scale = getResources().getDisplayMetrics().density * distance;
 45         mFlCardFront.setCameraDistance(scale);
 46         mFlCardBack.setCameraDistance(scale);
 47     }
 48 
 49     private boolean mIsShowBack = false;
 50 
 51     // 翻轉卡片
 52     public void flipCard() {
 53         // 正面朝上
 54         if (!mIsShowBack) {
 55             inSet.setTarget(mFlCardBack);
 56             outSet.setTarget(mFlCardFront);
 57             mIsShowBack = true;
 58         } else { // 背面朝上
 59             inSet.setTarget(mFlCardFront);
 60             outSet.setTarget(mFlCardBack);
 61             mIsShowBack = false;
 62         }
 63         inSet.start();
 64         outSet.start();
 65     }
 66 
 67     AnimatorListenerAdapter animatorListenerAdapter = new AnimatorListenerAdapter() {
 68         @Override
 69         public void onAnimationStart(Animator animation) {
 70             super.onAnimationStart(animation);
 71             mFlContainer.setClickable(false);//在動畫執行過程中,不許允許接收點擊事件
 72         }
 73 
 74         @Override
 75         public void onAnimationEnd(Animator animation) {
 76             super.onAnimationEnd(animation);
 77             mFlContainer.setClickable(true);//在動畫執行過程中,不許允許接收點擊事件
 78         }
 79     };
 80 
 81     private AnimatorSet inSet, outSet;
 82 
 83     private void initAnimatorSet() {
 84         inSet = new AnimatorSet();
 85         ObjectAnimator animator = ObjectAnimator.ofFloat(null, "rotationY", -180f, 0f);
 86         animator.setDuration(500);
 87         animator.setStartDelay(0);
 88         ObjectAnimator animator2 = ObjectAnimator.ofFloat(null, "alpha", 0.0f, 1f);
 89         animator2.setStartDelay(250);
 90         animator2.setDuration(0);
 91         inSet.playTogether(animator, animator2);
 92         inSet.addListener(animatorListenerAdapter);
 93 
 94         outSet = new AnimatorSet();
 95         ObjectAnimator animator_ = ObjectAnimator.ofFloat(null, "rotationY", 0, 180f);
 96         animator_.setDuration(500);
 97         animator_.setStartDelay(0);
 98         ObjectAnimator animator2_ = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
 99         animator2_.setStartDelay(250);
100         animator2_.setDuration(0);
101         outSet.playTogether(animator_, animator2_);
102         outSet.addListener(animatorListenerAdapter);
103     }
104 
105 }

 

2) 用 animator.xml來配置動畫特效,然后在java代碼中執行動畫

 1 package com.example.cardrotation;
 2 
 3 import android.animation.Animator;
 4 import android.animation.AnimatorInflater;
 5 import android.animation.AnimatorListenerAdapter;
 6 import android.animation.AnimatorSet;
 7 import android.support.v7.app.AppCompatActivity;
 8 import android.os.Bundle;
 9 import android.view.View;
10 import android.widget.FrameLayout;
11 
12 /**
13  * 旋轉卡片特效
14  * 第2種寫法
15  *
16  * 用animator.xml的配置來描述動畫特效
17  * 在代碼中,執行動畫
18  *
19  */
20 public class MainActivity extends AppCompatActivity {
21 
22     private FrameLayout mFlCardBack, mFlCardFront, mFlContainer;
23 
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28 
29         mFlCardBack = findViewById(R.id.fl_back);
30         mFlCardFront = findViewById(R.id.fl_front);
31         mFlContainer = findViewById(R.id.main_fl_container);
32         mFlContainer.setOnClickListener(new View.OnClickListener() {
33             @Override
34             public void onClick(View v) {
35                 flipCard();
36             }
37         });
38 
39         initAnimatorSet(); // 設置動畫
40         setCameraDistance(); // 設置鏡頭距離
41     }
42 
43     // 改變視角距離, 貼近屏幕,這個必須設置,因為如果不這么做,沿着Y軸旋轉的過程中有可能產生超出屏幕的3D效果。
44     private void setCameraDistance() {
45         int distance = 16000;
46         float scale = getResources().getDisplayMetrics().density * distance;
47         mFlCardFront.setCameraDistance(scale);
48         mFlCardBack.setCameraDistance(scale);
49     }
50 
51     private boolean mIsShowBack = false;
52 
53     // 翻轉卡片
54     public void flipCard() {
55         // 正面朝上
56         if (!mIsShowBack) {
57             mRightOutSet.setTarget(mFlCardFront);
58             mLeftInSet.setTarget(mFlCardBack);
59             mIsShowBack = true;
60         } else { // 背面朝上
61             mRightOutSet.setTarget(mFlCardBack);
62             mLeftInSet.setTarget(mFlCardFront);
63             mIsShowBack = false;
64         }
65         mRightOutSet.start();
66         mLeftInSet.start();
67     }
68 
69     private AnimatorSet mRightOutSet, mLeftInSet;
70     AnimatorListenerAdapter animatorListenerAdapter = new AnimatorListenerAdapter() {
71         @Override
72         public void onAnimationStart(Animator animation) {
73             super.onAnimationStart(animation);
74             mFlContainer.setClickable(false);//在動畫執行過程中,不許允許接收點擊事件
75         }
76 
77         @Override
78         public void onAnimationEnd(Animator animation) {
79             super.onAnimationEnd(animation);
80             mFlContainer.setClickable(true);//在動畫執行過程中,不許允許接收點擊事件
81         }
82     };
83 
84 
85     private void initAnimatorSet() {
86         mRightOutSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.anim_out);
87         mLeftInSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.anim_in);
88 
89         // 設置點擊事件
90         mRightOutSet.addListener(animatorListenerAdapter);
91         mLeftInSet.addListener(animatorListenerAdapter);
92     }
93 }

這里用到了xml配置,所以必須在res中寫xml

下面貼出anim_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 這里做個說明- 用XML來配置動畫效果,下面這種平行的寫法其實是讓旋轉,和透明動畫 同時執行,
    startOffset是執行延時,對應ObjectAnimator的 setStartDelay(long startDelay) 方法 -->

    <!--旋轉-->
    <objectAnimator
        android:duration="500"
        android:propertyName="rotationY"
        android:valueFrom="-180"
        android:valueTo="0" />

    <!--出現-->
    <objectAnimator
        android:duration="0"
        android:propertyName="alpha"
        android:startOffset="250"
        android:valueFrom="0.0"
        android:valueTo="1.0" />
    <!-- 所以說這個startOffSet的意思就是,這個動畫延遲多久ms以后執行 -->
</set>

和anim_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!--旋轉-->
    <objectAnimator
        android:duration="500"
        android:propertyName="rotationY"
        android:valueFrom="0"
        android:valueTo="180" />

    <!--消失-->
    <objectAnimator
        android:duration="0"
        android:propertyName="alpha"
        android:startOffset="250"
        android:valueFrom="1.0"
        android:valueTo="0.0" />
</set>

OK,關鍵代碼上面已經給出。

下面是公共部分布局的代碼:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_fl_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/cell_card_back" />

    <include layout="@layout/cell_card_front" />

</FrameLayout>

  

卡片反面cell_card_back.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fl_back"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="反面"
        android:textColor="@color/colorAccent"
        android:textSize="30sp" />

</FrameLayout>

卡片正面 cell_card_front.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:id="@+id/fl_front">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/darker_gray"
        android:gravity="center"
        android:text="正面"
        android:textColor="@color/colorPrimary"
        android:textSize="30sp" />
</FrameLayout>

 

OK,完事。

所有的動畫特效基本都有這兩種寫法。

具體用什么,看心情吧。 

用純java,可能api查起來方便一點,畢竟xml寫配置,不能alt點進去看屬性說明。

用xml的話,可能在代碼端就簡潔一點,屬性,自己想辦法上網查好了。

就這樣了·····

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM