基于Android實現(xiàn)3D翻頁效果
最近做了一個簡單的3D效果翻頁特效,先說說我的思路吧,首先我這個翻頁效果并不是兩個Activity之間的跳轉,而是在同一個activity類切換不同的view而已。我現(xiàn)在的做法是單擊一個button然后Gone當前的布局,然后把需要呈現(xiàn)的布局visible,在隱藏當前布局的時候啟動動畫,然后給動畫添加監(jiān)聽,在動畫結束時開始另外一個view的入場動畫就行了。
下面來看下我的主頁面的布局文件:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="fill_parent" android:layout_height="fill_parent" > <include android:layout_width="fill_parent" android:layout_height="fill_parent" layout="@layout/layout2" /> <include android:layout_width="fill_parent" android:layout_height="fill_parent" layout="@layout/layout1" /> </FrameLayout>
我這個布局文件使用<include>標簽包含了另外2個布局文件,這些布局文件才是呈現(xiàn)數(shù)據(jù)的,下面是另外2個布局文件:
layout1:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/test1" android:orientation="vertical" android:id="@+id/container1" > <Button android:id="@+id/bt_towhile" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="白色" /> </LinearLayout>
layout2:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container2" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/test2" android:orientation="vertical" > <Button android:id="@+id/bt_toblack" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="黑色" /> </LinearLayout>
我這里只是舉個例子并沒有放什么實際的類容,只是放了2個button,當我點擊其中一個跳轉到另外一個layout。
有了布局文件那我們就開始要實現(xiàn)功能了,我們的想法是點擊按鈕的時候開始一個動畫等動畫結束時再開啟另外一個動畫并隱藏和展示layout1和layout2。
下面是我寫的一個動畫工具類源碼:
package com.test.view; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; public class RotateAnimationUtil { private ViewGroup context; private View[] views; public RotateAnimationUtil(ViewGroup context, View... views) { super(); this.context = context; this.views = views; } /** * 應用自定義的Rotate3DAnimation動畫 * * @param flag * 當前控件的順序坐標 * @param startDegress * 開始的角度 * @param endDegress * 結束的角度 */ public void applyRotateAnimation(int flag, float startDegress, float endDegress) { final float centerX = context.getWidth() / 2.0f; final float centerY = context.getHeight() / 2.0f; Rotate3DAnimation rotate = new Rotate3DAnimation(startDegress, endDegress, centerX, centerY, 310.0f, true); rotate.setDuration(1000); rotate.setFillAfter(false); rotate.setInterpolator(new DecelerateInterpolator()); rotate.setAnimationListener(new DisplayNextView(flag)); context.startAnimation(rotate); } private final class DisplayNextView implements Animation.AnimationListener { private final int mFlag; private DisplayNextView(int flag) { mFlag = flag; } public void onAnimationStart(Animation animation) { } // 動畫結束 public void onAnimationEnd(Animation animation) { context.post(new SwapViews(mFlag)); } public void onAnimationRepeat(Animation animation) { } } /** * 新開一個線程動畫結束后再開始一次動畫效果實現(xiàn)翻屏特效 * * @author yangzhiqiang * */ private final class SwapViews implements Runnable { private final int mFlag; public SwapViews(int mFlag) { this.mFlag = mFlag; } public void run() { final float centerX = context.getWidth() / 2.0f; final float centerY = context.getHeight() / 2.0f; Rotate3DAnimation rotation; if (mFlag > -1) { views[0].setVisibility(View.GONE); views[1].setVisibility(View.VISIBLE); views[1].requestFocus(); rotation = new Rotate3DAnimation(270, 360, centerX, centerY, 310.0f, false); } else { views[1].setVisibility(View.GONE); views[0].setVisibility(View.VISIBLE); views[0].requestFocus(); rotation = new Rotate3DAnimation(90, 0, centerX, centerY, 310.0f, false); } rotation.setDuration(1000); rotation.setFillAfter(false); rotation.setInterpolator(new DecelerateInterpolator()); // 開始動畫 context.startAnimation(rotation); } } }
解釋一下這個類的構造方法:
public RotateAnimationUtil(ViewGroup context, View... views) { super(); this.context = context; this.views = views; }
有2個參數(shù),第一個參數(shù)就是我們的主布局頁面的FrameLayout,第2個參數(shù)就是我們要進行動畫切換的2個子layout,我這使用的是一個可變長參數(shù)只是為了方便而已。
public void applyRotateAnimation(int flag, float startDegress,float endDegress)方法第一個參數(shù)是標記當前是第是從哪個個layout跳轉,因外我們必須知道當前開始跳轉的layout才能推算角度。
下面是我自定義動畫的源碼:
package com.test.view; import android.graphics.Camera; import android.graphics.Matrix; import android.view.animation.Animation; import android.view.animation.Transformation; public class Rotate3DAnimation extends Animation { private final float mFormDegress; private final float mToDegress; private final float mCenterX; private final float mCenterY; /** * 控制z軸的一個常量值,主要是控制動畫的升降距離 */ private final float mDepthz; /** * 控制z軸是像上移動還是向下移動,從而實現(xiàn)升降效果 */ private final boolean mReverse; private Camera mCamera; public Rotate3DAnimation(float formDegress, float toDegress, float centerX, float centerY, float depthz, boolean reverse) { super(); this.mFormDegress = formDegress; this.mToDegress = toDegress; this.mCenterX = centerX; this.mCenterY = centerY; this.mDepthz = depthz; this.mReverse = reverse; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } /** * interpolatedTime 取值范圍是0-1之間當每次,當動畫啟動后會系統(tǒng)會不停的調用applyTransformation方法, * 并改變interpolatedTime的值 */ @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float formDegress = mFormDegress; // 通過差點值計算出轉變的角度 float degress = formDegress + ((mToDegress - formDegress) * interpolatedTime); final float centerX = mCenterX; final float centerY = mCenterY; final Camera camera = mCamera; // 得到當前矩陣 Matrix matrix = t.getMatrix(); // 報錯當前屏幕的狀態(tài) camera.save(); // 判斷是降還是升 if (mReverse) { // 正向改變Z軸角度 camera.translate(0.0f, 0.0f, mDepthz * interpolatedTime); } else { // 反向改變Z軸角度 camera.translate(0.0f, 0.0f, mDepthz * (1.0f - interpolatedTime)); } // 旋轉Y軸角度 camera.rotateY(degress); // 把當前改變后的矩陣信息復制給Transformation的Matrix camera.getMatrix(matrix); // 根據(jù)改變后的矩陣信息從新恢復屏幕 camera.restore(); // 讓動畫在屏幕中間運行 matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } }
如果你不需要沉降效果那么你把下面的代碼刪除掉即可:
if (mReverse) { // 正向改變Z軸角度 camera.translate(0.0f, 0.0f, mDepthz * interpolatedTime); } else { // 反向改變Z軸角度 camera.translate(0.0f, 0.0f, mDepthz * (1.0f - interpolatedTime)); }
好了核心代碼已經上完,下面是主界面代碼:
package com.test.rotateanimation; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; import com.test.view.RotateAnimationUtil; public class MainActivity extends Activity { private FrameLayout container; private LinearLayout container1; private LinearLayout container2; private RotateAnimationUtil rotateAnimationUtil; private Button bt_towhile; private Button bt_toblack; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); bt_towhile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { rotateAnimationUtil.applyRotateAnimation(1, 0, 90); } }); bt_toblack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { rotateAnimationUtil.applyRotateAnimation(-1, 0, -90); } }); // 設置當前View控件的緩存 container .setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE); } private void initView() { container = (FrameLayout) findViewById(R.id.container); bt_toblack = (Button) findViewById(R.id.bt_toblack); bt_towhile = (Button) findViewById(R.id.bt_towhile); container1 = (LinearLayout) findViewById(R.id.container1); container2 = (LinearLayout) findViewById(R.id.container2); rotateAnimationUtil = new RotateAnimationUtil(container, container1, container2); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
下面是運行效果,剪切效果不好,呵呵.
源碼下載:http://xiazai.jb51.net/201606/yuanma/RotateAnimation(jb51.net).rar
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- android中圖片翻頁效果簡單的實現(xiàn)方法
- 解析Android中實現(xiàn)滑動翻頁之ViewFlipper的使用詳解
- Android實現(xiàn)閱讀APP平移翻頁效果
- Android自定義左右或上下滑動翻頁效果
- Android自定義ViewPager實現(xiàn)縱向滑動翻頁效果
- Android?ViewPager實現(xiàn)左右滑動翻頁效果
- android ViewPager實現(xiàn)滑動翻頁效果實例代碼
- Android 仿日歷翻頁、仿htc時鐘翻頁、數(shù)字翻頁切換效果
- Android CardView+ViewPager實現(xiàn)ViewPager翻頁動畫的方法
- Android實現(xiàn)翻頁特效
相關文章
Android中訪問證書有問題的SSL網(wǎng)頁的方法
在WebView里加載SSL網(wǎng)頁很正常,也沒什么難度。但如果要加載的SSL頁面的證書有問題,比如過期、信息不正確、發(fā)行機關不被信任等,WebView就會拒絕加載該網(wǎng)頁2014-04-04Android使用Retrofit實現(xiàn)自定義Converter解析接口流程詳解
Retrofit是一個RESTful的HTTP網(wǎng)絡請求框架的封裝,網(wǎng)絡請求的工作本質上是OkHttp完成,而Retrofit僅負責網(wǎng)絡請求接口的封裝2023-03-03Android DragVideo實現(xiàn)播放視頻時任意拖拽的方法
這篇文章主要介紹了Android DragVideo實現(xiàn)播放視頻時任意拖拽的方法的相關資料,一種在播放視頻時,能夠拖拽的方案,需要的朋友可以參考下2016-12-12Android 自定義view模板并實現(xiàn)點擊事件的回調
這篇文章主要介紹了Android 自定義view模板并實現(xiàn)點擊事件的回調的相關資料,需要的朋友可以參考下2017-01-01