国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android仿Flipboard動畫效果的實(shí)現(xiàn)代碼

2019-10-22 18:16:51
字體:
供稿:網(wǎng)友

1.上原圖

前幾天在 Hencoder 征稿看到的Filpboard 里的的動畫效果:

android,flipboard,動畫,代碼

Filipboard.gif

先bb一句:在看本文的同時,如果覺得我寫的模糊看不太懂的可以直接拉到文末,配合完整代碼再一步一步看。

2.實(shí)現(xiàn) 整體思路:

用手機(jī)拍下來,逐幀觀看了許久,恍然大悟,就是一張紙,折起一邊之后,讓其對折線繞中心點(diǎn)旋轉(zhuǎn)。

關(guān)聯(lián)自定義 ViewCamera 來控制對折幅度, canves 控制旋轉(zhuǎn)。

具體:

每當(dāng)對折線旋轉(zhuǎn)的時候,圖標(biāo)總是一邊是折起來的,一邊是平鋪的,且中心對稱,所以將它整體分為兩部分來繪制。

使用 canvesClipRect() 方法可以輕松實(shí)現(xiàn)切割畫布。

應(yīng)該也能順著想到給 canves 做動畫讓折疊線(切割線)動起來,這里會有一個問題,即:對折線是動起來了,可繪制內(nèi)容也會跟著動起來,那我們要的是只有分割線在中間旋轉(zhuǎn)實(shí)時分割圖標(biāo),所以有個小技巧,

先這樣:

canvas.rotate(-degreeZ); canvas.clipRect(0, -centerY, centerX, centerY);

再這樣:

canvas.rotate(degreeZ); canvas.drawBitmap(bitmap, x, y, paint);

嗯對,在旋轉(zhuǎn)畫板的代碼之后做切割,切割之后呢又讓他以完全相同的角度反向旋轉(zhuǎn),再繪制圖標(biāo),這樣就可以實(shí)現(xiàn)之前讓切割線旋轉(zhuǎn),而圖標(biāo)不動的目的了。

先貼這部分代碼,明天寫剩余部分:

protected void onDraw(Canvas canvas) { super.onDraw(canvas); int bitmapWidth = bitmap.getWidth(); int bitmapHeight = bitmap.getHeight(); int centerX = getWidth() / 2; int centerY = getHeight() / 2; int x = centerX - bitmapWidth / 2; int y = centerY - bitmapHeight / 2; // 不動的另一部分  canvas.save(); canvas.translate(centerX, centerY); canvas.rotate(-degreeZ); canvas.clipRect(-centerX, -centerY, 0, centerY); canvas.rotate(degreeZ); canvas.translate(-centerX, -centerY); canvas.drawBitmap(bitmap, x, y, paint);  canvas.restore();}

這時候看到的效果應(yīng)該是這樣的:

android,flipboard,動畫,代碼

切割線旋轉(zhuǎn)

接下來寫和它中心對稱的另一半:

因?yàn)槭侵行膶ΨQ,旋轉(zhuǎn)速度一致,只需要變更切割的部分為對稱部分,所以這部分代碼只需要將前一部分代碼復(fù)制然后修改這一行 :

canvas.clipRect(-centerX, -centerY, 0, centerY);

為:

canvas.clipRect(0,-centerY,centerX,centerY);

就可以實(shí)現(xiàn)目的。

完整代碼:

protected void onDraw(Canvas canvas) {super.onDraw(canvas);int bitmapWidth = bitmap.getWidth();int bitmapHeight = bitmap.getHeight();int centerX = getWidth() / 2;int centerY = getHeight() / 2;int x = centerX - bitmapWidth / 2;int y = centerY - bitmapHeight / 2; // 不動的另一部分 canvas.save(); canvas.translate(centerX, centerY); canvas.rotate(-degreeZ); canvas.clipRect(-centerX, -centerY, 0, centerY); canvas.rotate(degreeZ); canvas.translate(-centerX, -centerY); canvas.drawBitmap(bitmap, x, y, paint); canvas.restore(); // 被折起來的另一部分 canvas.save(); canvas.translate(centerX,centerY); canvas.rotate(-degreeZ); canvas.clipRect(0,-centerY,centerX,centerY); canvas.rotate(degreeZ); canvas.translate(-centerX,-centerY); canvas.drawBitmap(bitmap,x,y,paint); canvas.restore();}

這時候運(yùn)行代碼的效果就是 沒有效果。因?yàn)槲覀兝L制的兩部分一直是中心對稱,雖然我們知道它在動,但是看起來仿佛只是繪制了一張靜態(tài)的圖標(biāo)。

不著急,這時候就需要給它對折起來的這一半加上 Camera ,讓它 “折起來”。

在代碼里添加 Camera 經(jīng)典四步:

camera.save(); camera.rotateY(degreeY); camera.applyToCanvas(canvas); camera.restore();

當(dāng)然不考慮直接加上這些代碼是不行的,因?yàn)槲覀兪?quot;對折",意味著 折起來的部分也要和 切割線 同步旋轉(zhuǎn),

所以這些代碼應(yīng)該這樣插入進(jìn)去:

// 被折起來的另一部分 canvas.save(); camera.save(); canvas.translate(centerX, centerY); canvas.rotate(-degreeZ); camera.rotateY(degreeY); camera.applyToCanvas(canvas); canvas.clipRect(0, -centerY, centerX, centerY); canvas.rotate(degreeZ); canvas.translate(-centerX, -centerY);  canvas.drawBitmap(bitmap, x, y, paint); camera.restore();  canvas.restore();

這時候再運(yùn)行代碼:

android,flipboard,動畫,代碼

已然完成百分之80

嘿,原動畫的要求已經(jīng)完成80%了?,F(xiàn)在去加上最后的動畫: 之前不動的一半也被折起來了,這個很簡單修改不動的那一部分的代碼:

// 不動的另一部分 canvas.save(); camera.save(); canvas.translate(centerX, centerY); canvas.rotate(-degreeZ); canvas.clipRect(-centerX, -centerY, 0, centerY); canvas.rotate(degreeZ); camera.rotateX(degreeY2); camera.applyToCanvas(canvas); canvas.translate(-centerX, -centerY); canvas.drawBitmap(bitmap, x, y, paint); camera.restore(); canvas.restore();

運(yùn)行代碼,ok,完成~

對了,還有個細(xì)節(jié),仔細(xì)觀察發(fā)現(xiàn) 中間旋轉(zhuǎn)動畫旋轉(zhuǎn)速度 越來越 的,所以使用 LinearOutSlowInInterpolator 這個插補(bǔ)器。

關(guān)于屬性動畫,還有后面的更多的定制性以及細(xì)節(jié)優(yōu)化,比如重寫 onMeasure() ,動畫屬性抽離就不說了,整體思路以及一些細(xì)節(jié)思考我感覺都講出來了,不知道是不是只有我一個人懂的那種。好懶啊,想睡覺。想下班,想吃雞。

android,flipboard,動畫,代碼

完成版

最后推薦一下大佬 扔物線 的學(xué)習(xí)網(wǎng)站 hencoder :http://hencoder.com/ 不僅免費(fèi),而且賊6~

雖然我猜也沒多少人能堅(jiān)持看到這里,好慘,捂臉。

項(xiàng)目碼云地址:  https://gitee.com/alucode/AsFilpBoard

完整代碼:

public class FlipBoardView extends View {private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);private Bitmap bitmap;private Camera camera = new Camera();int degreeZ;int degreeY;int degreeY2;//中間旋轉(zhuǎn)動畫private ObjectAnimator animator = ObjectAnimator.ofInt(this, "degreeZ", 0, 270);//第一段折起動畫private ObjectAnimator animator1 = ObjectAnimator.ofInt(this, "degreeY", 0, -45);//最后一段折起動畫private ObjectAnimator animator2 = ObjectAnimator.ofInt(this, "degreeY2", 0, -45);AnimatorSet animatorSet;public FlipBoardView(Context context) { super(context);}public FlipBoardView(Context context, @Nullable AttributeSet attrs) { super(context, attrs);}public FlipBoardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);}{ //糊臉修正,給camera 做z軸距離適配,避免繪制糊臉 DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); float newZ = -displayMetrics.density * 6; camera.setLocation(0, 0, newZ); bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.maps); animator.setDuration(1000); animator.setStartDelay(500); animator.setInterpolator(new LinearOutSlowInInterpolator()); animator1.setDuration(800); animator1.setStartDelay(500); animator1.setInterpolator(new LinearInterpolator()); animator2.setDuration(500); animator2.setStartDelay(500); animator2.setInterpolator(new LinearInterpolator()); animatorSet = new AnimatorSet(); animatorSet.playSequentially(animator1, animator, animator2); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {  super.onAnimationEnd(animation);  try {  Thread.sleep(500);  } catch (InterruptedException e) {  e.printStackTrace();  }  degreeZ = 0;  degreeY = 0;  degreeY2 = 0;  animatorSet.start(); } });}@Overrideprotected void onAttachedToWindow() { super.onAttachedToWindow(); animatorSet.start();}@Overrideprotected void onDetachedFromWindow() { super.onDetachedFromWindow(); animatorSet.end();}@SuppressWarnings("unused")public void setDegreeZ(int degreeZ) { this.degreeZ = degreeZ; invalidate();}@SuppressWarnings("unused")public void setDegreeY(int degreeY) { this.degreeY = degreeY; invalidate();}public void setDegreeY2(int degreeY2) { this.degreeY2 = degreeY2; invalidate();}/** * 原理:從折 線分為兩部分繪制,其實(shí)是繪制了兩個bitmap 一個動一個不動 然后截取拼湊 * * @param canvas ca */@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); int bitmapWidth = bitmap.getWidth(); int bitmapHeight = bitmap.getHeight(); int centerX = getWidth() / 2; int centerY = getHeight() / 2; int x = centerX - bitmapWidth / 2; int y = centerY - bitmapHeight / 2; canvas.save(); camera.save(); canvas.translate(centerX, centerY); canvas.rotate(-degreeZ); camera.rotateY(degreeY); camera.applyToCanvas(canvas); canvas.clipRect(0, -centerY, centerX, centerY); canvas.rotate(degreeZ); canvas.translate(-centerX, -centerY); canvas.drawBitmap(bitmap, x, y, paint); camera.restore(); canvas.restore();// 不動的另一部分 canvas.save(); camera.save(); canvas.translate(centerX, centerY); canvas.rotate(-degreeZ); canvas.clipRect(-centerX, -centerY, 0, centerY); canvas.rotate(degreeZ); camera.rotateX(degreeY2); camera.applyToCanvas(canvas); canvas.translate(-centerX, -centerY); canvas.drawBitmap(bitmap, x, y, paint); camera.restore(); canvas.restore();}/** * onMeasure() 日常重寫 * @param widthMeasureSpec w * @param heightMeasureSpec h */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width; int height; int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { width = getPaddingLeft() + bitmap.getWidth() + getPaddingRight(); } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { height = getPaddingTop() + bitmap.getHeight() + getPaddingBottom(); } setMeasuredDimension(width, height);}}

總結(jié)

以上所述是小編給大家介紹的Android仿Flipboard動畫效果的實(shí)現(xiàn)代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對VEVB武林網(wǎng)網(wǎng)站的支持!


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 栖霞市| 通榆县| 沙田区| 新化县| 锡林郭勒盟| 蛟河市| 丰镇市| 虞城县| 太和县| 海口市| 凤山县| 东方市| 宜兴市| 五指山市| 宁安市| 高唐县| 昌黎县| 涞源县| 石泉县| 安塞县| 茌平县| 江门市| 静海县| 信宜市| 东方市| 武冈市| 礼泉县| 和田县| 同仁县| 马公市| 怀远县| 通化市| 吴堡县| 天长市| 望谟县| 南江县| 阿勒泰市| 东光县| 灵璧县| 本溪市| 鄂伦春自治旗|