Android中FoldingLayout折叠布局的用法及实战全攻略

2019-12-10 18:55:43于丽

重点看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 实战 实现圆形、圆角图片

四、初步实现折叠
了解了原理以及阴影的绘制以后,接下来要开始学习真正的去折叠了,我们的目标效果为:

Android中FoldingLayout折叠布局的用法及实战全攻略

妹子折叠成了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; 
       
      //初始化matrix 
      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; 
 
        //setPolyToPoly 
        mMatrices[i].setPolyToPoly(src, 0, dst, 0, src.length >> 1); 
      } 
 
    } 
 
    @Override 
    protected void onDraw(Canvas canvas) 
    { 
      super.onDraw(canvas); 
      //绘制mNumOfFolds次 
      for (int i = 0; i < mNumOfFolds; i++) 
      { 
         
        canvas.save(); 
        //将matrix应用到canvas 
        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(); 
      } 
 
    } 
 
  } 
 
}