Android實(shí)現(xiàn)炫酷播放效果
本文實(shí)例為大家分享了Android實(shí)現(xiàn)播放效果的具體代碼,供大家參考,具體內(nèi)容如下
一、首先看效果
二、實(shí)現(xiàn)原理
使用貝塞爾曲線實(shí)現(xiàn)滑動效果,在使用屬性動畫實(shí)現(xiàn)水波紋效果,然后就能實(shí)現(xiàn)以上效果
三、實(shí)現(xiàn)
1、先封裝動畫框架,創(chuàng)建動畫基礎(chǔ)類
PathPoint.java
public class PathPoint { public static final int MOVE = 0; public static final int LINE = 1; public static final int CURVE = 2; float mControl0X, mControl0Y; float mControl1X, mControl1Y; public float mX, mY; int mOperation; //line/move private PathPoint(int operation, float x, float y) { this.mOperation = operation; this.mX = x; this.mY = y; } //curve private PathPoint(float c0X, float c0Y, float c1X, float c1Y, float x, float y) { this.mControl0X = c0X; this.mControl0Y = c0Y; this.mControl1X = c1X; this.mControl1Y = c1Y; this.mX = x; this.mY = y; this.mOperation = CURVE; } public static PathPoint moveTo(float x, float y) { return new PathPoint(MOVE, x, y); } public static PathPoint lineTo(float x, float y) { return new PathPoint(LINE, x, y); } public static PathPoint curveTo(float c0X, float c0Y, float c1X, float c1Y, float x, float y) { return new PathPoint(c0X, c0Y, c1X, c1Y, x, y); } }
2、創(chuàng)建動畫集合類,并且保存繪制軌跡
AnimatorPath
public class AnimatorPath { //記錄軌跡 private List<PathPoint> mPoints = new ArrayList<>(); public void moveTo(float x, float y) { mPoints.add(PathPoint.moveTo(x, y)); } public void lineTo(float x, float y) { mPoints.add(PathPoint.lineTo(x, y)); } public void curveTo(float c0X, float c0Y, float c1X, float c1Y, float x, float y) { mPoints.add(PathPoint.curveTo(c0X, c0Y, c1X, c1Y, x, y)); } public Collection<PathPoint> getPoints() { return mPoints; } }
3、實(shí)現(xiàn)頁面布局
<?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" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffe8e8e8"> <ImageView android:id="@+id/album_cover" android:layout_width="match_parent" android:layout_height="250dp" android:background="#22eeff" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="120dp" android:layout_below="@id/album_cover" android:layout_marginTop="-15dp" android:background="@color/colorPrimary" android:elevation="4dp" android:minHeight="?attr/actionBarSize" android:paddingLeft="72dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="sans-serif" android:text="大海大海" android:textColor="#FFF" android:textSize="30sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:fontFamily="sans-serif-light" android:text="王小二" android:textColor="#9cffffff" android:textSize="18sp" /> </LinearLayout> </android.support.v7.widget.Toolbar> <FrameLayout android:id="@+id/fab_container" android:layout_width="match_parent" android:layout_height="128dp" android:layout_below="@id/album_cover" android:layout_marginTop="-30dp" android:elevation="10dp"> <LinearLayout android:id="@+id/media_controls_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="horizontal"> <ImageView android:layout_width="20dp" android:layout_height="20dp" android:scaleX="0" android:scaleY="0" android:src="@mipmap/play" /> <ImageView android:id="@+id/iv_pause_play" android:layout_width="20dp" android:layout_height="20dp" android:layout_marginLeft="50dp" android:layout_marginRight="50dp" android:scaleX="0" android:scaleY="0" android:src="@mipmap/play" /> <ImageView android:layout_width="20dp" android:layout_height="20dp" android:layout_marginRight="50dp" android:scaleX="0" android:scaleY="0" android:src="@mipmap/play" /> </LinearLayout> <ImageButton android:id="@+id/fab" android:layout_width="56dp" android:layout_height="56dp" android:layout_gravity="top|right" android:layout_marginRight="72dp" android:background="@drawable/ripple" android:elevation="5dp" android:onClick="onPabPressed" android:transitionName="button_fab" /> </FrameLayout> </RelativeLayout>
4、獲取控件,并且設(shè)置點(diǎn)擊事件,設(shè)置一些動畫常量
private View mFab; private FrameLayout mFabcontainer; private LinearLayout mControlsContainer; //從什么時候開始執(zhí)行動畫 private static final float SCALE_FACTOR = 13f; //持續(xù)時間 private static final long ANIMATION_DURATION = 300; //貝塞爾曲線滑動到什么時候開始執(zhí)行動畫 private static final float MINIMUN_X_DISTANCE = 200; private boolean mRevealFlag; private float mFabSize;
5、給mFab設(shè)置點(diǎn)擊事件
private void onFabPressed(View view) { final float startX = mFab.getX(); //開始動畫 AnimatorPath path = new AnimatorPath(); path.moveTo(0, 0); path.curveTo(-200, 200, -400, 100, -600, 50); // path.lineTo(-600,50); ObjectAnimator anim = ObjectAnimator.ofObject(this, "fabLoc", new PathEvaluator(), path.getPoints().toArray()); anim.setInterpolator(new AccelerateInterpolator()); // anim.setRepeatCount(ValueAnimator.INFINITE); // anim.setRepeatMode(ValueAnimator.REVERSE); anim.setDuration(ANIMATION_DURATION); anim.start(); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { //到了path路徑中的某個位置就是開始擴(kuò)散動畫 if (Math.abs(startX - mFab.getX()) > MINIMUN_X_DISTANCE) { if (!mRevealFlag) { ImageButton fab = (ImageButton) mFab; fab.setImageDrawable(new BitmapDrawable()); //看布局里邊的FabContainer要比toolbar背景高mFabSize/2(為了最初的半個fab效果) mFabcontainer.setY(mFabcontainer.getY() + mFabSize / 2); //fab放大動畫 mFab.animate() .scaleXBy(SCALE_FACTOR) .scaleYBy(SCALE_FACTOR) .setListener(mEndRevealListener) .setDuration(ANIMATION_DURATION); mRevealFlag = true; } } } }); } public void setFabLoc(PathPoint newLoc) { mFab.setTranslationX(newLoc.mX); if (mRevealFlag) { //因?yàn)椴季掷镞叺膍Fabcontainer要比toolbar背景高mFabSize/2,所以fab為了看起來平順,需要上移mFabSize/2 mFab.setTranslationY(newLoc.mY - (mFabSize / 2)); } else { mFab.setTranslationY(newLoc.mY); } } private AnimatorListenerAdapter mEndRevealListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mFab.setVisibility(View.INVISIBLE); mFabcontainer.setBackgroundColor(getResources().getColor(R.color.colorAccent)); //reveal動畫完畢后,接著每一個子控件都有個縮放動畫(依次順序出來) for (int i = 0; i < mControlsContainer.getChildCount(); i++) { View v = mControlsContainer.getChildAt(i); ViewPropertyAnimator animate = v.animate() .scaleX(1) .scaleY(1) .setDuration(ANIMATION_DURATION); animate.setStartDelay(i * 50); animate.start(); } } };
PathEvaluator
public class PathEvaluator implements TypeEvaluator<PathPoint> { @Override public PathPoint evaluate(float t, PathPoint startValue, PathPoint endValue) { //t執(zhí)行的百分比 (0~1) float x, y; if (endValue.mOperation == PathPoint.CURVE) { //三階貝塞爾曲線 公式 float oneMinusT = 1 - t; x = oneMinusT * oneMinusT * oneMinusT * startValue.mX + 3 * oneMinusT * oneMinusT * t * endValue.mControl0X + 3 * oneMinusT * t * t * endValue.mControl1X + t * t * t * endValue.mX; y = oneMinusT * oneMinusT * oneMinusT * startValue.mY + 3 * oneMinusT * oneMinusT * t * endValue.mControl0Y + 3 * oneMinusT * t * t * endValue.mControl1X + t * t * t * endValue.mY; } else if (endValue.mOperation == PathPoint.LINE) { //x=起始點(diǎn)+t*起始點(diǎn)和終點(diǎn)的距離 x = startValue.mX + t * (endValue.mX - startValue.mX); y = startValue.mY + t * (endValue.mY - startValue.mY); } else { x = endValue.mX; y = endValue.mY; } return PathPoint.moveTo(x, y); } }
注意:屬性動畫既可以改變屬性,也可以改變一個變量或者方法
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Crashlytics Android 異常報告統(tǒng)計管理(詳解)
下面小編就為大家?guī)硪黄狢rashlytics Android 異常報告統(tǒng)計管理(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05Android中Serializable和Parcelable序列化對象詳解
這篇文章主要介紹了Android中Serializable和Parcelable序列化對象的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-02-02Android仿知乎懸浮功能按鈕FloatingActionButton效果
前段時間在看屬性動畫,恰巧這個按鈕的效果可以用屬性動畫實(shí)現(xiàn),下面通過本文給大家分享adroid仿知乎懸浮功能按鈕FloatingActionButton效果,需要的朋友參考下吧2017-04-04Android仿微信照片選擇器實(shí)現(xiàn)預(yù)覽查看圖片
這篇文章主要介紹了Android仿微信照片選擇器實(shí)現(xiàn)預(yù)覽查看圖片的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-01-01Android?Spinner和GridView組件的使用示例
Spinner其實(shí)是一個列表選擇框,不過Android的列表選擇框并不需要顯示下拉列表,而是相當(dāng)于彈出一個菜單供用戶選擇,GridView是一個在二維可滾動的網(wǎng)格中展示內(nèi)容的控件。網(wǎng)格中的內(nèi)容通過使用adapter自動插入到布局中2022-03-03Android多進(jìn)程間采用AIDL方式進(jìn)行通信
這篇文章主要為大家詳細(xì)介紹了Android多進(jìn)程間采用AIDL方式進(jìn)行通信,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04Android中SharedPreferences簡單使用實(shí)例
這篇文章主要介紹了Android中SharedPreferences簡單使用案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10