zoukankan      html  css  js  c++  java
  • 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的话,可能在代码端就简洁一点,属性,自己想办法上网查好了。

    就这样了·····

  • 相关阅读:
    AI:IPPR的数学表示-CNN稀疏结构进化(Mobile、xception、Shuffle、SE、Dilated、Deformable)
    基于视觉的机械手控制
    远程图形界面:VncServer与KDE桌面远程连接
    远程图形界面:使用putty+xmin远程登录ubuntu-kde
    CUDA 显存操作:CUDA支持的C++11
    C++11:using 的各种作用
    C++ 模板template和template
    Detectron:Pytorch-Caffe2-Detectron的一些跟进
    TF实战:(Mask R-CNN原理介绍与代码实现)-Chapter-8
    The type javax.servlet.http.HttpServletRequest cannot be resolved.
  • 原文地址:https://www.cnblogs.com/hankzhouAndroid/p/9430240.html
Copyright © 2011-2022 走看看