Android Custom view to achieve movie ticket online selection function _android

Source: Internet
Author: User
Tags abs drawtext ticket

Take a look at the movie tickets. Online selection function to achieve the effect of the map:

The interface is rough, mainly to see the principle.

This interface mainly includes the following parts

1. Seating
2, the left row number
3, the top left thumbnail
4, the red area in the thumbnail
5. Follow the movement when the finger moves
6, two fingers zoom with zoom

Main technical points

1. Matrix matrices
2, Gesturedetector and Scalegesturedetector
3, bitmap the basic usage
4, here only need to rewrite the view OnDraw to achieve full functionality

It can be found that there is no difficulty in fact, mainly is the calculation of some positions.

In order to be able to easily understand the first to use the knowledge point of the comb

1. Matrix matrices

The matrix is determined by 9 values in the 3*3 matrix, and all of the settings we have for the matrix are operations on these 9 values.

{mscale_x,mskew_x,mtrans_x,
Mskew_y,mscale_y,mtrans_y,
Mpersp_0,mpersp_1,mpersp_2}

This is the 9 values of the matrix, see the name also know what they mean.

This is mainly used for scaling and panning, and the following is an example of scaling to understand the control of scaling
Through the API provided by Android we can invoke Setscale, Prescale, Postscale to change the value of mscale_x and mscale_y to achieve scaling effect

So as long as we understand the difference between the three methods of Setscale, Prescale and Postscale, we can simply zoom control.

1, Setscale (Sx,sy), the matrix will first be set to the diagonal matrix, which is equivalent to call the Reset () method, and then set the matrix of mscale_x and mscale_y directly set to Sx,sy values
2, Prescale (Sx,sy), will not reset the matrix, but directly with the matrix before the mscale_x and mscale_y values (multiplied), m ' = m * S (SX, SY).
3, Postscale (Sx,sy), does not reset the matrix, but directly with the matrix before the mscale_x and mscale_y values (multiplied), M ' = S (SX, SY) * M.

So there is some bad understanding, a chestnut to see

1. Order of execution of pre ....

 Matrix matrix=new Matrix ();
 Float[] Points=new float[]{10.0f,10.0f};
 Matrix.prescale (2.0f, 3.0f);
 Matrix.pretranslate (8.0f,7.0f);
 Matrix.mappoints (points);
 LOG.I ("Test", points[0]+ "");
 LOG.I ("Test", points[1]+ "");

The result is a point coordinate (36.0,51.0)
It can be concluded that the order in which the transformations are performed is performed first by Pretranslate (8.0f,7.0f), in the execution of the Prescale (2.0f,3.0f). That is, for a matrix setting, all pre ... is executed backwards.

2, Post ... Order of execution

 Matrix matrix=new Matrix ();
 Float[] Points=new float[]{10.0f,10.0f};
 Matrix.postscale (2.0f, 3.0f);
 Matrix.posttranslate (8.0f,7.0f);
 Matrix.mappoints (points);
 LOG.I ("Test", points[0]+ "");
 LOG.I ("Test", points[1]+ "");

The result is a point coordinate (28.0,37.0)
It can be concluded that the order in which the transformations are performed is performed first by Postscale (2.0f,3.0f), in the execution of the Posttranslate (8.0f,7.0f). That is, for a matrix setting, all post ... is carried forward.

The main knowledge here is set ... and post ... method on the line, because only use these two.
Self-understanding is actually similar to Scrollto and Scrollby.

2, Gesturedetector and Scalegesturedetector

Gesturedetector is mainly used to identify certain gestures, just call gesturedetector.ontouchevent () to pass motionevent in.
Scalegesturedetector the attack class usage used to handle scaling is similar to Gesturedetector

3, bitmap the basic usage
reference to: about bitmap Some things you don't know

Take a look at the bitmap.

The following is the official drawing of this selection function.

1, Draw the seat:

 @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas);
 /** * If the first entry makes the seating chart centered * * (mviewh!= 0 && mvieww!= 0&&isfrist) {isfrist = false;
 Matrix.settranslate (-(Mvieww-getmeasuredwidth ())/2, 0);
 /** * Draw Seat * * drawseat (canvas);
 /** * Draw the number of rows/drawText (canvas);
 /** * Draw Thumbnails * * * Drawoverview (canvas);

 /** * Draw Thumbnails Selection Area * * * drawovewrect (canvas); }

 private void Drawseat (Canvas Canvas) {Float zoom = Getmatrixscalex ();
 Scale1 = zoom;
 Tranlatex = Gettranslatex ();
 Tranlatey = Gettranslatey (); /** * Use a two-layer for loop to draw all seats * * for (int i = 0; i < row; i++) {Float top = i * seathight * scale * scale1 + i * mspacey
 * Scale1 + Tranlatey;

 for (int j = 0; j < column; J +) {Float left = J * Seatwidth * scale * scale1 + J * Mspacex * scale1 + Tranlatex;
 Tempmatrix.settranslate (left, top);
 Tempmatrix.postscale (scale, scale, left, top);


 Tempmatrix.postscale (Scale1, Scale1, left, top);
 /** * Get information for each position/int state = Getseattype (i, j);
 /** * According to position information draw different position picture * * Switch (state) {case SEAT_TYPE_SOLD:canvas.drawBitmap (seatlock, Tempmatrix, NULL);
 Break
 Case SEAT_TYPE_SELECTED:canvas.drawBitmap (seatchecked, Tempmatrix, NULL);
 Break
 Case SEAT_TYPE_AVAILABLE:canvas.drawBitmap (seatnormal, Tempmatrix, NULL);
 Break

 Case Seat_type_not_available:break; }
 }
 }

 }

In fact, there is no difficulty here, the main thing is to use the two for loop, a layer of painting lines, a layer of painting columns

Also note that the current position of the calculation top = (current position i) (seat icon size seathight its own scaling than scale* scaling than Scale1) + (the current position i* the vertical direction of spacing mspacey* zoom ratio scale1) + Moving vertically, yes, moving distances.

2, Draw row number

private void DrawText (Canvas Canvas) {
 mtextpaint.setcolor (baccolor);
 RECTF RECTF = new RECTF ();
 Rectf.top = Gettranslatey ()-MNUMBERHEIGHT/2;
 Rectf.bottom = Gettranslatey () + mviewh* Getmatrixscalex () + MNUMBERHEIGHT/2;
 Rectf.left = 0;
 Rectf.right = Mtextwidth;


 Canvas.drawroundrect (RECTF, MTEXTWIDTH/2, MTEXTWIDTH/2, mtextpaint);
 Mtextpaint.setcolor (color.white);
 for (int i = 0; i < row; i++) {
 float top = (i *seathight*scale + i * mspacey) * Getmatrixscalex () + Gettranslatey ();
 Float bottom = (i * seathight*scale + i * mspacey + seathight) * Getmatrixscalex () + Gettranslatey ();
 Float baseline = (bottom + top-linenumberpaintfontmetrics.bottom-linenumberpaintfontmetrics.top)/2-6;
 Canvas.drawtext (Linenumbers.get (i), MTEXTWIDTH/2, Baseline, mtextpaint);
 } 
 

3. Draw thumbnail image

private void Drawoverview (Canvas Canvas) {/** * 1, first draw a background picture/Mbitmapoverview = Bitmap.createbitmap ((int) Moverviewwid
 th, (int) moverviewhight,bitmap.config.argb_8888);
 Canvas Overviewcanvas = new Canvas (Mbitmapoverview);
 Paint Paint = new Paint ();
 Paint.setcolor (Baccolor);
 Scaleoverx = MOVERVIEWWIDTH/MVIEWW;
 Scaleovery = MOVERVIEWHIGHT/MVIEWH;
 float tempx = mvieww * SCALEOVERX;
 float Tempy = MVIEWH * scaleovery;

 Overviewcanvas.drawrect (0, 0, (float) tempx, (float) tempy, paint);
 Matrix Tempovermatrix = new Matrix (); /** * 2, like the picture of a seating chart, draw seats in thumbnails (int i = 0; i < row; i++) {Float top = i * seathight * scale * scaleovery+ I * MSPA
 Cey * scaleovery; for (int j = 0; j < column; J +) {Float left = J * Seatwidth * scale * Scaleoverx + J * Mspacex * Scaleoverx+mtextwid
 Th*scaleoverx;
 Tempovermatrix.settranslate (left, top);

 Tempovermatrix.postscale (Scale*scaleoverx, Scale*scaleovery, left, top);
 int state = Getseattype (i, j); Switch (state) {case Seat_type_soLD:OverViewCanvas.drawBitmap (Seatlock, Tempovermatrix, NULL);
 Break
 Case SEAT_TYPE_SELECTED:OverViewCanvas.drawBitmap (seatchecked, Tempovermatrix, NULL);
 Break
 Case SEAT_TYPE_AVAILABLE:OverViewCanvas.drawBitmap (seatnormal, Tempovermatrix, NULL);
 Break

 Case Seat_type_not_available:break;

 }} canvas.drawbitmap (Mbitmapoverview,0,0,null);

 }

4, red areas in thumbnails

private void Drawovewrect (Canvas Canvas) {overrectpaint = new Paint ();
 Overrectpaint.setcolor (color.red);
 Overrectpaint.setstyle (Paint.Style.STROKE);
 Overrectpaint.setstrokewidth (Overrectlinewidth);
 int tempvieww;
 int TEMPVIEWH;
 if (Getmeasuredwidth () <mvieww) {tempvieww = Getmeasuredwidth ();
 }else{tempvieww = mvieww;
 } if (Getmeasuredheight () <mviewh) {TEMPVIEWH = Getmeasuredheight ();
 }else{TEMPVIEWH = MVIEWH;
 } try{Rect Rect; if (Getmatrixscalex () >= 1.0f) {rect = new rect (int) (Scaleoverx*math.abs (Gettranslatex ())/getmatrixscalex ()), (int ) (Scaleovery*math.abs (Gettranslatey ())/getmatrixscalex ()), (int) (Scaleoverx*math.abs (Gettranslatex ())/ Getmatrixscalex () +tempvieww*scaleoverx/getmatrixscalex ()), (int) (Scaleovery*math.abs (Gettranslatey ())/
 Getmatrixscalex () +tempviewh*scaleovery/getmatrixscalex ()); }else{rect = new rect ((int) (Scaleoverx*math.abs (Gettranslatex ())), (int) (Scaleovery*math.abs (Gettranslatey ())), ( int) (Scaleoverx*math.abs (GettraNslatex ()) +tempvieww*scaleoverx), (int) (Scaleovery*math.abs (Gettranslatey ()) +tempviewh*scaleovery));
 } canvas.drawrect (Rect, overrectpaint);
 }catch (Exception e) {e.printstacktrace ();

 } 
 }

5. Follow the movement when the finger moves

@Override Public
 Boolean ontouchevent (Motionevent event) {

 /**
 * Scaling event referred to scalegesturedetector processing
 * *
 scalegesturedetector.ontouchevent (event);
 /**
 * Move and click event to gesturedetector processing *
 *
 gesturedetector.ontouchevent (event);

 return true;
 }

/** * Mobile Event here is a simple judgment, the need for more detailed conditions to judge/public boolean onscroll (Motionevent E1, motionevent E2, float Distancex, float
 Distancey) {Float tempmvieww = column * seatwidth*scale*scale1+ (column-1) *mspacex*scale1+mtextwidth-getwidth ();


 float TEMPMVIEWH = row * seathight * scale * scale1 + (row-1) * Mspacey * scale1-getheight ();
 if ((Gettranslatex () >mtextwidth+mspacex) && distancex<0) {Distancex = 0.0f;
 if (Math.Abs (Gettranslatex ()) >tempmvieww) && (distancex>0)) {Distancex = 0.0f;
 } if ((Gettranslatey () >0) &&distancey<0) {distancey=0.0f;
 if (Math.Abs (Gettranslatey ()) &GT;TEMPMVIEWH) && (distancey>0)) {Distancey = 0.0f; 
 } matrix.posttranslate (-distancex,-distancey);
 Invalidate ();

 return false;
 /** * Click event/public boolean onsingletapconfirmed (Motionevent e) {int x = (int) e.getx ();

 int y = (int) e.gety (); for (int i = 0; i < row; i++) {for (int j = 0; j < column; J +) {int tempx = (int) (j * Seatwidth * scale + J * Mspacex) * Getmatrixscalex () + Gettranslatex ());

 int maxtemx = (int) (TEMPX + seatwidth * scale * GETMATRIXSCALEX ());
 int tempy = (int) ((i * seathight * scale + i * Mspacex) * Getmatrixscaley () + Gettranslatey ());


 int maxtempy = (int) (Tempy + seathight * scale * Getmatrixscaley ()); if (x >= tempx && x <= maxtemx && y >= tempy && y <= maxtempy) {int id = GetID (i,
 j);
 int index = Ishave (ID);
 if (index >= 0) {remove (index);


 else {addchooseseat (i, j);
 float Currentscaley = Getmatrixscaley ();
  if (Currentscaley < 1.7f) {ScaleX = x;
  ScaleY = y;
 /** * Zoom Operation When selected * * Zoomanimate (Currentscaley, 1.9f);
 } invalidate ();

 Break
 }} return super.onsingletapconfirmed (e);


 }
 });

6, two fingers zoom with zoom

public boolean Onscale (Scalegesturedetector detector) {
 float scalefactor = Detector.getscalefactor ();
 ScaleX = Detector.getcurrentspanx ();
 ScaleY = Detector.getcurrentspany ();
 A direct judgment of greater than 2 causes the obtained matrix scaling to continue to run once, resulting in a number like 2.000001 so that the
 //judgment condition is always true and thus does not perform a narrowing action
 //judgment multiplication greater than 2 Can be the current obtained scaling ratio even if the number 1.9999 and so on if continue to enlarge even if multiplied by 1.0001 will be larger than 2 thereby
 //avoid the above problem.

 if (Getmatrixscaley () * scalefactor > 2) {
 scalefactor = 2/getmatrixscaley ();
 }
 if (Getmatrixscaley () * Scalefactor < 0.8) {
 scalefactor = 0.8f/getmatrixscaley ();
 }
 Matrix.postscale (Scalefactor, scalefactor);


 Invalidate ();

 return true;
 }

So far this relatively rough selection function is achieved, there will be time to continue to optimize the details of the problem.

The following two demo are compared to the force I will not upload demo.

Resources:

Android Alternative block source analysis

Andriod to create cool movie tickets on-line selection control, 1:1 restore Taobao movie Online select Seat function

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

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.