[Custom control series 4] android plotting practice (1) drawing charts using Canvas + Path + Paint, and androidcanvas
Reprinted Please note: http://blog.csdn.net/duguang77/article/details/40869079
The previous blogs briefly introduced the Canvas + Path + Paint API. Below we use the methods in these classes to draw the following style.
Demo: https://github.com/z56402344/Android_Graphics_Instance_One
:
Dynamic:
This type of map is usually not used by the artist to cut the map during project creation. First, it is troublesome and second, there is no way to adapt it. Therefore, you can only draw it through the drawing class.
Let's first look at how to draw the most difficult point.
This is the most difficult point. I personally think it is how the arrow on the circle points to the middle position of a shard.
The figure seems quite complicated. In fact, these are all hypothetical. Let's split the layer first.
Effect split Layer
Simplified Graph
In this way, you should know how to draw this graph!
Let's take a closer look at the coordinates of the center.
protected void onDraw(Canvas canvas) {super.onDraw(canvas);mWidth = canvas.getWidth();mHeight = canvas.getHeight();mCenterX = mWidth/2;mCenterY = mHeight/4;}
The Canvas in the inherited View class OnDraw () method gets the position of the half-width, 1/4-high point of the screen, which is the O-point coordinate in, the column is also drawn by the coordinate points given by ourselves, so these two points are known.
The most important thing is to control the center and draw a triangle,
We have learned that you can draw triangles through the Canvas + Path + Paint combination API, but we do not know the coordinates of P and P,
// Start to draw the triangle Path = new path (); // The triangle Path. moveTo (float) (x2), (float) (y2); // point coordinate path. lineTo (float) (mPointB. x), (float) (mPointB. y); // path of the center coordinate. lineTo (float) x1, (float) y1); // P 'coordinate path. close (); // close the paint brush path canvas. drawPath (path, paint); // start painting
Through the simplified graph, we can see that it is actually a mathematical problem. Through the point O coordinate and the point H coordinate, the OP and the OP side length are their own given values, so they are also known, OH edge length is known, PH and P 'H are obtained through three-fold analysis. With these parameters, we can form a binary system to calculate the coordinates of P and P as follows:
<Span style = "white-space: pre"> </span> PointBean mPointA; <span style = "white-space: pre "> </span> // coordinates of the center at the top of the column <span style =" white-space: pre "> </span> PointBean mPointB = new PointBean (760,400 ); // assume the coordinates of a center point during initialization
// The following formula uses the coordinates of the center of the circle and the coordinates of the center of the top of the column body, the coordinate point position of the remaining two triangles is calculated using a binary system of equations. // x = x1-a * sin {arctan [(y2-y1)/(x2-x1)]} // y = y1 + a * cos {arctan [(y2-y1)/(x2-x1)]} // find the coordinate point Pdouble x1 = mPointA. x-50 * Math. sin (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); double y1 = mPointA. y + 50 * Math. cos (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); // obtain the coordinate point P 'double x2 = mPointA. x + 50 * Math. sin (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); double y2 = mPointA. y-50 * Math. cos (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x )));
This is the most difficult point in the figure. If you know the P; P 'and H coordinates, you can easily draw the triangle of the center.
The following is all the code. I will put the project on github and you can download it.
/*** Draw the triangle with the center point at the top of the column body and the center point coordinate. * @ author DuGuang **/public class CustomTrigon extends View {PointBean mPointA; // PointBean mPointB = new PointBean (760,400) at the top of the column body; // when initializing, assume that the coordinates of a center point are private float mCenterX; // The coordinates of the center point are Xprivate float mCenterY; // Yprivate int mWidth coordinate of the center of the circle; // canvas width = private int mHeight of the mobile phone screen; // canvas Height = mobile phone screen height-ActionBar-top titlepublic CustomTrigon (Context context) {super (context);} public CustomTrigon (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle);} public CustomTrigon (Context context, AttributeSet attrs) {super (context, attrs);} @ SuppressLint ("DrawAllocation ") @ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); mWidth = canvas. getWidth (); mHeight = canvas. getHeight (); mCenterX = mWidth/2; mCenterY = mHeight/4; mPointA = new PointBean (int) mCenterX, (int) mCenterY); Paint paint = new Paint (); paint. setAntiAlias (true); paint. setStyle (Style. FILL); paint. setStrokeWidth (30f); paint. setDither (true); paint. setColor (getResources (). getColor (R. color. cril); getDot2 (paint, canvas);} public void getDot2 (Paint paint, Canvas canvas) {// The following formula uses the coordinates of the center of the circle and the coordinates of the center of the top of the column body, the coordinate point position of the remaining two triangles is calculated using a binary system of equations. // x = x1-a * sin {arctan [(y2-y1)/(x2-x1)]} // y = y1 + a * cos {arctan [(y2-y1)/(x2-x1)]} // find the coordinate point Pdouble x1 = mPointA. x-50 * Math. sin (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); double y1 = mPointA. y + 50 * Math. cos (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); // obtain the coordinate point P 'double x2 = mPointA. x + 50 * Math. sin (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); double y2 = mPointA. y-50 * Math. cos (Math. atan (mPointB. y-mPointA. y)/(mPointB. x-mPointA. x); Log. I ("dg", "x >>>" + x1 + "y >>>" + y1); // start to draw a triangle Path path = new Path (); // triangle path. moveTo (float) (x2), (float) (y2); // point coordinate path. lineTo (float) (mPointB. x), (float) (mPointB. y); // path of the center coordinate. lineTo (float) x1, (float) y1); // P 'coordinate path. close (); // close the paint brush path canvas. drawPath (path, paint); // start painting}/*** Insert the coordinates of the center point at the top of a column body * @ param pointB */public void setData (PointBean pointB) through different levels) {mPointB = pointB; invalidate ();}}
/*** Custom control circle * @ author DuGuang **/public class CustomCircle extends View {private float mCenterX; // Circular X axis center private float mCenterY; // circular Y axis center private float mCircleSize; // circular diameter size private Context mContext; private int mWidth; // canvas width = mobile phone screen width private int mHeight; // canvas Height = mobile phone screen height-ActionBar-top titlepublic CustomCircle (Context context) {super (context); init (context);} public CustomCircle (Context context, attributeSet attrs, int defStyle) {super (context, attrs, defStyle); init (context);} public CustomCircle (Context context, AttributeSet attrs) {super (context, attrs ); init (context);}/*** initialize data * @ param context */private void init (Context context) {this. mContext = context; this. mCenterX = 350f; this. mCenterY = 350f; this. mCircleSize = 285f ;}@ SuppressLint ("DrawAllocation") @ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); mWidth = canvas. getWidth (); mHeight = canvas. getHeight (); mCenterX = mWidth/2; mCenterY = mHeight/4; mCircleSize = mHeight/6; // first Paint brush, draw a hollow circle paint = new Paint (); paint. setAntiAlias (true); // removes the tooth margin from paint. setStyle (Style. STROKE); // hollow paint. setStrokeWidth (30f); // paint width. setDither (true); // clear the deying paint. setColor (getResources (). getColor (R. color. cril); // set the paint brush color // draw a circular Path = new Path () on the canvas using the path; Path. addCircle (mCenterX, mCenterY, mCircleSize, Path. direction. CCW); canvas. drawPath (path, paint); // second Paint brush, draw a solid circle Paint paint_white = new paint (); Path path_white = new Path (); paint_white.setAntiAlias (true ); paint_white.setStyle (Style. FILL); paint_white.setDither (true); paint_white.setColor (getResources (). getColor (R. color. white); // path_white.addCircle (mCenterX, mCenterY, mCircleSize-15, Path. direction. CCW); path_white.addCircle (mCenterX, mCenterY, 5, Path. direction. CCW); canvas. drawPath (path_white, paint_white); // Paint a hollow circle paint_STROKE = new Paint (); Path path_STROKE = new Path (); paint_STROKE.setAntiAlias (true ); paint_STROKE.setStyle (Style. STROKE); paint. setStrokeWidth (5f); // paint brush width paint_STROKE.setDither (true); paint_STROKE.setColor (getResources (). getColor (R. color. cril); path_STROKE.addCircle (mCenterX, mCenterY, mCircleSize-25, Path. direction. CCW); canvas. drawPath (path_STROKE, paint_STROKE );}}
/*** Custom space, columnar body with rounded corners * @ author DuGuang **/public class CustomRect extends View {// private float [] radii = {12f, 12f, 12f, 12f, 0f, 0f, 0f, 0f}; // the color of the column body, private int [] colors = {R. color. rect_cril_leve1, R. color. rect_cril_leve2, R. color. rect_cril_leve3, R. color. rect_cril_leve4, R. color. rect_cril_leve5, R. color. rect_cril_leve6}; private int mWidth; // canvas width = private int mHeight of the mobile phone screen; // canvas Height = mobile phone screen height-ActionBar-top titleprivate int mRectWidth; // rectangular width private int mRectHeight; // rectangular height private Paint mPaint; private String mLevel; // The words of the L1-L3 private String mName; // The initial, advanced, professional words private static float mToY = 15f; // less than 1, the overall move down; greater than 1, move private static float mRectY = 4 as a whole; // The length of the rectangle is extended to 1, and the length of the rectangle is shortened to private ArrayList <String> mPointList; // public CustomRect (Context context) {super (context); init (context);} public CustomRect (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); init (context);} public CustomRect (Context context, AttributeSet attrs) {super (context, attrs); init (context );} private void init (Context context) {}@ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); mPointList = new ArrayList <String> (); mWidth = canvas. getWidth (); mHeight = canvas. getHeight (); mRectWidth = (int) (mWidth/9.5); mRectHeight = mHeight/2; // six columnar bodies for (int I = 0; I <6; I ++) {initBitmaps (canvas, I) ;}/ *** draw a rectangle * @ param canvas * @ param index */private void initBitmaps (Canvas canvas, int index) {mPaint = new Paint (); mPaint. setAntiAlias (true); mPaint. setStyle (Style. FILL); mPaint. setStrokeWidth (30f); mPaint. setDither (true); mPaint. setColor (getResources (). getColor (colors [index]); // you can use the Path to calculate the width and height of each column, place the center coordinates at the top of the column body into the set // The center coordinates at the top of the column body into the set, which is used for the triangle with the center of the center, through the center coordinates and the column coordinate, draw the triangle Path path = new Path (); int width = (int) (mRectWidth/2 + (index * mRectWidth * 1.5); int height_top = (int) (mRectHeight + (mRectHeight/15) * (6-index) + mRectWidth * 1.5); int height_bootom = height_top-mRectHeight/10 + (mRectHeight/15) * index; height_top = (int) (height_top-mRectHeight/mRectY); // The height start position moves the 1/10 screen path to 0. addRoundRect (new RectF (width, height_top, width + mRectWidth, height_bootom), radii, Path. direction. CCW); canvas. drawPath (path, mPaint); String RectX = String. valueOf (width + mRectWidth/2); String RectY = String. valueOf (height_top); mPointList. add (RectX + "-" + RectY); Log. I ("dg", "mPointList >>>" + mPointList. size (); Path path1 = new Path (); path1.addRoundRect (new RectF (width, height_bootom + 10, width + mRectWidth, height_bootom + 12), radii, Path. direction. CCW); canvas. drawPath (path1, mPaint); switch (index) {case 0: mLevel = "L1-L3"; mName = "Getting started"; break; case 1: mLevel = "L4-L6 "; mName = ""; break; case 2: mLevel = "L7-L9"; mName = "intermediate"; break; case 3: mLevel = "L10-L12"; mName = "medium "; break; case 4: mLevel = "L13-L15"; mName = "advanced"; break; case 5: mLevel = "L16"; mName = "expert"; break; default: break;} drawLevel (canvas, index, width, height_bootom, mLevel); drawText (canvas, index, width, height_bootom, mName );} /*** painting name * @ param canvas * @ param index * @ param width * @ param height_bootom * @ param name */private void drawText (Canvas canvas, int index, int width, int height_bootom, String name) {Paint paint = new Paint (); paint. setAntiAlias (true); paint. setStyle (Style. FILL); paint. setStrokeWidth (30f); paint. setDither (true); paint. setColor (getResources (). getColor (colors [index]); paint. setTextSize (30); canvas. drawText (name, width + mRectWidth/5, height_bootom + 100, paint );} /*** painting level ** @ param canvas * @ param index * @ param width * @ param height_bootom * @ param level */private void drawLevel (Canvas canvas, int index, int width, int height_bootom, String level) {Paint paint = new Paint (); paint. setAntiAlias (true); paint. setStyle (Style. FILL); paint. setStrokeWidth (30f); paint. setDither (true); paint. setColor (getResources (). getColor (colors [index]); paint. setTextSize (30); if (index = 5) {canvas. drawText (level, width + mRectWidth/4, height_bootom + 60, paint);} else if (index = 4 | index = 3) {canvas. drawText (level, width + mRectWidth/20, height_bootom + 60, paint);} else {canvas. drawText (level, width + mRectWidth/6, height_bootom + 60, paint);} public ArrayList <String> getPointList () {return mPointList ;} public void setPointList (ArrayList <String> mPointList) {this. mPointList = mPointList ;}}
/*** Home page ** @ author DuGuang * blog address: http://blog.csdn.net/duguang77 **/public class TestCourseReportActivity extends Activity {private FrameLayout mFlMain; private ArrayList <String> mPointList; private CustomRect mCusRect; private CustomTrigon mTrigon; private TextView mTvHideOne, mTvLevel, mTvHideTwo, mTvHide; private View mViewLine; private int mWidth; private int mHeight; private Handler mHandler = new Handler () {public void handleMessage (android. OS. message msg) {// obtain the mPointList coordinate position at the center of the five shard body vertices. addAll (mCusRect. getPointList (); String [] split = mPointList. get (5 ). split ("-"); mTrigon. setData (new PointBean (Integer. parseInt (split [0]), Integer. parseInt (split [1]) ;};@overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_course_testcourse_report); initView (); initData ();} private void initView () {mFlMain = (FrameLayout) findViewById (R. id. fl_mian); mCusRect = (CustomRect) findViewById (R. id. cus_rect); mTvHideOne = (TextView) findViewById (R. id. TV _hide_one); mTvLevel = (TextView) findViewById (R. id. TV _level); mTvHideTwo = (TextView) findViewById (R. id. TV _hide_two); mViewLine = findViewById (R. id. view_line); mTvHide = (TextView) findViewById (R. id. TV _hide);} private void initData () {mPointList = new ArrayList <String> (); CustomCircle circle = new CustomCircle (this); mTrigon = new CustomTrigon (this); mFlMain. addView (mTrigon, 2); mFlMain. addView (circle, 3); new Thread () {public void run () {// The Thread is started here to prevent layout files from being completed, systemClock is abnormal when the coordinate at the top of the column is obtained. sleep (200); mHandler. sendEmptyMessage (0 );};}. start (); // obtain the screen width and height (method 1) mWidth = getWindowManager (). getdefadisplay display (). getWidth (); // screen width mHeight = getWindowManager (). getdefadisplay display (). getHeight (); // screen height int width = mWidth/2-mWidth/8; int height = mHeight/4-mHeight/12; // The first TextView is not displayed here. I don't know why. Mark it and modify FrameLayout later. layoutParams params = new FrameLayout. layoutParams (LayoutParams. MATCH_PARENT, LayoutParams. MATCH_PARENT); params. topMargin = height + 40; params. leftMargin = width; mTvHideOne. setLayoutParams (params); FrameLayout. layoutParams params4 = new FrameLayout. layoutParams (LayoutParams. MATCH_PARENT, LayoutParams. MATCH_PARENT); params4.topMargin = height-10; params4.leftMargin = width; mTvHide. setLayoutParams (params4); FrameLayout. layoutParams params1 = new FrameLayout. layoutParams (LayoutParams. MATCH_PARENT, LayoutParams. MATCH_PARENT); params1.topMargin = height + 40; params1.leftMargin = width; mTvLevel. setTextColor (getResources (). getColor (R. color. text_hide); mTvLevel. setLayoutParams (params1); FrameLayout. layoutParams params2 = new FrameLayout. layoutParams (300, 1); params2.topMargin = height + 140; params2.leftMargin = width; mViewLine. setBackgroundColor (getResources (). getColor (R. color. view_backgroud); mViewLine. setLayoutParams (params2); FrameLayout. layoutParams params3 = new FrameLayout. layoutParams (LayoutParams. MATCH_PARENT, LayoutParams. MATCH_PARENT); params3.topMargin = height + 150; params3.leftMargin = width; mTvHideTwo. setTextColor (getResources (). getColor (R. color. text_level); mTvHideTwo. setLayoutParams (params3 );}}
Demo: https://github.com/z56402344/Android_Graphics_Instance_One
The project will be sent to github this weekend. Please wait for the link address. If you have any questions, please leave a message.
Reprinted Please note: http://blog.csdn.net/duguang77/article/details/40869079
Canvas plotting of android Custom Controls
In the activity, I performed scrollBy ON THE relativelayout of the control, so that the part that cannot be drawn out of the screen will appear, is it because the control has limited the size? This is my drag code @ Override public boolean onTouchEvent (MotionEvent event) {switch (event. getAction () {case MotionEvent. ACTION_DOWN: currentX = (int) event. getRawX (); currentY = (int) event. getRawY (); break; case MotionEvent. ACTION_UP: break; case MotionEvent. ACTION_MOVE: int x2 = (int) event. getRawX (); int y2 = (int) event. getRawY (); container. scrollBy (currentX-x2, currentY-y2); currentX = x2; currentY = y2; metroView. invalidate (); default: break;} return super. onTouchEvent (event);} view original post>
How to Use android to draw triangles
. I did not say anything about it. Ah, it's so annoying to go home that I can find a way. It was originally implemented by the android. graphics. Path class. The description in The Api is as follows: The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. it can be drawn with canvas. drawPath (path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path. it generally means that the path class contains multiple components, such as straight line segments, quadratic curves, and cubic curves. It can be drawn on the canvas, whether it is a fill or stroke. Example: package cn. lgl. draw; import android. content. context; import android. graphics. canvas; import android. graphics. color; import android. graphics. linearGradient; import android. graphics. paint; import android. graphics. path; import android. graphics. rectF; import android. graphics. shader; import android. view. view; public class MyView extends View {public MyView (Context context) {super (context); // TODO Auto-generated constructor stub} @ Override protected void onDraw (Canvas canvas) {// TODO Auto-generated method stub super. onDraw (canvas);/* set the background to white */canvas. drawColor (Color. WHITE); Paint paint = new Paint ();/* de-sawtooth */paint. setAntiAlias (true);/* set the paint color */paint. setColor (Color. RED);/* set the paint style to STROKE: hollow */paint. setStyle (Paint. style. STROKE);/* set the width of the paint box */paint. setStrokeWidth (3);/* draw a hollow triangle */Path path = new Path (); path. moeto (10,330); path. lineTo (70,330); path. lineTo (40,100); path. close (); canvas. drawPath (path, paint);/* set the paint style to FILL: solid */paint. setStyle (Pain ...... remaining full text>