Making a vertical list is very common and simple, as follows:
But how do we create a list that can be arc-shaped? Just like the following effect:
Of course, we have to customize a view to create a list like that. I decided to use Surfaceview to create this list view. After analysis, the problem includes the following:
How do I draw a picture within an arc?
Suppose you have a circular arc (CenterX, CenterY) with a central point and a radius R. A point P has an angle relative to the center point. The following formula can then describe the problem:
Based on this, we can easily draw a list item on the arc.
How do I slide a list view on an arc?
This problem occurs when the user slides the list. How do we update the angle of each list item? To be exact, we must record the sliding angle in detail. Added to the angle of each item in the current list view. To address this requirement. I decided to use Gesturedetector to control the event. Also, in this class, my main consideration is how to record the sliding angle in detail (the function name is the following).
public boolean onscroll (Motionevent E1, motionevent E2, float Distancex, float distancey)
Based on E2, Distancex, and Distancey, the sliding angle will be recorded in detail in the following picture:
Based on this picture, we give the following formula
I'm talking about creating a list of shows as examples. The pictures in the list come from the resource folder. You can refer to the source code I uploaded.
code is as follows |
copy code |
int[] Playerdrawableresourceids = new int[] {R.drawable.ronaldo, r.drawable.zindance, R.drawable.congvinh, R.drawable.huynhduc, R.drawable.gerrard, R.drawable.nagatomo, R.drawable.messi, R.drawable.minhphuong, R.drawable.neymar, R.drawable.ronaldo_beo, R.drawable.ronaldinho, R.drawable.xavi}; |
How do I draw a picture in an arc?
First, create a class Circledrawitem for the list item.
The code is as follows |
Copy Code |
public class Circledrawitem { Public Bitmap Miconbitmap; public double mangle; } |
Miconbitmap: A bitmap of list items.
Mangle: The radian of each list item. This radian is updated when the list item is rotated.
Because the arc will be displayed on the left side of the screen. So the center of the circle will set the X coordinate to a negative number. At the same time, the y-coordinate is set to the y-coordinate value of the screen center.
The code is as follows |
Copy Code |
Mcenterx = (int) (-GLOBAL.DP * 200); Mcentery = (int) (global.dh/2.0f); Mradius = (int) (450 * GLOBAL.DP); Mstartangleinradian = MATH.PI/4; |
Calculated with the value of global:
The code is as follows |
Copy Code |
GLOBAL.DW = Getresources (). Getdisplaymetrics (). Widthpixels; GLOBAL.DH = Getresources (). Getdisplaymetrics (). Heightpixels; GLOBAL.DP = global.density/1.5f; |
This arc retains the list of circledrawitem arrays. The radian of the first item is PI/4. The interval for each list item is PI/10. The radian of the first item and the radian between the two items can be modified according to your requirements.
The code is as follows |
Copy Code |
for (int i = 0; i < playerdrawableresourceids.length; i++) { Circledrawitem Circledrawitem = new Circledrawitem (); Circledrawitem.miconbitmap = Decodesampledbitmapfromresource ( Getresources (), Playerdrawableresourceids[i], 50, 50); Circledrawitem.mangle = Mstartangleinradian-i * MATH.PI/10; Datas.add (Circledrawitem); } |
I created a thread to draw each item of data into an arc.
The code is as follows |
Copy Code |
protected void Draw () { Canvas Canvas = Getholder (). Lockcanvas (); if (canvas = = null) { Return } Canvas.save (); Canvas.drawcolor (Color.transparent, mode.clear); Paint Paint = new Paint (); Paint.setantialias (TRUE); Paint.setfilterbitmap (TRUE); Paint.setantialias (TRUE);
for (int i = 0; i < datas.size (); i++) { Canvas.save (); Circledrawitem item = datas.get (i); Double x = Mcenterx + math.cos (item.mangle) * Mradius; Double y = mcentery-math.sin (item.mangle) * Mradius; Canvas.drawbitmap (Item.miconbitmap, (int) X-item.miconbitmap.getwidth ()/2, (int) y -Item.mIconBitmap.getHeight ()/2, paint); Canvas.restore (); } Canvas.restore (); Getholder (). Unlockcanvasandpost (canvas); } |
How do I make a list slide in an arc?
Reference Ongesturelistener and overload the Onscroll () function.
The code is as follows |
Copy Code |
@Override public boolean onscroll (Motionevent E1, motionevent E2, float Distancex, Float Distancey) { float TPX = E2.getx (); float tpy = e2.gety (); float DISX = (int) Distancex; float Disy = (int) Distancey; Double scrollangle = Calculatescrollangle (TPX, tpy, TPX + DISX, tpy + Disy); for (int i = 0; i < datas.size (); i++) { Datas.get (i). mangle + = Scrollangle; } return true; }
|
The method for calculating the sliding angle is as follows:
code is as follows |
copy code |
Private double Calculatescrollangle (float px1, float py1, float px2, Float py2) { double radian1 = math.atan2 (py1, px1); Double radian2 = math.at An2 (Py2, px2); double diff = radian2-radian1; return diff; } |