Android實(shí)現(xiàn)炫酷播放效果
本文實(shí)例為大家分享了Android實(shí)現(xiàn)播放效果的具體代碼,供大家參考,具體內(nèi)容如下
一、首先看效果

二、實(shí)現(xiàn)原理
使用貝塞爾曲線實(shí)現(xiàn)滑動(dòng)效果,在使用屬性動(dòng)畫(huà)實(shí)現(xiàn)水波紋效果,然后就能實(shí)現(xiàn)以上效果
三、實(shí)現(xiàn)
1、先封裝動(dòng)畫(huà)框架,創(chuàng)建動(dòng)畫(huà)基礎(chǔ)類(lèi)
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)建動(dòng)畫(huà)集合類(lèi),并且保存繪制軌跡
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)頁(yè)面布局
<?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è)置一些動(dòng)畫(huà)常量
private View mFab; private FrameLayout mFabcontainer; private LinearLayout mControlsContainer; //從什么時(shí)候開(kāi)始執(zhí)行動(dòng)畫(huà) private static final float SCALE_FACTOR = 13f; //持續(xù)時(shí)間 private static final long ANIMATION_DURATION = 300; //貝塞爾曲線滑動(dòng)到什么時(shí)候開(kāi)始執(zhí)行動(dòng)畫(huà) 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();
//開(kāi)始動(dòng)畫(huà)
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路徑中的某個(gè)位置就是開(kāi)始擴(kuò)散動(dòng)畫(huà)
if (Math.abs(startX - mFab.getX()) > MINIMUN_X_DISTANCE) {
if (!mRevealFlag) {
ImageButton fab = (ImageButton) mFab;
fab.setImageDrawable(new BitmapDrawable());
//看布局里邊的FabContainer要比toolbar背景高mFabSize/2(為了最初的半個(gè)fab效果)
mFabcontainer.setY(mFabcontainer.getY() + mFabSize / 2);
//fab放大動(dòng)畫(huà)
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為了看起來(lái)平順,需要上移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動(dòng)畫(huà)完畢后,接著每一個(gè)子控件都有個(gè)縮放動(dòng)畫(huà)(依次順序出來(lái))
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);
}
}
注意:屬性動(dòng)畫(huà)既可以改變屬性,也可以改變一個(gè)變量或者方法
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android使用fragment實(shí)現(xiàn)左側(cè)導(dǎo)航
這篇文章主要為大家詳細(xì)介紹了Android使用fragment實(shí)現(xiàn)左側(cè)導(dǎo)航,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
Android 快速使用正則表達(dá)式,校驗(yàn)身份證號(hào)的實(shí)例
下面小編就為大家分享一篇Android 快速使用正則表達(dá)式,校驗(yàn)身份證號(hào)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android實(shí)現(xiàn)倒計(jì)時(shí)的按鈕效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)倒計(jì)時(shí)的按鈕效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
Android自定View流式布局根據(jù)文字?jǐn)?shù)量換行
這篇文章主要為大家詳細(xì)介紹了Android自定View流式布局,根據(jù)文字?jǐn)?shù)量換行,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Android Webview的postUrl與loadUrl加載頁(yè)面實(shí)例
這篇文章主要介紹了Android Webview的postUrl與loadUrl加載頁(yè)面實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
基于android示例程序(bitmapfun) 高效加載圖片讓人無(wú)語(yǔ)地方
嘗試了使用git上的一個(gè)開(kāi)源項(xiàng)目afinal(bitmapfun的封裝版)來(lái)加載圖片,但是在測(cè)試的時(shí)候發(fā)現(xiàn)了一個(gè)問(wèn)題,新的圖片加載器(bitmapfun)比之前用的ImageDownloader要慢很多,特別是在網(wǎng)絡(luò)狀況不好的時(shí)候,那簡(jiǎn)直是太讓人無(wú)語(yǔ)了2013-04-04
Android自定義圓弧進(jìn)度條加數(shù)字動(dòng)態(tài)變化
這篇文章主要為大家詳細(xì)介紹了Android自定義圓弧進(jìn)度條加數(shù)字動(dòng)態(tài)變化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07

