Android FoldingLayout folding layout principle and implementation (1). android code implements Layout
Reprinted please indicate the source: bytes]
1. Overview
The blog about FoldingLayout and the github address. I feel very nice, so I spent some time researching and writing this blog. This blog will show you how to analyze the basic principles and implement our FoldingLayout step by step. Of course, if you are competent, you can directly download the code on github for learning.
Blogs are divided into the following parts:
1. setPolyToPoly of Matrix
2. Use gradient and shadow on Images
3. The initial implementation of FoldingLayout allows you to fold images (you can control the number of folds and draw shadows)
4. Introduce a gesture so that the finger can be folded by FoldingLayout.
5. Fold-over slide with DrawerLayout
6. Folding side slide with SlidingPaneLayout
OK, paste the following part:
Change the image corresponding to the above 3, sister is good ~
OK, corresponding to the above 4.
Corresponding to the above 5.
OK. Select some images. Otherwise, it will take up too much space.
Next, we will learn it in order ~~~
2. setPolyToPoly of Matrix
To fold, the most important thing is the core principle. The first step we need to know is how to display a normal picture with an offset.
In fact, the essence lies in the setPolyToPoly method of Matrix.
public boolean setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex,int pointCount)
Let's take a brief look at the parameters of this method. src represents the coordinates before the transformation; dst represents the coordinates after the transformation; transformation from src to dst, you can use srcIndex and dstIndex to specify the point of the first transformation. Generally, it is possible to set a bit 0. PointCount indicates the number of points of the supported conversion coordinates. A maximum of four conversion coordinates are supported.
If you don't understand it, let's take a simple example:
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);}}}
We have compiled a PolyToPolyView as the main view of our Activity.
In PolyToPolyView, we loaded an image and initialized our Matrix. Note that src and dst are the four vertices of normal slices. Dst makes some modifications to the y coordinate of the two vertices on the right of the image.
You can mark the position of src and dst on the paper.
Finally, we plot the image in onDraw. The effect is as follows:
If you have drawn four dst points on the paper, you must be familiar with this result.
We can see that we have implemented image skew through matrix. setPolyToPoly, so we will introduce it to the folding case. If we fold the image twice, do you have any ideas? If not, let's continue to look down.
3. Introduce shadow
In fact, it is quite convenient to present the shadow after initial folding. But to reduce the simplicity of its understanding, we will extract the Shadow first.
If we want to add a shadow, we hope that:
We can see that we have added a shadow to the left. How can we achieve this?
We mainly use LinearGradient to add a layer of gradient from black to transparent from left to right.
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 upload; private LinearGradient release; 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); // draw the shadow canvas. drawRect (0, 0, mBitmap. getWidth (), mBitmap. getHeight (), mShadowPaint); canvas. restore ();}}}
Focus on mShadowPaint, mShadowGradientShader, and mShadowGradientMatrix. One is a paint brush. We set a gradient Shader for the paint brush. The Shader parameter is
New LinearGradient (0, 0, 0.5f, 0, Color. BLACK, Color. TRANSPARENT, TileMode. CLAMP );
Starting point (), ending point (f, 0); color from BLACK to transparent; mode is CLAMP, that is, stretch the last pixel.
Here you may ask, this is how to set a gradient for the 0.5 pixel region. No, right, yes. Let's continue to see that we use setLocalMatrix (mShadowGradientMatrix); and this
MShadowGradientMatrix expands mBitmap with coordinates. getWidth () times, that is, the gradient area is (0.5f * mBitmap. getWidth (), 0): The size of half a graph. What about the second half?
The second half uses the CLAMP mode, which is transparent to stretch.
For details about Shader and setLocalMatrix usage, refer to: Android BitmapShader practices circular and rounded image
4. Initial folding
After learning about the principle and shadow rendering, we will start to learn how to hide the shadow. Our goal is:
The sister folded into eight parts, and the shadow range is: Each of the left and right sides of the sink, black translucent cover on the left side, black to transparent shadow on the right side of the short distance (you can take a closer look ).
Now, you can simply tilt and add shadows to the image. The only difficulty is how to divide the image into fast ones. I believe that everyone will fold each image.
In fact, we can draw this image multiple times, such as the first draw down and the second draw online skew. This is similar to the implementation of our title 2. We only need to use setPolyToPoly.
If you draw a graph multiple times, it is definitely not the whole graph. For example, for the first time, I only want to display the first image. Therefore, we also need clipRect, it should have been unveiled ~~~
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; /*** total width after image folding */private int mTranslateDis;/*** ratio of the total width after image folding to the original image width */private float mFacto R = 0.8f;/*** Number of folding blocks */private int mNumOfFolds = 8; private Matrix [] mMatrices = new Matrix [mNumOfFolds]; private Bitmap mBitmap; /*** draw the black transparent area */private Paint mSolidPaint;/*** draw the shadow */private Paint mShadowPaint; private Matrix mShadowGradientMatrix; private LinearGradient mShadowGradientShader; /***** width of each block in the source image */private int mFlodWidth;/***** width of each block */private int mTranslateDisPerFlod; public PolyToPol YView (Context context) {super (context); mBitmap = BitmapFactory. decodeResource (getResources (), R. drawable. tanyan); // The total width of the collapsed mTranslateDis = (int) (mBitmap. getWidth () * mFactor); // The width of each block in the source image. mFlodWidth = mBitmap. getWidth ()/mNumOfFolds; // when collapsed, mTranslateDisPerFlod = mTranslateDis/mNumOfFolds; // initialize matrixfor (int I = 0; I <mNumOfFolds; I ++) {mMatrices [I] = new Matrix ();} mSolidPaint = new Paint (); int al Pha = (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); mShadow GradientShader. setLocalMatrix (mShadowGradientMatrix); mShadowPaint. setAlpha (alpha); // The height reduced by the vertical axis. The int depth = (int) Math is calculated by using the stock theorem. sqrt (mFlodWidth * mFlodWidth-mTranslateDisPerFlod * mTranslateDisPerFlod)/2; // conversion point float [] src = new float [NUM_OF_POINT]; float [] dst = new float [NUM_OF_POINT]; /*** each of the original images corresponds to each of the collapsed images. The direction is top left, top right, bottom right, and bottom left. You can draw them on the paper. */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); // draw mNumOfFolds for (int I = 0; I <mNumOfFolds; I ++) {canvas. save (); // apply the matrix to canvascanvas. concat (mMatrices [I]); // controls the displayed size canvas. clipRect (mFlodWidth * I, 0, mFlodWidth * I + mFlodWidth, mBitmap. getHeight (); // draw the image canvas. drawBitmap (mBitmap, 0, 0, null); // move the shadow canvas. translate (mFlodWidth * I, 0); if (I % 2 = 0) {// draw a Black canvas. drawRect (0, 0, mFlodWidth, mBitmap. getHeight (), mSolidPaint);} else {// draw the shadow canvas. drawRect (0, 0, mFlodWidth, mBitmap. getHeight (), mShadowPaint);} canvas. restore ();}}}}
In a simple explanation, the partial shadow is actually folded as follows:
1. initialize the conversion point. The comment here is very clear. You 'd better draw it on paper and mark each variable.
2. It is matrix. setPolyToPoly.
3. Use this matrix when drawing, and clipRect controls the display area (this area is also very simple, the first block to the last part of the source image). It is best to draw a bitmap.
Shadow. Here you can change to a brighter image ~~
Well, due to the length of the article, the rest of the content will continue to be completed in the next article. The next article will show how to fold a simple image into a folding effect for all controls in a layout, and introduce gestures,
Combined with DrawerLayout and other applications to slide.
For effects similar to this, you must draw a painting with a pen or paper; otherwise, it is hard to understand.
Source code: Download
Group Number:429757068
Scan the Public Account (notify blogs, videos, and other notifications as soon as possible ):