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

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

简单讲解下,不去管绘制阴影的部分,其实折叠就是:
1、初始化转换点,这里注释说的很清楚,大家最好在纸上绘制下,标一下每个变量。
2、为matrix.setPolyToPoly
3、绘制时使用该matrix,且clipRect控制显示区域(这个区域也很简单,原图的第一块到最后一块),最好就是绘制bitmap了。
阴影这里大家可以换个明亮点的图片去看看~~

五、FoldLayout的实现
1、实现
我们的想法是这样的,我们的FoldLayout只能有一个直接子元素,当然这个子元素可以是RelativeLayout什么的,可以很复杂。然后只要外层套了我们的FoldLayout,就能实现折叠效果。
那么也就是说,我们的FoldLayout折叠效果展示的是它的子元素的“样子”,那么如何或者这个“样子”呢?
大家都知道,我们的ViewGroup有个方法叫做:dispatchDraw(Canvas)主要用来绘制子元素,我们可以对这个canvas进行设置matrix,以及重复调用dispatchDraw(Canvas)来实现类似上篇博客最后的效果,这样就完成了我们的可行性的分析。

package com.zhy.view; 
 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Bitmap.Config; 
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.util.AttributeSet; 
import android.view.View; 
import android.view.ViewGroup; 
 
public class FoldLayout extends ViewGroup 
{ 
 
  private static final int NUM_OF_POINT = 8; 
  /** 
   * 图片的折叠后的总宽度 
   */ 
  private float mTranslateDis; 
 
  protected float mFactor = 0.6f; 
 
  private int mNumOfFolds = 8; 
 
  private Matrix[] mMatrices = new Matrix[mNumOfFolds]; 
 
  private Paint mSolidPaint; 
 
  private Paint mShadowPaint; 
  private Matrix mShadowGradientMatrix; 
  private LinearGradient mShadowGradientShader; 
 
  private float mFlodWidth; 
  private float mTranslateDisPerFlod; 
 
  public FoldLayout(Context context) 
  { 
    this(context, null); 
  } 
 
  public FoldLayout(Context context, AttributeSet attrs) 
  { 
    super(context, attrs); 
 
    for (int i = 0; i < mNumOfFolds; i++) 
    { 
      mMatrices[i] = new Matrix(); 
    } 
 
    mSolidPaint = new Paint(); 
    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(); 
    this.setWillNotDraw(false); 
 
  } 
 
  @Override 
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
  { 
    View child = getChildAt(0); 
    measureChild(child, widthMeasureSpec, heightMeasureSpec); 
    setMeasuredDimension(child.getMeasuredWidth(), 
        child.getMeasuredHeight()); 
 
  } 
 
  @Override 
  protected void onLayout(boolean changed, int l, int t, int r, int b) 
  { 
    View child = getChildAt(0); 
    child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); 
 
    mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), 
        Config.ARGB_8888); 
    mCanvas.setBitmap(mBitmap); 
    updateFold(); 
 
  } 
 
  private void updateFold() 
  { 
    int w = getMeasuredWidth(); 
    int h = getMeasuredHeight(); 
 
    mTranslateDis = w * mFactor; 
    mFlodWidth = w / mNumOfFolds; 
    mTranslateDisPerFlod = mTranslateDis / mNumOfFolds; 
 
    int alpha = (int) (255 * (1 - mFactor)); 
    mSolidPaint.setColor(Color.argb((int) (alpha * 0.8F), 0, 0, 0)); 
 
    mShadowGradientMatrix.setScale(mFlodWidth, 1); 
    mShadowGradientShader.setLocalMatrix(mShadowGradientMatrix); 
    mShadowPaint.setAlpha(alpha); 
 
    float depth = (float) (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++) 
    { 
      mMatrices[i].reset(); 
      src[0] = i * mFlodWidth; 
      src[1] = 0; 
      src[2] = src[0] + mFlodWidth; 
      src[3] = 0; 
      src[4] = src[2]; 
      src[5] = h; 
      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 ? h - depth : h; 
      dst[6] = dst[0]; 
      dst[7] = isEven ? h : h - depth; 
 
      for (int y = 0; y < 8; y++) 
      { 
        dst[y] = Math.round(dst[y]); 
      } 
 
      mMatrices[i].setPolyToPoly(src, 0, dst, 0, src.length >> 1); 
    } 
  } 
 
  private Canvas mCanvas = new Canvas(); 
  private Bitmap mBitmap; 
  private boolean isReady; 
 
  @Override 
  protected void dispatchDraw(Canvas canvas) 
  { 
 
    if (mFactor == 0) 
      return; 
    if (mFactor == 1) 
    { 
      super.dispatchDraw(canvas); 
      return; 
    } 
    for (int i = 0; i < mNumOfFolds; i++) 
    { 
      canvas.save(); 
 
      canvas.concat(mMatrices[i]); 
      canvas.clipRect(mFlodWidth * i, 0, mFlodWidth * i + mFlodWidth, 
          getHeight()); 
      if (isReady) 
      { 
        canvas.drawBitmap(mBitmap, 0, 0, null); 
      } else 
      { 
        // super.dispatchDraw(canvas); 
        super.dispatchDraw(mCanvas); 
        canvas.drawBitmap(mBitmap, 0, 0, null); 
        isReady = true; 
      } 
      canvas.translate(mFlodWidth * i, 0); 
      if (i % 2 == 0) 
      { 
        canvas.drawRect(0, 0, mFlodWidth, getHeight(), mSolidPaint); 
      } else 
      { 
        canvas.drawRect(0, 0, mFlodWidth, getHeight(), mShadowPaint); 
      } 
      canvas.restore(); 
    } 
  } 
    //...dispatchDraw 
 
  public void setFactor(float factor) 
  { 
    this.mFactor = factor; 
    updateFold(); 
    invalidate(); 
  } 
 
  public float getFactor() 
  { 
    return mFactor; 
  } 
 
}