Implementation of the implementation curve of the principle of the Android paging effect, and the implementation of the android paging Effect

Source: Internet
Author: User

Implementation of the implementation curve of the principle of the Android paging effect, and the implementation of the android paging Effect

Respect Original reprinted Please note: From AigeStudio (http://blog.csdn.net/aigestudio) Power by Aige infringement must be investigated!

ArtilleryTown Building

In the previous section, we introduced a line to implement the page folding and flip effect. With the basis of the previous two sections, the implementation of the curve can be very simple. Why do we say this? Because the curve is nothing more than adding the implementation of the curve to the Path based on the line, which only affects our Region, other events, such as sliding computing, are almost unchanged, right? To put it bluntly, it is to update the existing line View, although it is a transformation, but how should we start? First, let's take a look at the effect of page turning in reality? If you have a book, a book, or even a piece of paper around you and try to flip it in different ways, you will find that apart from the limitations mentioned in the previous two sections, there are also some special phenomena:

1. The turning area is a radian area on the side:


However, we will ignore the radians shown in the first section, because we cannot see the radians from the top-down perspective. So ~ We force it to be parallel to the page:


2. Based on the distance between the drag and drop points and the page height, we can get different degrees of curvature:


However, what we are looking down at is that the curve has different radians:


Similarly, according to the first section, in order to simplify the problem, we regard the drag-and-drop distance from the height of the page as a value so that the starting point of the curve we are looking down at starts from the point of intersection of the control:


3. As mentioned at the end of the previous section, the image will have similar distortion effects in the curved area.

OK. A rough analysis is like this. We can draw the following analysis chart based on the analysis results:


From the analysis above, we can see that DB = 1/4OB, FA = 1/4OA, and vertices F and D are two curves respectively (if there is no special declaration, the curve we call is the starting point of the besell curve, the same below) (of course, you can also say that the end does not matter). At this moment, we take points A and B as the control points of the curve and use them as the endpoints for line segments AG and BC along the X axis and Y axis, and AG = AF, BC = BD, respectively, then point G and C are respectively the end points of the curve. In this way, our two second-order besell curves are very special, such as the curve DC, it consists of the starting point D, C, and control point B, while BD = BC, that is, the triangle BDC is an isosceles triangle, and further it is equal to the two control arm of the curve DC, further, we can infer that the vertex J of the curve DC must be on the center vertical line of the straight line DC, furthermore, based on the second-order besell curve formula described in "custom controls are actually very simple 5/12", we can conclude that if and only when t = 0.5, the endpoint of the curve will be on vertex J, therefore, we can obtain the vertex coordinates of the curve very simply. Well, YY belongs to YY. We still need to return to specific operations. First, we need to calculate the coordinates of points G, F, D, and C. These four coordinates are also quite easy, take the coordinate of point F for example, we use point F as the vertical lines of OM and AM respectively:


Because FA = 1/4OA, we can obtain the x coordinate Fx = a + 3/4MA of point F, y coordinate Fy = B + 3/4OM, the x coordinate Gx of the gpoint is a + MA-1/4x, and the other two points D and C are not involved. How can this be reflected in the code? First, to make it easier to observe the effect, comment out the image:

/** If the coordinate point is at the origin (that is, when no touch occurs), draw the first page */if (mPointX = 0 & mPointY = 0) {// canvas. drawBitmap (mBitmaps. get (mBitmaps. size ()-1), 0, 0, null); return;} // omitting a large amount of code // drawBitmaps (canvas );
And draw lines:

canvas.drawPath(mPath, mPaint);
In the previous section, we divided the Path into two types:

if (sizeLong > mViewHeight) {//…………………………} else {//…………………………}
Similarly, we also process two cases separately, so the curve at the top of the control is invisible when we are targeting sizeLong> mViewHeight. We only need to consider the curve at the bottom:

// Calculate the curve start point float startXBtm = btmX2-CURVATURE * sizeShort; float startYBtm = mViewHeight; // calculate the curve end point float endXBtm = mPointX + (1-CURVATURE) * (tempAM ); float endYBtm = mPointY + (1-CURVATURE) * mL; // calculate the curve control point float controlXBtm = btmX2; float controlYBtm = mViewHeight; // calculate curve vertex float gradient = 0.25F * startXBtm + 0.5F * controlXBtm + 0.25F * endXBtm; float bezierPeakYBtm = 0.25F * startYBtm + 0.5F * controlYBtm + 0.25F * ybendtm; /** generate a quadrilateral path with curves */mPath. moveTo (startXBtm, startYBtm); mPath. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPath. lineTo (mPointX, mPointY); mPath. lineTo (topX1, 0); mPath. lineTo (topX2, 0); mPath. lineTo (bezierPeakXBtm, bezierPeakYBtm );
The actual effect of this part is as follows:


PS: To facilitate your understanding of the parameters, I give a reference to the coordinates of each vertex, which is easy to understand. The actual process can omit this step to simplify the code.

When sizeLong <= mViewHeight, there is not only a curve at the bottom, but also on the right:

/** Calculated parameter */float leftY = mViewHeight-sizeLong; float btmX = mViewWidth-curve; // calculates the curve starting point float startXBtm = btmX-CURVATURE * cursor; float startYBtm = mViewHeight; float startXLeft = mViewWidth; float startYLeft = leftY-CURVATURE * sizeLong;/** limit the left curve start point */if (startYLeft <= 0) {startYLeft = 0 ;} /** limit the right curve start point */if (startXBtm <= 0) {startXBtm = 0;} // calculate the curve end point float endXBtm = mPointX + (1-CURVATURE) * (tempAM); float endYBtm = mPointY + (1-CURVATURE) * mL; float endXLeft = mPointX + (1-CURVATURE) * mK; float endYLeft = mPointY-(1-CURVATURE) * (sizeLong-mL); // calculate the curve control point float controlXBtm = btmX; float controlYBtm = mViewHeight; float controlXLeft = mViewWidth; float controlYLeft = leftY; // calculates the curve vertex float gradient = 0.25F * startXBtm + 0.5F * controlXBtm + 0.25F * gradient; float gradient = 0.25F * Gradient + 0.5F * controlYBtm + 0.25F * endYBtm; float bezierPeakXLeft = 0.25F * startXLeft + 0.5F * controlXLeft + 0.25F * endXLeft; float bezierPeakYLeft = 0.25F * startYLeft + 0.5F * controlYLeft + 0.25F * endYLeft; /** generate a triangle path with a curve */mPath. moveTo (startXBtm, startYBtm); mPath. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPath. lineTo (mPointX, mPointY); mPath. lineTo (endXLeft, endYLeft); mPath. quadTo (controlXLeft, controlYLeft, startXLeft, startYLeft );
The effect is as follows:


With the Path, we should consider how to convert it to Region. In this process, another problem is that the curve Path is not like the linear Path in the previous section, and we can easily obtain the range and Region, because our collapsed area is actually like this:


The red path area, which is the area we fold. In fact, we plot the second-order besell curve for convenience of calculation, that is to say, in addition to the red lines, our Path also contains the blue lines, right? So the question is, how can we "Remove" These two parts? In fact, there are many methods. We can generate only half a curve During computation. This is a method we use pure computation, I remember that I mentioned at the beginning of this series that there are two ways to implement the paging effect. One is pure computing, and the other is the combination of graphics. How can we combine them? Here we do not need to use the pure computing method for the calculation of the region. We try to use a combination of images. First, convert the Path to Region to see what it looks like:

Region region = computeRegion(mPath);canvas.clipRegion(region);canvas.drawColor(Color.RED);// canvas.drawPath(mPath, mPaint);
The effect is as follows:


We can see that there is no closed Path to form the Region effect. The fact is that there is a big gap with the Region we need. First, the two-month semi-circle is redundant, and the second is missing one in the visual test:


For example, the blue one, how should we "fill" this one? Using the idea of graphic combination, we try to add a rectangle for the Region:


Then, if the result is less than two months of semi-circle collection, isn't it? This part of the code is greatly changed. I will post the code first:

If (sizeLong> mViewHeight) {// calculate ...... Amount ...... AN edge ~ by Graph ~ Float an = sizeLong-mViewHeight; // The MN edge float largerTrianShortSize of the triangle AMN = an/(sizeLong-(mViewHeight-mPointY) * (mViewWidth-mPointX ); // float smallTrianShortSize = an/sizeLong * sizeShort;/** calculation parameter */float topX1 = mViewWidth-largertrian1_size; float topX2 = mViewWidth-Timeout; float btmX2 = mViewWidth-sizeShort; // calculates the curve starting point float startXBtm = btmX2-CURVATURE * sizeShort; float startYBtm = mViewHeight; // calculate the curve end point float endXBtm = mPointX + (1-CURVATURE) * (tempAM); float endYBtm = mPointY + (1-CURVATURE) * mL; // calculate the curve control point float controlXBtm = btmX2; float controlYBtm = mViewHeight; // calculate the curve vertex float bezierPeakXBtm = 0.25F * startXBtm + 0.5F * controlXBtm + 0.25F * endXBtm; float bezierPeakYBtm = 0.25F * startYBtm + 0.5F * controlYBtm + 0.25F * endYBtm;/** generate a quadrilateral path with curves */mPath. moveTo (startXBtm, startYBtm); mPath. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPath. lineTo (mPointX, mPointY); mPath. lineTo (topX1, 0); mPath. lineTo (topX2, 0);/** backup region Path */mPathTrap. moveTo (startXBtm, startYBtm); mPathTrap. lineTo (topX2, 0); mPathTrap. lineTo (bezierPeakXBtm, bezierPeakYBtm); mPathTrap. close ();/** Path of the bottom half circle */mPathSemicircleBtm. moveTo (startXBtm, startYBtm); mPathSemicircleBtm. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPathSemicircleBtm. close ();/** generate the path containing the folding and next page * // It is useless to omit it temporarily. // calculate the mRegionSemicircle = computeRegion (mPathSemicircleBtm) in the semi-circular area of the month );} else {/** calculation parameter */float leftY = mViewHeight-sizeLong; float btmX = mViewWidth-sizeShort; // calculate the curve start point float startXBtm = btmX-CURVATURE * sizeShort; float startYBtm = mViewHeight; float startXLeft = cursor; float startYLeft = leftY-CURVATURE * sizeLong; // calculate the curve end float endXBtm = mPointX + (1-CURVATURE) * (tempAM ); float endYBtm = mPointY + (1-CURVATURE) * mL; float endXLeft = mPointX + (1-CURVATURE) * mK; float endYLeft = mPointY-(1-CURVATURE) * (sizeLong-mL); // compute the curve control point float controlXBtm = btmX; float controlYBtm = mViewHeight; float controlXLeft = mViewWidth; float controlYLeft = leftY; // calculate curve vertex float gradient = 0.25F * startXBtm + 0.5F * controlXBtm + 0.25F * endXBtm; float bezierPeakYBtm = 0.25F * startYBtm + 0.5F * controlYBtm + 0.25F * ybendtm; float bezierPeakXLeft = 0.25F * startXLeft + 0.5F * controlXLeft + 0.25F * endXLeft; float bezierPeakYLeft = 0.25F * startYLeft + 0.5F * controlYLeft + 0.25F * endYLeft; /** limit the right curve start point */if (startYLeft <= 0) {startYLeft = 0;}/** limit the left curve start point at the bottom */if (startXBtm <= 0) {startXBtm = 0;}/** re-calculate the coordinates of the besell curve vertex Based on the limit point on the left at the bottom */float partOfShortLength = CURVATURE * sizeShort; if (btmX> =-mValueAdded & btmX <= partOfShortLength-mValueAdded) {float f = btmX/queues; float t = 0.5F * f; float bezierPeakTemp = 1-t; float temperature = bezierPeakTemp * bezierPeakTemp; float bezierPeakTemp2 = 2 * t * bezierPeakTemp; float temperature = t * t; temperature = * startXBtm + temperature * controlXBtm + temperature * endXBtm; signature = bezierPeakTemp1 * startYBtm + bezierPeakTemp2 * controlYBtm + bezierPeakTemp3 * endYBtm;}/** re-calculate the coordinates of the beiser curve vertex Based on the limit point on the right */float partOfLongLength = curv; if (leftY >=- mValueAdded & leftY <= partOfLongLength-mValueAdded) {float f = leftY/rows; float t = 0.5F * f; float bezierPeakTemp = 1-t; float temperature = bezierPeakTemp * bezierPeakTemp; float bezierPeakTemp2 = 2 * t * bezierPeakTemp; float temperature = t * t; temperature = optional * startXLeft + interval * controlXLeft + interval * endXLeft; bezierPeakYLeft = bezierPeakTemp1 * startYLeft + bezierPeakTemp2 * controlYLeft + bezierPeakTemp3 * endYLeft;}/** backup region Path */mPathTrap. moveTo (startXBtm, startYBtm); mPathTrap. lineTo (startXLeft, startYLeft); mPathTrap. lineTo (bezierPeakXLeft, bezierPeakYLeft); mPathTrap. lineTo (bezierPeakXBtm, bezierPeakYBtm); mPathTrap. close ();/** generate a triangle path with a curve */mPath. moveTo (startXBtm, startYBtm); mPath. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPath. lineTo (mPointX, mPointY); mPath. lineTo (endXLeft, endYLeft); mPath. quadTo (controlXLeft, controlYLeft, startXLeft, startYLeft);/** generate the Path */mPathSemicircleBtm of the half circle at the bottom of the month. moveTo (startXBtm, startYBtm); mPathSemicircleBtm. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPathSemicircleBtm. close ();/** generate the Path */mPathSemicircleLeft of the right half of the month. moveTo (endXLeft, endYLeft); mPathSemicircleLeft. quadTo (controlXLeft, controlYLeft, startXLeft, startYLeft); mPathSemicircleLeft. close (); /** generate the path containing the folding and next page * // It is not omitted for the moment./** calculate the bottom and right half-circle of two months */Region regionSemicircleBtm = computeRegion (mPathSemicircleBtm ); region regionSemicircleLeft = computeRegion (mPathSemicircleLeft); // merge mRegionSemicircle in the half-circle of two months. op (regionSemicircleBtm, regionSemicircleLeft, Region. op. UNION);} // The collapsed Region regioFlod = computeRegion (mPath) generated based on Path; // The alternate Region regionTrap = computeRegion (mPathTrap ); // Add the folded area and the backup area regioFlod. op (regionTrap, Region. op. UNION); // remove the half-circle area from the added area to obtain the final collapsed area regioFlod. op (mRegionSemicircle, Region. op. DIFFERENCE);/** fill the canvas according to the cropping area */canvas. clipRegion (regioFlod); canvas. drawColor (Color. RED );
One thing we did with the 200 line of code is to calculate the Path correctly. We also calculated the Path based on the previous two cases. In the first case, when sizeLong> mViewHeight, let's calculate the replacement area first:


Lines 46-49 of the above Code

/** Backup region Path */mPathTrap. moveTo (startXBtm, startYBtm); mPathTrap. lineTo (topX2, 0); mPathTrap. lineTo (bezierPeakXBtm, bezierPeakYBtm); mPathTrap. close ();
Then calculate the Path of the half circle at the bottom:


Lines 54-56

/** Bottom semi-circle Path */mPathSemicircleBtm. moveTo (startXBtm, startYBtm); parameters. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); closed. close ();
Add the current folding area and the backup area, and subtract the Path area of the half-circle to get the correct folding area. Lines 64 and 192-201 correspond to the Code:

// Calculate mRegionSemicircle = computeRegion (mPathSemicircleBtm) in the semi-circular area of the month );//.................. A large amount of code is omitted in the middle .................. // The folding Region regioFlod = computeRegion (mPath) generated based on Path; // The backup Region regionTrap = computeRegion (mPathTrap); // Add the folding Region and the backup Region regioFlod. op (regionTrap, Region. op. UNION); // remove the half-circle area from the added area to obtain the final collapsed area regioFlod. op (mRegionSemicircle, Region. op. DIFFERENCE );
In this case, our folding area is soy sauce purple:


In either case, it is a little more complicated. In addition to calculating the bottom, we also need to calculate the Path area on the right side, code 165-174:

/** Generate the Path */mPathSemicircleBtm of the half circle of the bottom month. moveTo (startXBtm, startYBtm); mPathSemicircleBtm. quadTo (controlXBtm, controlYBtm, endXBtm, endYBtm); mPathSemicircleBtm. close ();/** generate the Path */mPathSemicircleLeft of the right half of the month. moveTo (endXLeft, endYLeft); mPathSemicircleLeft. quadTo (controlXLeft, controlYLeft, startXLeft, startYLeft); mPathSemicircleLeft. close (); Calculation of the backup area, 147-151:/** backup area Path */mPathTrap. moveTo (startXBtm, startYBtm); mPathTrap. lineTo (startXLeft, startYLeft); mPathTrap. lineTo (bezierPeakXLeft, bezierPeakYLeft); mPathTrap. lineTo (bezierPeakXBtm, bezierPeakYBtm); mPathTrap. close (); Region conversion, 184-188:/** calculate the half-circle of the bottom and right sides */Region regionSemicircleBtm = computeRegion (mPathSemicircleBtm ); region regionSemicircleLeft = computeRegion (mPathSemicircleLeft); // merge mRegionSemicircle in the half-circle of two months. op (regionSemicircleBtm, regionSemicircleLeft, Region. op. UNION );
The final computation is the same as that in the first case. The results are as follows:


In combination with the two situations, we can get the following results:


Then, we need to calculate the "next page" area. Similarly, according to our explanation in the previous section, we first get the sum of the folding area and the next page area, and then subtract the folding area to get the area of the next page:

mRegionNext = computeRegion(mPathFoldAndNext);mRegionNext.op(mRegionFold, Region.Op.DIFFERENCE);
The rendering effect is as follows:


Finally, we combined the last two sections to inject data:

/*** Plot the bitmap data ** @ param canvas * Canvas object */private void drawBitmaps (canvas) {// reset isLastPage to falseisLastPage = false before plotting the bitmap; // limit the value range of pageIndex: mPageIndex = mPageIndex <0? 0: mPageIndex; mPageIndex = mPageIndex> mBitmaps. size ()? MBitmaps. size (): mPageIndex; // start position of the calculated data int start = mBitmaps. size ()-2-mPageIndex; int end = mBitmaps. size ()-mPageIndex;/** if the data start point is smaller than 0, it indicates that the current image has reached the last image */if (start <0) {// at This time, set isLastPage to trueisLastPage = true; // and display the prompt showToast ("This is fucking lastest page"); // force reset start to 0; end = 1;}/** calculate the area of the current page */canvas. save (); canvas. clipRegion (mRegionCurrent); canvas. drawBitmap (mBitmaps. get (end-1), 0, 0, null); canvas. restore ();/** calculate the area of the fold page */canvas. save (); canvas. clipRegion (mRegionFold); canvas. translate (mPointX, mPointY);/** calculate the collapsed area Image Based on the long and short sides */if (mRatio = Ratio. SHORT) {canvas. rotate (90-mDegrees); canvas. translate (0,-mViewHeight); canvas. scale (-1, 1); canvas. translate (-mViewWidth, 0);} else {canvas. rotate (-(90-mDegrees); canvas. translate (-mViewWidth, 0); canvas. scale (1,-1); canvas. translate (0,-mViewHeight);} canvas. drawBitmap (mBitmaps. get (end-1), 0, 0, null); canvas. restore ();/** calculate the area on the next page */canvas. save (); canvas. clipRegion (mRegionNext); canvas. drawBitmap (mBitmaps. get (start), 0, 0, null); canvas. restore ();}
The final result is as follows:


This part of the code will not be pasted out. Most of the Code is the same as the previous section, because it takes a little time to travel in two days. This section is rough, but there are no major changes, if you do not know anything, you can leave a message or comment on @ in the group. In the next section, we will try to achieve image distortion during page turning.

Source Code address: Portal

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.