The last one made a water ripple view I don't know if you've tried it. Click the Open link
This effect does not seem to make any sense, if you do not listen to the callback image can be directly replaced. The purpose of this blog is to exercise your thinking ability and to customize view requirements with a better face.
Reprint Please specify source: http://blog.csdn.net/wingichoy/article/details/50554058
This article is written in sync with the code. That is, the code that knocks when you write an article. This will appear to be a bit confusing article. But I want to record this, a custom view of the real production process, is 1.1 points, step by step follow the change of thinking, perfect. It is impossible to make a complete view in a single swoop. Technology is the same, it is impossible to skyrocketing rise. is a step-by-step accumulation.
In addition, each blog is based on the basic knowledge of the previous blog, if you just touch the custom view. Can say the way to customize view simple learning here to see my previous article. I have recorded the process of learning to customize view, and some of the previous blogs have made some mistakes more or less. Here I do not want to correct the errors in the blog post, because some of the mistakes are often committed, and later the blog has pointed out these errors, and no longer committed, this is a learning process. So I want to record the wrong experience. And so become a master to look back at that year's self is how food. will also have a sense of accomplishment.
The usual ritual is as follows:
First draw a hexagon, before drawing to calculate the relevant knowledge of the hexagon:
Suppose a side length of a positive hexagon is a, because each angle is 120° so it can be high to three A.
With this information we can draw a hexagon out, as follows:
float height = (float) (MATH.SQRT (3) *mlength); Mpath.moveto (mlength/2,0); Mpath.lineto (0,HEIGHT/2); Mpath.lineto (mlength/2,height); Mpath.lineto ((float) (mlength*1.5), height); Mpath.lineto (2*MLENGTH,HEIGHT/2); Mpath.lineto (float) (mlength*1.5), 0); Mpath.lineto (mlength/2,0); Mpath.close ();
Drawing effect:
It then translates it according to an offset to draw multiple hexagons with a loop
Here offset is the offset, next to the words should be offset by a hexagonal width, width by the known as A/2+A+A/2 2a;
for (int i = 0; i < 3;i++) { int offset = mlength * 2 * i; Mpath.moveto (MLENGTH/2 + offset, 0); Mpath.lineto (0 + offset, HEIGHT/2); Mpath.lineto (MLENGTH/2 + offset, height); Mpath.lineto ((float) (Mlength * 1.5) + offset, height); Mpath.lineto (2 * mlength + offset, HEIGHT/2); Mpath.lineto (float) (Mlength * 1.5) +offset, 0); Mpath.lineto (mlength/2+offset, 0); Mpath.close (); }
Discover the following effects
It's not right, it's strange. The bottom of the empty triangle can not fit our second line AH.
So how to do it. Increase offset! How much to increase it. One more edge length should be added. This will just be left blank. Try it.
Now prepare to draw the second line ....
We found that the coordinates of our path were relative to the written dead. So to go back and change to a given starting point, you can draw a hexagon, after calculation, to obtain
Here a stands for the side length.
The code after the change is:
float height = (float) (MATH.SQRT (3) *mlength); for (int i = 0; i < 3;i++) { //horizontal axis offset int offset = mlength * 3 * i; The upper-left corner of x int x = MLENGTH/2 + offset; int y = 0; Draws the entire positive hexagon mpath.moveto (x, y) according to the top left corner; Mpath.lineto (X-MLENGTH/2, HEIGHT/2 + y); Mpath.lineto (x, height+y); Mpath.lineto (x + mlength, height +y); Mpath.lineto ((float) (x + 1.5*mlength), height/2+y); Mpath.lineto (x + mlength, y); Mpath.lineto (x, y); Mpath.close (); }
The effect is the same as the drawing. But the method and the change.
Then draw the second line, and the path to the beginning of the second line should be here
The coordinates are: 2a, HEIGHT/2 the offsets here are constant.
First the method of drawing path is extracted (as shortcut CTRL + ALT + M)
Draw the entire positive hexagonal private void GetPath (float height, float x, float y) { mpath.moveto (x, y) according to the upper left corner; Mpath.lineto (X-MLENGTH/2, HEIGHT/2 + y); Mpath.lineto (x, height+y); Mpath.lineto (x + mlength, height +y); Mpath.lineto ((float) (x + 1.5*mlength), height/2+y); Mpath.lineto (x + mlength, y); Mpath.lineto (x, y); Mpath.close (); }
And then give a loop to draw the hexagon of the second row.
for (int i = 0;i<2;i++) { float offset = mlength * 3 * i; float x = mlength*2 + offset; Float y = height/2; GetPath (height,x,y); } Canvas.drawpath (Mpath,mpaint);
Get the following effect.
Now the full code for OnDraw is as follows:
@Override protected void OnDraw (canvas canvas) { Mpaint.setcolor (Color.parsecolor ("#FFBB33")); The high float height of the positive hexagon = (float) (MATH.SQRT (3) *mlength); for (int i = 0; i < 3;i++) { //horizontal axis offset float offset = mlength * 3 * i; The upper left corner of the x float x = mlength/2 + offset; Float y = 0; GetPath (height, x, y); } Canvas.drawpath (mpath,mpaint); Mpath.reset (); Mpaint.setcolor (Color.parsecolor ("#AA66CC")); for (int i = 0;i<2;i++) { float offset = mlength * 3 * i; float x = mlength*2 + offset; Float y = height/2; GetPath (height,x,y); } Canvas.drawpath (Mpath,mpaint); }
Next, you control the number of each line.
The number of each line is private int mcolumnscount = 3; Number of rows private int mlinecount = 3;
The corresponding loop also changes, the outermost set a large loop, to control the multi-line drawing
for (int j = 0; J < Mlinecount; J + +) { if (j%2 = = 0) draw odd lines else draw even rows}
Now the whole OnDraw is as follows.
@Override protected void OnDraw (canvas canvas) {//positive hexagon high float height = (float) (MATH.SQRT (3) * mlength) ; for (int j = 0; J < Mlinecount; J + +) {if (j 2 = = 0) {Mpaint.setcolor (Color.parsecolor ("#F FBB33 ")); for (int i = 0; i < Mcolumnscount; i++) {//horizontal axis offset Float offset = mlength * 3 * I ; The upper left corner of the x float x = mlength/2 + offset; Float y = j * HEIGHT/2; GetPath (height, x, y); } canvas.drawpath (MPath, mpaint); Mpath.reset (); } else {Mpaint.setcolor (Color.parsecolor ("#AA66CC")); for (int i = 0; i < Mcolumnscount; i++) {Float offset = mlength * 3 * i; float x = mlength * 2 + offset; Float y = (HEIGHT/2) * j; GetPath (height, x, y); } canvas.drawpath (MPath, mpaint); Mpath.reset (); } } }
As if the color is not good to see. Let's change the color dynamically.
Add a property list to hold the color
Private arraylist<integer> mcolorlist;
Mcolorlist = new arraylist<> (); Mcolorlist.add (Color.parsecolor ("#33B5E5")); Mcolorlist.add (Color.parsecolor ("#AA66CC")); Mcolorlist.add (Color.parsecolor ("#99CC00")); Mcolorlist.add (Color.parsecolor ("#FFBB33")); Mcolorlist.add (Color.parsecolor ("#FF4444"));
In the loop, remove the color value
for (int j = 0; J < Mlinecount; J + +) { Mpaint.setcolor (Mcolorlist.get (j));
The effect is as follows:
Well.. It looks a little bit like ... Let's add some text to the middle.
First, give each cell a number.
The number of rows I is by the loop J above
Research law discovery number equals j*3 + I
We have the coordinates xy in the upper-left corner of the hexagon that can easily calculate the center coordinates
That's all there is. Open a list to store the text in the middle:
The list private arraylist<string> mtextlist that holds the text ;
Add point data at initialization time
Mtextlist = new arraylist<> (); for (int i =0;i<mlinecount*mcolumnscount;i++) { mtextlist.add ("Wing" +i); } Mtextpaint = new Paint (); Mtextpaint.settextsize (20);
Draw Text: Note the order in which he and path are drawn and overwrite the text if the path is drawn.
float txtlength = Mtextpaint.measuretext (Mtextlist.get (txtID)); Canvas.drawtext (Mtextlist.get (txtID), x+mlength/2-txtlength/2,y+height/2+5, mtextpaint);
Here's the whole OnDraw.
@Override protected void OnDraw (canvas canvas) {//positive hexagon high float height = (float) (MATH.SQRT (3) * Mlengt h); for (int j = 0; J < Mlinecount; J + +) {Mpaint.setcolor (Mcolorlist.get (j)); if (j% 2 = = 0) {//Mpaint.setcolor (Color.parsecolor ("#FFBB33")); for (int i = 0; i < Mcolumnscount; i++) {int txtid = J*3 +i; Horizontal axis offset Float offset = mlength * 3 * i; The upper left corner of the x float x = mlength/2 + offset; Float y = j * HEIGHT/2; Mpath.reset (); GetPath (height, x, y); Canvas.drawpath (MPath, mpaint); float txtlength = Mtextpaint.measuretext (Mtextlist.get (txtID)); Canvas.drawtext (Mtextlist.get (txtID), x+mlength/2-txtlength/2,y+height/2+5, mtextpaint); }} else {//Mpaint.setcoloR (Color.parsecolor ("#AA66CC")); for (int i = 0; i < Mcolumnscount; i++) {int txtid = J*3 +i; float offset = mlength * 3 * i; float x = mlength * 2 + offset; Float y = (HEIGHT/2) * j; Mpath.reset (); GetPath (height, x, y); Canvas.drawpath (MPath, mpaint); float txtlength = Mtextpaint.measuretext (Mtextlist.get (txtID)); Canvas.drawtext (Mtextlist.get (txtID), x+mlength/2-txtlength/2,y+height/2+5, mtextpaint); } } } }
Now the following:
Well, now let him be flexible. Add a variety of set methods, such as the number of rows AH column Ah long ah, the text content ah color AH.
/** * Set Number of columns * @param mcolumnscount * /public void Setcolumnscount (int mcolumnscount) { This.mcolumnscount = Mcolumnscount; Invalidate (); } /** * Set Number of lines * @param mlinecount * /public void Setlinecount (int mlinecount) { This.mlinecount = Mlinecount; Invalidate (); } /** * Set Text data * /public void settextlist (arraylist<string> textlist) { mtextlist.clear (); Mtextlist.addall (textlist); Invalidate (); } /** * Set color data * @param colorlist * /public void setcolorlist (arraylist<integer> colorlist) { mcolorlist.clear (); Mcolorlist.addall (colorlist); Invalidate (); }
And did you forget to measure it? Just give him the outermost rectangular size.
@Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) { int widthsize = Measurespec.getsize (WIDTHMEASURESPEC); int widthmode = Measurespec.getmode (widthmeasurespec); int heightsize = measurespec.getsize (heightmeasurespec); int heightmode = Measurespec.getmode (heightmeasurespec); if (Widthmode = = measurespec.at_most) { widthsize = (int) ((3f*mcolumnscount+0.5f) *mlength); } else{// throw new IllegalStateException ("only support wrap_content"); } if (Heightmode = = measurespec.at_most) { heightsize = (int) ((mlinecount/2f +0.5f) * (MATH.SQRT (3) * mlength)); } else{// throw new IllegalStateException ("only support wrap_content"); } Setmeasureddimension (widthsize,heightsize); }
Let's look at the size of the view using wrap_content:
Well.. The measurement is also on the ... Here I only realized wrap_content everyone can and extension let him support exactly
Such a honeycomb briquette view is done ... But it doesn't look like a bird. Because there is no interaction. Pictures can be completely replaced. So this time left a problem, the handling of events. In fact, the logic is not very complex, is to determine whether the touch point in the path, if the time in the action_up, separate numbering, according to the number of callback can, this issue, prepare the next blog to solve, please continue to pay attention to my blog crab crab!
Address of this project: Click to open the link
If you think I'm doing a good job, please click on the top and continue to follow me. Thank you!!
Take your hand to draw a beautiful cellular view Android Custom view