I. Overview
inadvertently turned to Foldinglayout's introduction of the blog, as well as the GitHub address. Feel very nice ah, so spent a little time research and writing, this blog will take you from the most basic principle analysis, step-by-step realization of our foldinglayout, of course, if you are competent, you can directly download github code to learn.
Blogs are basically divided into the following sections:
1, the Matrix Setpolytopoly use
2. Use gradients and shadows on the picture
3, the initial foldinglayout realization, completes the picture the folding display (may control folds the number of times, contains the shadow the Drawing)
4, the introduction of gestures, fingers can be foldinglayout folding
5, the combination of drawerlayout to achieve folding sideslip
6, the combination of slidingpanelayout to achieve folding sideslip
OK, put down part of the effect chart:
Change map corresponding to the above 3, sister good
OK, corresponding to the above 4.
Corresponds to the above 5.
OK, select some of the pictures, or too much space.
So next, we will follow the order of study ~ ~ ~ ~
Second, the matrix of setpolytopoly use
to achieve folding, the most important thing is the principle of its core, then the first step we have to understand is how to put a normal display of the picture, so that it can be offset display.
In fact, the essence of the matrix is the Setpolytopoly method.
Public boolean setpolytopoly (float[] src, int srcindex, float[] DST, int dstindex,int pointcount) a simple look at the parameters of the method, SRC represents the coordinates before the transformation, DST represents the transformation of the coordinates, from the SRC to DST transformation, you can through the Srcindex and Dstindex to make the first transformation point, generally may set bit 0. Pointcount represents the number of supported transformation coordinates, up to 4.
If you don't understand, here's a simple example to take you through:
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 savedinstancest
ATE) {super.oncreate (savedinstancestate);
Setcontentview (This) (new Polytopolyview);
Class Polytopolyview extends View {private Bitmap mbitmap;
Private Matrix Mmatrix;
Public Polytopolyview {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);
}
}
}
We have written a polytopolyview as the main view of our activity.
In Polytopolyview, we loaded a picture, initialized our matrix, note src and DST two arrays, SRC is the normal picture of the 4 vertices. DST makes a slight modification to the y-coordinate of the two points on the right side of the picture.
You can mark the position of SRC and DST four points slightly on the paper.
In the end, we ondraw the image to draw, the effect is:
If you've been drawing a little bit of DST's four points on paper, you're not unfamiliar with this result.
We can see through the matrix.setpolytopoly to achieve the image of the tilt, then introduced to the folding situation, assuming that folding two times, we have ideas mody, consider, if not, continue to look down.
Iii. Introduction of Shadows
in fact, the shadow should be realized after the initial folding, this demo is actually more convenient, but in order to reduce the simplicity of its understanding, we first draw out the shadow to say.
Let's say we're going to add a shadow to the above picture, and the desired effect is this:
You can see that we have a little shadow added to the left, how to achieve it?
Mainly using LinearGradient, we add a layer from left to right to the gradient from black to transparent.
public class Matrixpolytopolywithshadowactivity extends activity {@Override protected void onCreate (Bundle save
Dinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (This) (new Polytopolyview);
Class Polytopolyview extends View {private Bitmap mbitmap;
Private Matrix Mmatrix;
Private Paint Mshadowpaint;
Private Matrix Mshadowgradientmatrix;
Private LinearGradient Mshadowgradientshader;
Public Polytopolyview {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); Draw Shadow Canvas.drawrect (0, 0, mbitmap.getwidth (), Mbitmap.gethei
Ght (), mshadowpaint);
Canvas.restore ();
}
}
}
Focus on Mshadowpaint,mshadowgradientshader,mshadowgradientmatrix One is a brush, we set a gradient for the brush shader, this shader parameter is
New LinearGradient (0, 0, 0.5f, 0,color.black, Color.transparent, Tilemode.clamp);
The starting point (0,0), the end point (0.5f,0), the color from black to transparent, the pattern is clamp, that is, the last pixel is stretched.
Here, you might ask, this is a gradient for a 0.5-pixel area, no, uh, yes, keep looking. Next we use Setlocalmatrix (Mshadowgradientmatrix);
Mshadowgradientmatrix and coordinates are enlarged mbitmap.getwidth () times, which means that the area where the gradient is now set (0.5f*mbitmap.getwidth (), 0) is half the size of the picture, then the second half of the picture?
The second half applies clamp mode, stretching the transparency.
About shader, Setlocalmatrix and other uses can also refer to: Android bitmapshader actual combat to achieve circular, fillet picture
Iv. Initial realization of folding
after understanding the principles and the rendering of shadows, the next step is to start learning to really fold, and our goal is to:
Sister folded into 8 parts, and the range of Shadow is: each sink down the left and right sides of the slit, the left side of the black translucent cover, the right-hand side of the short black to Transparent shadow (you can look carefully).
Now in fact, we will simply tilt the picture and add shadows, then the only difficulty is how to divide a picture into a lot of fast, I believe that every folded everyone will.
In fact, we can draw the graph several times, such as the first draw downward tilt, the second draw the online tilt, so it is similar to the implementation of our Heading 2, just use Setpolytopoly.
So many times, each display is definitely not a whole picture, for example, the first time, I just want to show the first piece, so we still need to cliprect the cooperation, said this, should and revealed the secret ~ ~ ~
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 (This) (new Polytopolyview);
Class Polytopolyview extends View {private static final int num_of_point = 8;
/** * Picture of the total width of the folded * * * private int mtranslatedis;
/** * After folding the total width and the original width of the ratio * * private float mfactor = 0.8f; Number of/** * Folding block * * Private int MnumOffolds = 8;
Private matrix[] mmatrices = new Matrix[mnumoffolds];
Private Bitmap Mbitmap;
/** * Draw the transparent area of black * * * private Paint msolidpaint;
/** * Draw Shadow * * private Paint mshadowpaint;
Private Matrix Mshadowgradientmatrix;
Private LinearGradient Mshadowgradientshader;
/*** * The width of each piece of the original * * * private int mflodwidth;
/** * Folding, the width of each block * * * private int mtranslatedisperflod;
Public Polytopolyview {Super (context);
Mbitmap = Bitmapfactory.decoderesource (Getresources (), R.drawable.tanyan);
The total width after folding is Mtranslatedis = (int) (Mbitmap.getwidth () * mfactor);
The width of each piece of the original artwork mflodwidth = Mbitmap.getwidth ()/mnumoffolds;
When folded, the width of each block mtranslatedisperflod = Mtranslatedis/mnumoffolds; Initializes the 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); The height at which the longitudinal axis is reduced, with the Pythagorean theorem computed under the int depth = (int) math.sqrt (mflodwidth * Mflodwidth-mtranslatedisperflod * Mtrans
Latedisperflod)/2;
Conversion point float[] src = new Float[num_of_point];
float[] DST = new Float[num_of_point]; /** * Each piece of the original image, corresponding to the folding of each piece, the direction of the upper left, right, lower right, lower left, everyone on the paper themselves painted under the * 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); Draw Mnumoffolds for (int i = 0; i < mnumoffolds; i++)
{Canvas.save ();
The matrix is applied to canvas canvas.concat (mmatrices[i]);
Control display Size Canvas.cliprect (mflodwidth * I, 0, mflodwidth * i + mflodwidth, mbitmap.getheight ());
Draw Pictures Canvas.drawbitmap (mbitmap, 0, 0, NULL);
Move the drawing Shadow Canvas.translate (Mflodwidth * i, 0);
if (i% 2 = 0) {//Draw black cover Canvas.drawrect (0, 0, Mflodwidth, Mbitmap.getheight (),
Msolidpaint); }else {//Draw shadow Canvas.drawrect (0, 0, Mflodwidth, Mbitmap.getheight (), Mshado
Wpaint);
} canvas.restore ();
}
}
}
}
The simple explanation, does not go to the Tube draws the shadow the part, actually folds is:
1, initialize the conversion point, the comment here is very clear, everybody better draw on the paper, mark each variable.
2. For Matrix.setpolytopoly
3, the use of the matrix when drawing, and Cliprect control display area (this area is also very simple, the first piece to the last piece), the best is to draw the bitmap.
Shadow Here you can change a bright point of the picture to see ~ ~
V. THE realization of Foldlayout
1. Realize
Our idea is this, our foldlayout can only have a direct child element, of course this child element can be relativelayout something, can be very complex. Then as long as the outer cover of our foldlayout, we can achieve folding effect.
So in other words, our foldlayout folding effect shows the "look" of its child elements, so how or is this "look"?
As we all know, our ViewGroup has a method called: Dispatchdraw (Canvas) is mainly used to draw child elements, we can set the matrix for this Canvas, and repeat call Dispatchdraw (Canvas) To achieve the final results similar to the last blog, so that the completion of our feasibility analysis.
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;
/** * Picture of the total width of the folded * * * 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, NULL);
Public Foldlayout (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 = Getchilda
T (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;
}
}
The above code should not be unfamiliar to you, just the change from view to a single picture to ViewGroup.
Since it is ViewGroup, onmeasure,onlayout and so on. Measurement and layout depend entirely on its child view. The
then takes something that needs to be initialized, and does not depend on the width, such as the brush or anything, in the construct; the onlayout, which is dependent on the width, calls the Updatefold (), and initializes the related code. The code in the
Updatefold is not unfamiliar to us because it is basically consistent with the previous blog. The main thing is to compute mflodwidth,mtranslatedisperflod and to iterate through the set of Mnumoffolds to initialize our matrix. After the
Matrix completes Setpolytopoly, we can then draw:
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 ();
}
}
Mfactor mainly represents the ratio of the total width to the original width after folding, the default is 1 when not folded, so call Super.dispatchdraw (canvas) directly;
So if it's 0, it's all folded up, and we'll go directly if (mfactor = 0) return;
If the (0,1) between the normal situation, if you remember the last blog content, but is based on the Mnumoffolds loop to draw several times, each time you set the matrix, the use of cliprect can realize our folding.
Here you see, I called the first time when I was drawing:
Super.dispatchdraw (Mcanvas);
Canvas.drawbitmap (mbitmap, 0, 0, null);
IsReady = true;
In our own new Mbitmap also draws a picture, because I do not want to call Super.dispatchdraw every time, so as long as isready=true, We can then invoke the draw Mbitmap and avoid calling Super.dispatchdraw ().
Draw complete picture, is to draw the black cover and Shadow ~ ~, is two rect of drawing.
After completing these, we can simply sit down to test and use our layout.
2, testing
Layout file:
<com.zhy.view.foldlayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:id=" @+id/id_fold_layout "
android:layout_width=" Match_parent
" android:layout_height= "Match_parent" >
<imageview
android:layout_width= "Match_parent"
Android : layout_height= "match_parent"
android:scaletype= "Fitxy"
android:src= "@drawable/xueshan"/>
< /com.zhy.view.foldlayout>
Activity
Package com.zhy.sample.folderlayout;
Import Com.zhy.view.FoldLayout;
Import Android.animation.ObjectAnimator;
Import Android.annotation.SuppressLint;
Import android.app.Activity;
Import Android.os.Bundle;
public class Foldlayoutactivity extends activity
{
private foldlayout mfoldlayout;
@Override
protected void onCreate (Bundle savedinstancestate)
{
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_fold);
Mfoldlayout = (foldlayout) Findviewbyid (r.id.id_fold_layout);
/*mfoldlayout.post (New Runnable ()
{
@SuppressLint ("Newapi")
@Override public
Void Run ()
{
objectanimator.offloat (mfoldlayout, "factor", 1, 0, 1)
. Setduration (5000). Start ();
}
}); */
}
}
Now the effect is that we change the mfactor to 0.6f:
Of course, it was static at the moment, but we succeeded in drawing a static graph to flodlayout.
Next we add the touch folding function to the fingers.
VI. touchfoldlayout
1. Realize
Add Touch function is actually very simple, our drawing relies on mfactor this value, we just in ontouchevent inside to accumulate the finger to move the distance, and then dynamically update this value on it.
Package Com.zhy.view;
Import Android.content.Context;
Import Android.graphics.Canvas;
Import Android.util.AttributeSet;
Import Android.view.GestureDetector;
Import android.view.MotionEvent;
public class Touchfoldlayout extends Foldlayout {private Gesturedetector mscrollgesturedetector;
Public Touchfoldlayout (context, AttributeSet attrs) {Super (context, attrs);
Init (context, attrs); {mscrollgesturedetector = new Gesturedetector (context context, AttributeSet attrs) (Contex
T, new Scrollgesturedetector ()); @Override public boolean ontouchevent (Motionevent event) {return mscrollgesturedetector.ontouchevent (EV
ENT);
private int mtranslation =-1; @Override protected void Dispatchdraw (Canvas Canvas) {if (mtranslation = = 1) mtranslation = GetWidth ()
;
Super.dispatchdraw (canvas); Class Scrollgesturedetector extends Gesturedetector.simplEongesturelistener {@Override public boolean ondown (Motionevent e) {return true;
@Override public boolean onscroll (Motionevent E1, motionevent E2, float Distancex, float distancey)
{mtranslation-= Distancex;
if (Mtranslation < 0) {mtranslation = 0;
} if (Mtranslation > GetWidth ()) {mtranslation = GetWidth ();
float factor = Math.Abs (((float) mtranslation)/((float) getwidth ());
Setfactor (factor);
return true;
}
}
}
We choose to inherit foldlayout, rewrite its ontouchevent, and then get the moving distance through Mscrollgesturedetector, and the final and the width do more than deserve to our factor, and then call Setfactor to make the change.
public void Setfactor (float factor)
{
this.mfactor = factor;
Updatefold ();
Invalidate ();
}
OK, this completes the introduction of the finger control.
2, testing
Now change the class in the layout file:
<com.zhy.view.touchfoldlayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= " Http://schemas.android.com/tools "
android:id=" @+id/id_fold_layout "
android:layout_width=" match_parent "
android:layout_height=" match_parent ">
<imageview
android:layout_width=" Match_parent "
android:layout_height= "match_parent"
android:scaletype= "Fitxy"
android:src= "@drawable/xueshan" />
</com.zhy.view.TouchFoldLayout>
Activity unchanged, look at the test effect: (Remember to change the mfactor to the default value of 1.0f before testing)
So far we have finished the effect of cool, but we also need to apply to specific cases, otherwise it is special effects, it is necessary to duang.
So we first consider adding to the Sideslip menu, the Sideslip menu has a lot of options, Google also offers two, one is Drawerlayout, the other is slidingpanelayout.
The following shows how to integrate the two layouts separately.
First look at the slidingpanelayout, because Drawerlayout still have some place to revise.
Eight, Foldslidingpanellayout
1. Realize
For the use of slidingpanelayout, should be no problem, it is the layout of the root layout of the file set to Slidingpanelayout, and then put two sub layout, one represents the Sideslip menu, a representative content area.
So, how do we integrate into the Slidingpanelayout species? There are roughly two ways:
1, our folding menu as the root layout of the sideslip layout, and then in the activity species to monitor setpanelslidelistener make changes.
2, directly inherit Slidingpanelayout, and its internal will child (0) wrapped up with foldlayout, and then listen to Setpanelslidelistener.
Here we choose the latter, because the latter is packaged, and can be used directly in accordance with the Slidingpanelayout original way, do not need to do unnecessary operations.
Look at the code below:
Package Com.zhy.view;
Import Android.content.Context;
Import Android.support.v4.widget.SlidingPaneLayout;
Import Android.util.AttributeSet;
Import Android.view.View;
Import Android.view.ViewGroup; public class Foldslidingpanellayout extends Slidingpanelayout {public Foldslidingpanellayout (context context, Attribu
Teset attrs) {Super (context, attrs);
} @Override protected void Onattachedtowindow () {Super.onattachedtowindow ();
View child = Getchildat (0);
if (child!= null) {Removeview;
Final Foldlayout foldlayout = new Foldlayout (GetContext ());
Foldlayout.setanchor (0);
Foldlayout.addview (child);
Viewgroup.layoutparams Laypar = Child.getlayoutparams ();
AddView (foldlayout, 0, Laypar); Setpanelslidelistener (New Panelslidelistener () {@Override public void onpanelslide (Vie W arg0, float arg1) {Foldlayout.setfactoR (ARG1); @Override public void onpanelopened (View arg0) {//TODO auto-generated
Method stub} @Override public void onpanelclosed (View arg0) {
}
});
}
}
}
We inherit the Slidingpanelayout, then in the Onattachedtowindow, take out the sideslip layout, wrap a foldlayout on the outer layer, and monitor the setpanelslidelistener inside. In the onpanelslide species according to the parameters, to dynamically set the Foldlayout factor.
2, Test
(1), layout file
<com.zhy.view.foldslidingpanellayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns: tools= "Http://schemas.android.com/tools" "
android:id=" @+id/id_drawerlayout "
android:layout_width=" match _parent "
android:layout_height=" match_parent ">
<fragment
android:id=" @+id/id_left_menu
" Android:name= "Com.zhy.sample.folderlayout.LeftMenuFragment"
android:layout_width= "240DP"
android: layout_height= "Match_parent"/>
<relativelayout
android:layout_width= "Match_parent"
android:layout_height= "Match_parent" >
<imageview
android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
android:scaletype= "Fitcenter"
android:src= "@drawable/xueshan" >
</RelativeLayout>
</com.zhy.view.FoldSlidingPanelLayout>
Our menu uses a fragment.
(2), menu layout
package com.zhy.sample.folderlayout;
Import Android.os.Bundle;
Import android.support.v4.app.Fragment;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.ArrayAdapter;
Import Android.widget.ListView;
public class Leftmenufragment extends Fragment {private ListView mmenus;
Private string[] Mmenuitemstr = {"Bear", "Bird", "Cat", "tigers", "Panda"};
@Override public View Oncreateview (layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) {
View view = Inflater.inflate (R.layout.fragment_left_menu, container, false);
Mmenus = (ListView) View.findviewbyid (R.ID.ID_LEFT_MENU_LV);
Mmenus.setadapter (New arrayadapter<string> (Getactivity (), R.layout.item_left_menu, mMenuItemStr));
return view; }
}
<listview xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:id=" @+id/id_left_menu_lv "
android:layout_width=" 240DP "
android: layout_height= "Match_parent"
android:layout_gravity= "Start"
android:background= "#FFF"
android: Choicemode= "Singlechoice"/>
Item is a textview, do not paste ~ ~
3. Activity
Package com.zhy.sample.folderlayout;
Import Android.os.Bundle;
Import android.support.v4.app.FragmentActivity;
public class Slidingpanellayoutsampleactivity extends fragmentactivity
{
@Override
protected void OnCreate (Bundle arg0)
{
super.oncreate (arg0);
Setcontentview (r.layout.activity_slidingpanellayout);
}
Well, there is nothing to do in the activity, the introduction of the layout file will do.
Better look at the effect chart.
3. Effect drawing
Here the number of menu blocks is more, you can modify the operation.
OK, here we will foldlayout and slidingpanelayout integration, the construction of such a personality sideslip.
It is best to have the integration with Drawerlayout.
Nine, Folddrawerlayout
1. Realize
About the use of drawerlayout, similar to the above Slidingpanelayout, write a layout file, the introduction of activity is good. We still use the above method 2 to implement a drawerlayout subclass.
Package Com.zhy.view;
Import Android.content.Context;
Import Android.support.v4.view.GravityCompat;
Import Android.support.v4.view.ViewCompat;
Import Android.support.v4.widget.DrawerLayout;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import android.view.Gravity;
Import Android.view.View;
Import Android.view.ViewGroup;
public class Folddrawerlayout extends Drawerlayout {private static final String TAG = "Drawerfoldlayout";
Public Folddrawerlayout (context, AttributeSet attrs) {Super (context, attrs);
} @Override protected void Onattachedtowindow () {Super.onattachedtowindow ();
Final int childcount = Getchildcount ();
for (int i = 0; i < ChildCount. i++) {final View child = Getchildat (i);
if (ISDRAWERVIEW2 (child)) {LOG.E (TAG, ' at ' + i);
Foldlayout foldlayout = new Foldlayout (GetContext ()); <span style= "Font-family:arial, HelvetICA, Sans-serif; " >foldlayout</span><span style= "font-family:arial, Helvetica, Sans-serif;"
>.setanchor (1);</span> removeview (child);
Foldlayout.addview (child);
Viewgroup.layoutparams Laypar = Child.getlayoutparams ();
AddView (Foldlayout, I, Laypar); } setdrawerlistener (New Drawerlistener () {@Override public void ondrawerstatechanged (i NT arg0) {//TODO auto-generated method stub} @Override public void Ondrawersli De (View Drawerview, float slideoffset) {if (Drawerview instanceof foldlayout) {Fol
Dlayout foldlayout = ((foldlayout) drawerview);
LOG.E (TAG, "slideoffset =" + Slideoffset);
Foldlayout.setfactor (Slideoffset);
@Override public void ondraweropened (View arg0) {} @Override
public void ondrawerclosed (View arg0) {
}
});
Boolean isDrawerView2 (View child) {final int gravity = ((layoutparams) Child.getlayoutparams ()). Gravity;
Final int absgravity = gravitycompat.getabsolutegravity (Gravity, viewcompat.getlayoutdirection (child)); Return (Absgravity & (Gravity.left |
gravity.right))!= 0;
}
}
See this, you might think, and then just like Slidingpanelayout, write a layout file? Not really, if you do, you'll find it hard to pull it out because it's like this:
Drawelayout's sideslip menu, such as we pull out 50%, then normally show the right side of the sideslip layout 50%, But if this 0.5 is set to our factor, it will shrink the layout to 50% and on the left.
cause, you pull 50% actually still can't see, because fold to the left 50% go. There are still two solutions:
(1), combine attribute animation, do offset, specific reference: Android drawerlayout high Imitation QQ5.2 two-way sideslip menu
(2), let our folding, contraction to the final position can be controlled, we now all to the most coordinate contraction, If it can be set to the far right, then this example will be fine.
2, introducing anchor
We introduce a manchor variable, a value range [0,1], to control where the foldlayout ultimately collapses. In fact, the modified code is relatively small, I paste the modified code:
" private void Updatefold () {//... float anchorpoint = Manchor * W;
float Midfold = (anchorpoint/mflodwidth); for (int i = 0; i < Mnumoffolds i++) {//Introducing anchor dst[0] = (Anchorpoint > I * mflodwidth)? anch
Orpoint + (i-midfold) * Mtranslatedisperflod:anchorpoint-(midfold-i) * MTRANSLATEDISPERFLOD; DST[2] = (Anchorpoint > (i + 1) * mflodwidth)? Anchorpoint + (i + 1-midfold) * Mtranslatedisperflod:anchorpoint-(Midfold-i-1) * Mtranslat Edisperflod; }
}
The only change is dst[0] and dst[2] coordinates, of course, after the introduction of anchor, you need to determine whether the original coordinates are less than anchorpoint, if less than the need to add some offsets, greater than the reverse.
Remember:
public void Setanchor (float anchor)
{
this.manchor = anchor;
Updatefold ();
Invalidate ();
}
Open this line of code for the above folddrawerlayout: Foldlayout.setanchor (1), and make the last merge position to the right.
Use the way, now is to write a good layout file, we directly use slidingpanelayout that layout file, change a root layout class on the line.
3. Effect drawing