Android 正反面視圖動畫切換

今天做到一個模塊,需要做一個控件,能夠正反面都有視圖,點擊就能翻轉(zhuǎn)切換的那種(對對對,就是你想的那種?。?。

好好思考了一下,應(yīng)該不怎么難,于是便開始動手自己寫一個簡易的。

大體思路

兩個疊加在一起的視圖,一個可見,一個不可見,分別設(shè)置動畫效果(繞Y軸旋轉(zhuǎn)),正面視圖從0-90度旋轉(zhuǎn),旋轉(zhuǎn)結(jié)束后,隱藏正面視圖,顯示背面視圖,然后背面視圖從-90-0度旋轉(zhuǎn) ,形成了一個完整的動畫流程。(具體可見下面效果圖)

1.首先需要兩個視圖。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.sundae.FrontAndBackAnimator.MainActivity">
    

    <RelativeLayout
        android:id="@+id/card_back"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_marginTop="102dp"
        android:background="@android:color/holo_blue_bright"
        android:gravity="center"
        android:visibility="gone">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="你好世界!"
            android:textSize="30sp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignEnd="@+id/textView"
            android:layout_alignStart="@+id/textView"
            android:layout_below="@+id/textView"
            android:layout_marginTop="12dp"
            android:text="Button" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/card_face"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_marginTop="102dp"
        android:background="@android:color/holo_orange_dark"
        android:gravity="center"
        android:visibility="visible">

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Hello World!"
            android:textSize="30sp"
            android:textStyle="bold" />

        <EditText
            android:id="@+id/editText2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@+id/textView2"
            android:layout_below="@+id/textView2"
            android:layout_marginTop="12dp"
            android:ems="10"
            android:hint="請輸入。。。"
            android:inputType="textPersonName" />
    </RelativeLayout>


</RelativeLayout>

得到如下效果


QQ20170612-100003@2x.png

這其實是兩個視圖疊加在一起的,位置和寬高相同,一個在下層,一個在上層。

2.接下來需要實現(xiàn)翻轉(zhuǎn)的動畫效果

使用ObjectAnimator,需要設(shè)置這幾個屬性

        toBackObjectAnimator = new ObjectAnimator();
        toBackObjectAnimator.setFloatValues(0f , 90f);    
        ///動畫更新值的范圍(設(shè)置為0-90度)
        toBackObjectAnimator.setDuration(duration);  ///動畫的時長
        toBackObjectAnimator.setPropertyName("rotationY");    
        ///所更改的object屬性  這里是y軸角度
        toBackObjectAnimator.setTarget(faceView);
        ///設(shè)置需要應(yīng)用的視圖

toBackObjectAnimator.addUpdateListener()可以添加動畫更新的監(jiān)聽器
然后就可以使用toBackObjectAnimator.start()開始動畫了

3.動畫流程

(1)正面視圖設(shè)置動畫從0-90度旋轉(zhuǎn)。
(2)旋轉(zhuǎn)結(jié)束后,隱藏正面視圖,顯示背面視圖。
(3)背面視圖開始旋轉(zhuǎn),從-90-0度旋轉(zhuǎn)。
(4)結(jié)束
這是一個流程。

4.動畫顯示距離的問題

這時你運行一下后會發(fā)現(xiàn)這樣的問題


未命名1.gif

(?ì _ í?)我去,動畫怎么就糊臉上了呢。
這是繞Y軸旋轉(zhuǎn)的時候會出現(xiàn)的現(xiàn)象,需要調(diào)整視距。(初始化的時候調(diào)用一次即可,設(shè)置需要設(shè)置的view)

    /**
     * rotationY屬性變換時需要調(diào)整相機距離,否則會影響用戶體驗
     */
    private void setCameraDistance() {
        int distance = 16000;
        float scale = context.getResources().getDisplayMetrics().density * distance;
        view.setCameraDistance(scale);    //設(shè)置相機視距距離
        view1.setCameraDistance(scale);   //需要設(shè)置的都設(shè)置一下
    }

5.一個線性動畫的問題

當你這樣寫好后還會發(fā)現(xiàn)一個問題,動畫update的值并不是一個線性的
而是以一種類似S型曲線的值來變幻,


這樣的減速-加速-減速的曲線。
而我需要的是線性的動畫效果(速度一致)
這時就需要用到一個叫插值器(TimeInterpolator)的神奇的東西。

    /**
     * 線性值插值器
     */
    class LinearAnim implements TimeInterpolator{

        @Override
        public float getInterpolation(float input) {
            //Log.e("TAG", "getInterpolation: input : " + input );
            return input;
        }
    }

寫一個類使用TimeInterpolator接口
實現(xiàn)getInterpolation方法。

可以Log看一下input的值,實現(xiàn)線性效果的話直接return input就可以了。

寫好想要的效果后對ObjectAnimator設(shè)置一下就行了
toBackObjectAnimator.setInterpolator(new LinearAnim());

后續(xù)會對TimeInterpolator進行一些詳細的學(xué)習,挺好玩的一個東西,能夠?qū)崿F(xiàn)很多效果。

6.上面的工作完成后能夠?qū)崿F(xiàn)如下效果(GIF沒有實際流暢)

anim.gif
OK,基本的功能就搞定了,剩下的就是一些邏輯性的問題了

我已經(jīng)做好了一個工具類可以參考或直接調(diào)用
FrontAndBackView.java

調(diào)用方法如下:

faceAndBackView = new FrontAndBackView(getApplicationContext() , frontView, backView);
//faceAndBackView.setDuration(2000);    設(shè)置時常

添加點擊監(jiān)聽器調(diào)用toggle方法。

@Override
    public void onClick(View v) {
        if(v.getId() == R.id.front_view || v.getId() == R.id.back_view)
            faceAndBackView.toggle();
    }

這樣就可以直接使用了,可以循環(huán)哦。

ps:只是一個初步版本,后續(xù)有機會還會繼續(xù)完善,如果發(fā)現(xiàn)有bug或者有什么建議請聯(lián)系我哦??,一起學(xué)習。
948820549@qq.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容