AndroidFoldingLayout摺疊布局原理及實現(一)(轉載)

來源:互聯網
上載者:User

標籤:

AndroidFoldingLayout摺疊布局原理及實現(一)

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/44278417,本文出自:【張鴻洋的部落格】

1、概述

無意中翻到的FoldingLayout的介紹的部落格,以及github地址。感覺很nice呀,於是花了點時間研究以及編寫,本篇部落格將帶大家從最基本的原理分析,一步一步的實現我們的FoldingLayout,當然了,如果你能力過硬,可以直接下載github上的代碼進行學習。

部落格基本分為以下幾個部分:

1、Matrix的setPolyToPoly使用

2、在圖片上使用漸層和陰影

3、初步的FoldingLayout的實現,完成圖片的摺疊顯示(可控制摺疊次數、包含陰影的繪製)

4、引入手勢,手指可以可以FoldingLayout的摺疊

5、結合DrawerLayout實現摺疊式側滑

6、結合SlidingPaneLayout實現摺疊式側滑

ok,貼下部分的:


改圖對應上述3,妹子不錯吧~

ok,對應上述4.


對應上述5。

ok,挑選了部分圖,不然太占篇幅了。

那麼接下來,我們就按照順序往下學習了~~~

2、Matrix的setPolyToPoly使用

想要實現摺疊,最重要的就是其核心的原理了,那麼第一步我們要瞭解的就是,如何能把一張正常顯示的圖片,讓它能夠進行位移顯示。

其實精髓就在於Matrix的setPolyToPoly的方法。

public boolean setPolyToPoly(float[] src, int srcIndex,  float[] dst, int dstIndex,int pointCount) 
簡單看一下該方法的參數,src代表變換前的座標;dst代表變換後的座標;從src到dst的變換,可以通過srcIndex和dstIndex來制定第一個變換的點,一般可能都設定位0。pointCount代表支援的轉換座標的點數,最多支援4個。

如果不明白沒事,下面通過一個簡單的例子,帶大家瞭解:

package com.zhy.sample.folderlayout;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Matrix;import android.os.Bundle;import android.view.View;public class MatrixPolyToPolyActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(new PolyToPolyView(this));}class PolyToPolyView extends View{private Bitmap mBitmap;private Matrix mMatrix;public PolyToPolyView(Context context){super(context);mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.tanyan);mMatrix = new Matrix();float[] src = { 0, 0,//mBitmap.getWidth(), 0,//mBitmap.getWidth(), mBitmap.getHeight(),//0, mBitmap.getHeight() };float[] dst = { 0, 0,//mBitmap.getWidth(), 100,//mBitmap.getWidth(), mBitmap.getHeight() - 100,//0, mBitmap.getHeight() };mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);}@Overrideprotected void onDraw(Canvas canvas){super.onDraw(canvas);canvas.drawBitmap(mBitmap, mMatrix, null);}}}

我們編寫了一個PolyToPolyView作為我們的Activity的主視圖。

在PolyToPolyView中,我們載入了一張圖片,初始化我們的Matrix,注意src和dst兩個數組,src就是正常情況片的4個頂點。dst將圖片右側兩個點的y座標做了些許的修改。

大家可以在紙上稍微標一下src和dst的四個點的位置。

最後我們在onDraw的時候進行映像的繪製,效果為:


如果你已經在紙上稍微的畫了dst的四個點,那麼這個結果你一定不陌生。

可以看到我們通過matrix.setPolyToPoly實現了圖片的傾斜,那麼引入到摺疊的情況,假設摺疊兩次,大家有思路麼,考慮一下,沒有的話,繼續往下看。

3、引入陰影

其實陰影應該在實現初步的摺疊以後來說,這樣示範其實比較方便,但是為了降低其理解的簡單性,我們先把陰影抽取出來說。

假設我們現在要給加上陰影,希望的是這樣的:


可以看到我們左側加入了一點陰影,怎麼實現呢?

主要還是利用LinearGradient,我們從左至右添加一層從黑色到透明的漸層即可。

public class MatrixPolyToPolyWithShadowActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(new PolyToPolyView(this));}class PolyToPolyView extends View{private Bitmap mBitmap;private Matrix mMatrix;private Paint mShadowPaint;private Matrix mShadowGradientMatrix;private LinearGradient mShadowGradientShader;public PolyToPolyView(Context context){super(context);mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.tanyan);mMatrix = new Matrix();mShadowPaint = new Paint();mShadowPaint.setStyle(Style.FILL);mShadowGradientShader = new LinearGradient(0, 0, 0.5f, 0,Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);mShadowPaint.setShader(mShadowGradientShader);mShadowGradientMatrix = new Matrix();mShadowGradientMatrix.setScale(mBitmap.getWidth(), 1);mShadowGradientShader.setLocalMatrix(mShadowGradientMatrix);mShadowPaint.setAlpha((int) (0.9*255));}@Overrideprotected void onDraw(Canvas canvas){super.onDraw(canvas);canvas.save();float[] src = //...;float[] dst = //...;mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);canvas.concat(mMatrix);canvas.drawBitmap(mBitmap, 0, 0, null);//繪製陰影                                                                                                                        canvas.drawRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(),mShadowPaint);canvas.restore();}}}

重點看mShadowPaint,mShadowGradientShader,mShadowGradientMatrix一個是畫筆,我們為畫筆設定了一個漸層的Shader,這個Shader的參數為

new LinearGradient(0, 0, 0.5f, 0,Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);

起點(0,0)、終點(0.5f,0);顏色從和BLACK到透明;模式為CLAMP,也就是展開最後一個像素。

這裡你可能會問,這才為0.5個像素的地區設定了漸層,不對呀,恩,是的,繼續看接下來我們使用了setLocalMatrix(mShadowGradientMatrix);,而這個

mShadowGradientMatrix將和座標擴大了mBitmap.getWidth()倍,也就是說現在設定漸層的地區為(0.5f*mBitmap.getWidth(),0)半張圖的大小,那麼後半張圖呢?

後半張應用CLAMP模式,展開的透明。

關於Shader、setLocalMatrix等用法也可以參考:Android BitmapShader 實戰 實現圓形、圓角圖片

4、初步實現摺疊

瞭解了原理以及陰影的繪製以後,接下來要開始學習真正的去摺疊了,我們的目標效果為:


妹子摺疊成了8份,且陰影的範圍為:每個沉下去夾縫的左右兩側,左側黑色半透明遮蓋,右側短距離的黑色到透明陰影(大家可以仔細看)。

現在其實大家以及會將圖片簡單傾斜和添加陰影了,那麼唯一的痛點就是怎麼將一張圖分成很多快,我相信每塊的摺疊大家都會。

其實我們可以通過繪製該圖多次,比如第一次繪製往下傾斜;第二次繪製網上傾斜;這樣就和我們標題2的實作類別似了,只需要利用setPolyToPoly。

那麼繪製多次,每次顯示肯定不是一整張圖,比如第一次,我只想顯示第一塊,所以我們還需要clipRect的配合,說到這,應該以及揭秘了~~~

package com.zhy.sample.folderlayout;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.Shader.TileMode;import android.os.Bundle;import android.view.View;public class SimpleUseActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(new PolyToPolyView(this));}class PolyToPolyView extends View{private static final int NUM_OF_POINT = 8;/** * 圖片的摺疊後的總寬度 */private int mTranslateDis;/** * 摺疊後的總寬度與原圖寬度的比例 */private float mFactor = 0.8f;/** * 摺疊塊的個數 */private int mNumOfFolds = 8;private Matrix[] mMatrices = new Matrix[mNumOfFolds];private Bitmap mBitmap;/** * 繪製黑色透明地區 */private Paint mSolidPaint;/** * 繪製陰影 */private Paint mShadowPaint;private Matrix mShadowGradientMatrix;private LinearGradient mShadowGradientShader;/*** * 原圖每塊的寬度 */private int mFlodWidth;/** * 摺疊時,每塊的寬度 */private int mTranslateDisPerFlod;public PolyToPolyView(Context context){super(context);mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.tanyan);//摺疊後的總寬度mTranslateDis = (int) (mBitmap.getWidth() * mFactor);//原圖每塊的寬度mFlodWidth = mBitmap.getWidth() / mNumOfFolds;//摺疊時,每塊的寬度mTranslateDisPerFlod = mTranslateDis / mNumOfFolds;//初始化matrixfor (int i = 0; i < mNumOfFolds; i++){mMatrices[i] = new Matrix();}mSolidPaint = new Paint();int alpha = (int) (255 * mFactor * 0.8f) ;mSolidPaint.setColor(Color.argb((int) (alpha*0.8F), 0, 0, 0));mShadowPaint = new Paint();mShadowPaint.setStyle(Style.FILL);mShadowGradientShader = new LinearGradient(0, 0, 0.5f, 0,Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);mShadowPaint.setShader(mShadowGradientShader);mShadowGradientMatrix = new Matrix();mShadowGradientMatrix.setScale(mFlodWidth, 1);mShadowGradientShader.setLocalMatrix(mShadowGradientMatrix);mShadowPaint.setAlpha(alpha);//縱軸減小的那個高度,用勾股定理計算下int depth = (int) Math.sqrt(mFlodWidth * mFlodWidth- mTranslateDisPerFlod * mTranslateDisPerFlod)/2;//轉換點float[] src = new float[NUM_OF_POINT];float[] dst = new float[NUM_OF_POINT];/** * 原圖的每一塊,對應摺疊後的每一塊,方向為左上、右上、右下、左下,大家在紙上自己畫下 */for (int i = 0; i < mNumOfFolds; i++){src[0] = i * mFlodWidth;src[1] = 0;src[2] = src[0] + mFlodWidth;src[3] = 0;src[4] = src[2];src[5] = mBitmap.getHeight();src[6] = src[0];src[7] = src[5];boolean isEven = i % 2 == 0;dst[0] = i * mTranslateDisPerFlod;dst[1] = isEven ? 0 : depth;dst[2] = dst[0] + mTranslateDisPerFlod;dst[3] = isEven ? depth : 0;dst[4] = dst[2];dst[5] = isEven ? mBitmap.getHeight() - depth : mBitmap.getHeight();dst[6] = dst[0];dst[7] = isEven ? mBitmap.getHeight() : mBitmap.getHeight()- depth;//setPolyToPolymMatrices[i].setPolyToPoly(src, 0, dst, 0, src.length >> 1);}}@Overrideprotected void onDraw(Canvas canvas){super.onDraw(canvas);//繪製mNumOfFolds次for (int i = 0; i < mNumOfFolds; i++){canvas.save();//將matrix應用到canvascanvas.concat(mMatrices[i]);//控制顯示的大小canvas.clipRect(mFlodWidth * i, 0, mFlodWidth * i + mFlodWidth,mBitmap.getHeight());//繪製圖片canvas.drawBitmap(mBitmap, 0, 0, null);//移動繪製陰影canvas.translate(mFlodWidth * i, 0);if (i % 2 == 0){//繪製黑色遮蓋canvas.drawRect(0, 0, mFlodWidth, mBitmap.getHeight(),mSolidPaint);}else{//繪製陰影canvas.drawRect(0, 0, mFlodWidth, mBitmap.getHeight(),mShadowPaint);}canvas.restore();}}}}

簡單講解下,不去管繪製陰影的部分,其實摺疊就是:

1、初始化轉換點,這裡注釋說的很清楚,大家最好在紙上繪製下,標一下每個變數。

2、為matrix.setPolyToPoly

3、繪製時使用該matrix,且clipRect控制顯示地區(這個地區也很簡單,原圖的第一塊到最後一塊),最好就是繪製bitmap了。

陰影這裡大家可以換個明亮點的圖片去看看~~


好了,由於篇幅原因,剩下的內容將在下一篇繼續完成,下一篇將展示如何將簡單的圖片的摺疊,轉化為對一個布局內所有控制項的摺疊效果,以及引入手勢、

和DrawerLayout等結合應用到側滑中去。

對於類似這種效果的,一定要拿出稿紙筆去畫一畫,否則很難弄明白。


源碼:下載

群號:429757068

公眾號請掃描(第一時間通知部落格、視頻等通知):














原文連結本文由豆約翰部落格備份專家遠程一鍵發布

AndroidFoldingLayout摺疊布局原理及實現(一)(轉載)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.