轉載請標明出處: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
-
{
-
-
@Override
-
protected 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);
-
}
-
-
@Override
-
protected 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
-
{
-
-
@Override
-
protected 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));
-
-
}
-
-
@Override
-
protected 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);
-
-
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
-
{
-
-
@Override
-
protected 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;
-
-
-
for (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;
-
-
-
mMatrices[i].setPolyToPoly(src, 0, dst, 0, src.length >> 1);
-
}
-
-
}
-
-
@Override
-
protected void onDraw(Canvas canvas)
-
{
-
super.onDraw(canvas);
-
-
for (int i = 0; i < mNumOfFolds; i++)
-
{
-
-
canvas.save();
-
-
canvas.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等結合應用到側滑中去。
對於類似這種效果的,一定要拿出稿紙筆去畫一畫,否則很難弄明白。