Teach you how to draw androidk line time-sharing chart and index

Source: Internet
Author: User
Tags drawtext gety


First nonsense: Before coming to the company, the project is done by the outsourcing company, interview at the beginning, no contact with too much time figure K line this piece, feel very difficult, I can handle not! But after a period of time, found that the previous do is a piece of crushed, but this goods is the main function ah, sooner or later their own fencing, pain determined, open, this would like to use open source control, but want to implement it yourself: then the article

Start with Surfaceview, but this goods in the upper and lower sliding will appear black edge, this problem I was also tangled for a long time, think of products will definitely play back, hit back also disgraced, forget not much things to use the view bar, nonsense really TM many, start it.

1, create the project (Android Studio) 2, yes, first, save your time: 3, the activity is set to horizontal screen, do not set does not matter, I think the horizontal screen of a good view
      android: screenorientation="Landscape"
4, the two base class time-sharing graph point data and the data of each point of the candlestick, the notes are very clear

/** * Ticks required data field */public class Cminute {//Time public long time;//latest price public double price;//volume public long count;//average public Double average;//change public double rate;//Price public double money;p ublic long GetTime () {return time;} Public String Gettimestr () {SimpleDateFormat SDF = new SimpleDateFormat ("hh:mm"); try {return Sdf.format (new Date (TIME * 10 00));} catch (Exception e) {return "--:--";}}}

public class Stickdata implements parcelable {    //time    private long;    Open    private double open;    Close    private double close;    Highest    private double high;    Minimum    private double low;    Volume    private Long Count;    Closed yesterday    private double last;    Percentage change    private double rate;    Price    private double money;    Calculates the zero value of the moving average to save the    private double mavalue;    5 segment EMA    private double sma5;    10 segment EMA    private double sma10;    20 segment EMA    private double sma20;    Volume 5-segment moving average    private double countSma5;    Volume 10-segment moving average    private double countSma10;    Three parameters of the MACD    private double dif;//line    private double dea;//line    private double macd;//columnar    //KDJ three lines    private double K;    private double D;    Private Double J;    A private double RSV is required to calculate K    ;    Candlestick funds    //Super Large single equity    private double sp;    Large single equity    private double BG;    Medium single Equity    private double MD;    Small single equity    private double sm;

5. Steps for drawing

    @Override    protected void OnDraw (canvas canvas) {        super.ondraw (canvas);        1, initialize the required data        initwidthandheight ();        2, Draw grid        DrawGrid (canvas);        3, Draw the line (the price line of the time line, the average line or the average of the candlestick)        drawlines (canvas);        if (linetype! = Type_fenshi) {            //4, if it is a candle, draw another candlestick chart            drawcandles (canvas);        }        5, write the XY axis text (written early will be overwritten)        drawText (canvas);        6, draw the indicator to be displayed        switch (indextype) {case            Index_vol:                drawvol (canvas);                break;            Case INDEX_ZJ:                drawzj (canvas);                break;            Case INDEX_MACD:                drawmacd (canvas);                break;            Case INDEX_KDJ:                drawkdj (canvas);                break;        }    }

6, drawing implementation

In fact, the time-sharing line is the drawing line, candlestick Chart is also a line, but more than draw a rectangle, if analyzed into such words, simply learn more, then I will teach you to draw a line to draw a rectangle ....

Here omit 10000 words, OK said finished (actually is needless to say, just then two methods Drawline,drawrect), next we focus on the calculation of position:

We actually get the data, it is not possible to directly display the coordinate system, because it may be very large and small, first of all, say the y-axis bar


Y-Axis

y = height-input * Height/(max-min);

Y: Calculation results

Height:view height

Max: A set of data maximum values displayed

Min: Minimum value in a set of data displayed

When displaying ticks, the maximum and minimum values need to be fetched at the average price and

Maximum and minimum values can be removed from the highest and lowest when the candlestick is displayed

X-Axis

x = Width/drawcount * i;

X: Calculation results

Width:view width

Drawcount: Total number of impressions

such as Shanghai index, the morning of the opening of the afternoon 2 hours, because the time-sharing chart is not units per minute, then Drawcount is the 60*4,k line is required to calculate the width of drawcount, in my Code, candlesticks and candlesticks after the white space ratio is 10:2


7, indicators

Time-sharing chart of the funds due to the use of other interfaces, the demo will not show, you can refer to the indicator of the money trend of the candlestick (on a few lines, simple bar)

MACD, KDJ, VOL5, VOL10, VOL20 These indicators can Baidu, I do not much, the calculation method are the same, I directly paste code, K line of four indicators, in addition to funds, other indicators can directly through the bar of the high and low open the calculation of yesterday,

public class Indexparseutil {//EMA span (SMA5,SMA10,SMA20), note that when modifying this value, you need to increase the SMA field inside the Stickdata, modify the Initsma method of this class, otherwise it will not take effect public s    tatic Final int start_sma5 = 5;    public static final int start_sma10 = 10;    public static final int start_sma20 = 20;    26: When calculating MACD, 26 segment CLOSE average dif= (EMA (close,12)-EMA (close,26)) public static final int start_dif = 26;    35: When calculating MACD, 35 section begins to take the previous 9th DIF value Dea:=ema (dif,9) public static final int start_dea = 35;    12: Calculate K-value public static final int start_k = 12;    15: Calculate DJ public static final int start_dj = 15;    9: Calculate RSV public static final int start_rev = 9;    public static final int[] SMA = {start_sma5,start_sma10, start_sma20}; /** * Calculate MACD * @param list */public static void INITMACD (List<stickdata> list) {if (list = = N        ULL) return;                1 Calculates all DIF for (int i = 0; i < list.size (); i++) {if (i + start_dif <= list.size ()) { List.get (i + start_dif-1). Setdif (Getclosesma (List.sUblist (i + start_dif-12, i + start_dif))-Getclosesma (list.sublist (i + start_dif-26, i + start_dif))); }}//2 calculates all the DEA for (int i = 0; i < list.size (); i++) {if (i + Start_dea <= list.siz                E ()) {List.get (i + start_dea-1). Setdea (Getdifsma (list.sublist (i + start_dea-9, i + Start_dea)); 3 Calculate MACD list.get (i + start_dea-1). SETMACD (2d * (List.get (i + start_dea-1). Getdif ()-list.            Get (i + start_dea-1). Getdea ()));        }}}/** * Calculate KDJ * @param list */public static void Initkdj (List<stickdata> list) {        if (list = = null) return;                1 Calculates all REV for (int i = 0; i < list.size (); i++) {if (i + Start_rev <= list.size ()) {                The 9th day begins with the calculation of RSV stickdata data = list.get (i + start_rev-1);                double[] Maxandmin = getmaxandmin (List.sublist (i, i + Start_rev)); List.get (i + STart_rev-1). SETRSV ((Data.getclose ()-maxandmin[1])/(Maxandmin[0]-maxandmin[1]) * 100); }}//2 calculates all K for (int i = 0; i < list.size (); i++) {if (i + Start_k <= list.size ())            {List.get (i + start_k-1). SETK (Getrsvsma (list.sublist (i + start_k-3, i + start_k)); }}//3 calculates all DJ for (int i = 0; i < list.size (); i++) {if (i + START_DJ <= list.size (                ) {Stickdata data = List.get (i + start_dj-1);                List.get (i + start_dj-1). SETD (Getksma (list.sublist (i + start_dj-3, i + START_DJ)));            List.get (i + start_dj-1). SETJ (3 * DATA.GETK ()-2 * DATA.GETD ()); }}}/** * Calculates the moving averages for all data in the list and assigns them to the inside * * @param list K line data */public static void Initsma (list<stickdata> List)        {if (list = = null) return;        for (int i = 0; i < list.size (), i++) {for (int j:sma) {        if (i + J <= list.size ()) {//5th day start Calculation 5th ema if (j = = Start_sma5) {                        The amount of SMA5 list.get (i + j-1). SETCOUNTSMA5 (Getcountsma (List.sublist (i, i + j)));                    K-SMA5 List.get (i + j-1). SETSMA5 (Getclosesma (List.sublist (i, i + j)));                            } else//10th day start Calculation 10th EMA if (j = = start_sma10) { The amount of SMA10 list.get (i + j-1). SETCOUNTSMA10 (Getcountsma (List.sublist (i, i + j)))                            ;                        K-SMA10 List.get (i + j-1). SETSMA10 (Getclosesma (List.sublist (i, i + j)));                                }else//20th Day start Calculation 20th EMA if (j = = start_sma20) { K-SMA20 List.get (i + j-1). SETSMA20 (Getclosesma (List.sublist (i, i + j))); }}}}}/** * When calculating KDJ, take 9th the highest lowest value * @param datas * @return */priv Ate static double[] Getmaxandmin (list<stickdata> datas) {if (datas = null | | datas.size () = = 0) r        Eturn new double[]{0, 0};        Double max = datas.get (0). Gethigh ();        Double min = datas.get (0). Getlow ();            for (Stickdata data:datas) {max = max > Data.gethigh ()? Max:data.getHigh (); min = min < Data.getlow ()?        Min:data.getLow ();    } return new Double[]{max, Min}; /** * Candlestick Amount Calculated Moving average * @param datas * @return * * * private static double Getcountsma (LIST&LT;STICKDATA&G T        Datas) {if (datas = = null) return-1;        Double sum = 0;        for (Stickdata data:datas) {sum + = Data.getcount ();    } return Numberutil.doubledecimal (Sum/datas.size ()); /** * Candlestick Price calculates the moving average price * @param datas * @retURN */private static double Getclosesma (list<stickdata> datas) {if (datas = = null) return-1;        Double sum = 0;        for (Stickdata data:datas) {sum + = Data.getclose ();    } return Numberutil.doubledecimal (Sum/datas.size ()); The moving average of/** * Candlestick dif * @param datas * @return * */private static double Getdifsma (List<stickdata&gt ;        Datas) {if (datas = = null) return-1;        Double sum = 0;        for (Stickdata data:datas) {sum + = Data.getdif ();    } return Numberutil.doubledecimal (Sum/datas.size ()); /** * 3rd RSV moving average, k value * @param datas * @return * */private static double Getrsvsma (list<stickdata        > Datas) {if (datas = = null) return-1;        Double sum = 0;        for (Stickdata data:datas) {sum + = DATA.GETRSV ();    } return Numberutil.doubledecimal (Sum/datas.size ()); }/** * 3rd K moving average, i.e. D value * @paramDatas * @return * * * private static double Getksma (list<stickdata> datas) {if (datas = = null) retur        n-1;        Double sum = 0;        for (Stickdata data:datas) {sum + = DATA.GETK ();    } return Numberutil.doubledecimal (Sum/datas.size ()); }}


8, swipe and zoom

This is simple, the time-sharing line does not support sliding and scaling, only the K-line needs: Because the K-line data is more, the default one screen display is not complete, so need to directly swipe, zoom, may be want to see the trend of it (I guess)!


The method is to swipe and zoom directly through gestures,


Then: I got 600 data, showing 500-600, sliding, as long as the 100 move forward on it, such as sliding to 450-550; Zoom, it is even easier, if a screen display 100, then you set a screen display 80 or 120 is scaled, is not so easy!

9, Cross Line

Well, the picture is over, need to cross the line out to walk two steps!



Let's take a look at my layout.

   <relativelayout            android:layout_width= "0DP"            android:layout_height= "match_parent"            android:layout_ weight= "686" >            <eat.arvin.com.mychart.view.fenshiview                android:id= "@+id/cff_fenshiview"                Android:layout_width= "Match_parent"                android:layout_height= "match_parent"/>            < Eat.arvin.com.mychart.view.CrossView                android:id= "@+id/cff_cross"                android:layout_width= "Match_parent"                android:layout_height= "match_parent"                android:visibility= "Gone"/>        </RelativeLayout>

Understand, the two goods are separate, I just fenshiview inside capture Click event, and then determine whether the point has data, and some words in the Crossview draw line, to draw two lines, Europe

   @Override Public        Boolean onsingletapup (Final motionevent e) {            //delay 300 milliseconds display, double-click to make time for            new Handler (). Postdelayed (New Runnable () {                @Override public                void Run () {                    //Click Show Cross-line                    if (crossview! = null) {                        if ( Crossview.getvisibility () = = View.gone) {                            oncrossmove (E.getx (), e.gety ());}}}            , Double_ Tap_delay);            Return Super.onsingletapup (e);        }

Crossview

public class Crossview extends View {/** * cross-line movement monitoring */public interface Onmovelistener {/**  * Cross-line movement (callback to the location of data storage, to determine whether to draw a line, then call this interface to draw a line method) * * @param x x coordinate * @param y y-axis coordinates */void        Oncrossmove (float x, float y);    /** * cross-line vanishing callback */void Ondismiss ();    } private Crossbean Bean;    Gesture control private Gesturedetector gesturedetector;    Private Onmovelistener Onmovelistener;        Public Crossview (context context, AttributeSet Attrs) {Super (context, attrs);            Gesturedetector = new Gesturedetector (GetContext (), new Gesturedetector.simpleongesturelistener () {@Override                public boolean onsingletapup (Motionevent e) {//Click Hide Crosshairs setvisibility (GONE);                if (Onmovelistener! = null) Onmovelistener.ondismiss ();            Return Super.onsingletapup (e); } @Override Public Boolean Onscroll (motionevent E1, motionevent E2, float Distancex, float distancey) {//sliding, notification to interface if (Onmovelistener! = null)                {Onmovelistener.oncrossmove (E2.getx (), e2.gety ());            } return Super.onscroll (E1, E2, Distancex, Distancey);    }        }); } @Override public boolean ontouchevent (Motionevent event) {if (gesturedetector! = null) gestured        Etector.ontouchevent (event);    return true;        } @Override protected void OnDraw (canvas canvas) {super.ondraw (canvas);    Drawcrossline (canvas); }/** *//Cross line according to X, y * * @param canvas */private void Drawcrossline (canvas canvas) {//When this point is not there        Without drawing if (bean.x < 0 | | BEAN.Y < 0) return;        Boolean Isjunxian = bean.y2 >= 0;        Paint p = new paint ();        P.setantialias (TRUE);        P.setcolor (Colorutil.color_cross_line);        P.setstrokewidth (2f); P.setstylE (Paint.Style.FILL);        Horizontal canvas.drawline (0, BEAN.Y, getwidth (), BEAN.Y, p);        Vertical line Canvas.drawline (bean.x, 0, bean.x, GetHeight (), p);            if (Isjunxian) {///EMA Draw dot//Draw cross line and EMA Price line intersection of round canvas.drawcircle (bean.x, BEAN.Y, p);            P.setcolor (Colorutil.color_sma_line);        Canvas.drawcircle (bean.x, Bean.y2, p);        } p.setcolor (Color.Black);        P.settextsize (32f);        1, write the price (vertical bar on the left, the price needs to write to the right) Drawpricetextwithrect (canvas, bean.x, BEAN.Y, Bean.price, p);        2, Write Time Drawtimetextwithrect (canvas, bean.x, Bean.gettime (), p);        3, write the text of the indicator drawindextexts (canvas);    P.reset ();        } private void drawindextexts (canvas canvas) {if (Bean.indextext = = NULL | | bean.indexcolor = = NULL) return;        Paint p = new paint ();        P.setantialias (TRUE);        P.settextsize (26f);        float x = 0; Float y = getheight () * (Chartconstant.main_scale + ChaRtconstant.time_scale) + 25;            for (int i = 0;i < Bean.indexText.length; i++) {P.setcolor (bean.indexcolor[i]);            Canvas.drawtext (Bean.indextext[i], x, Y, p);        x + = Lineutil.gettextwidth (P, bean.indextext[i]) + 30;        }}/** * Write time, and box */private void Drawtimetextwithrect (canvas canvas, float x, String, Paint p) {        P.settextalign (Paint.Align.LEFT);        float textWidth = Lineutil.gettextwidth (p, time) + 20;        Float y = getheight () * Chartconstant.main_scale;        Paint RP = new paint ();        Rp.setcolor (Color.White);        Rp.setstyle (Paint.Style.FILL);        Rp.setstrokewidth (2f);        1, first draw white bottom float StartX = X-TEXTWIDTH/2;        float EndX = x + textwidth/2;            if (StartX < 0) {StartX = 2f;        EndX = StartX + textWidth;            } if (EndX > GetWidth ()) {EndX = GetWidth ()-2;        StartX = Endx-textwidth; } Canvas.drawrECT (StartX, y + 2, EndX, Y + +, RP);        Rp.setcolor (Color.Black);        Rp.setstyle (Paint.Style.STROKE);        2, then draw black box Canvas.drawrect (StartX, y + 2, EndX, Y + +, RP);    3, Write text Canvas.drawtext (time, StartX + ten, y + 27.5f, p);  }/** * Write text and bring a background to the text, which is equivalent to drawing a rect behind the text */private void Drawpricetextwithrect (canvas canvas, float x, float y,        String text, Paint p) {Float textWidth = lineutil.gettextwidth (p, text) + 10;        Paint RP = new paint ();        Rp.setcolor (Color.White);        Rp.setstyle (Paint.Style.FILL);        Rp.setstrokewidth (2f);        float starty = y-15f;        float EndY = y + 15f;            if (Starty < 0) {starty = 0f;        EndY = Starty + 30f;            } else if (EndY > GetHeight ()) {EndY = GetHeight ();        Starty = endy-30f; if (x <) {//x axis is on the left, the box is drawn on the right//1, draw the white bottom first canvas.drawrect (GetWidth ()-TextWidth , Starty, GetWidth (), ENdY, RP);            Rp.setcolor (Color.Black);            Rp.setstyle (Paint.Style.STROKE);            2, then draw the black box Canvas.drawrect (getwidth ()-TextWidth, Starty, GetWidth (), EndY, RP);            P.settextalign (Paint.Align.RIGHT);        Canvas.drawtext (text, getwidth ()-5f, endY-3, p);            } else {//x axis on the right, change frame to left canvas.drawrect (0, Starty, TextWidth, EndY, RP);            Rp.setcolor (Color.Black);            Rp.setstyle (Paint.Style.STROKE);            Canvas.drawrect (0, Starty, TextWidth, EndY, RP);            P.settextalign (Paint.Align.LEFT);        Canvas.drawtext (text, 5f, endY-3, p);        }}/** * Draw the cross line of the tick line */public void DrawLine (Crossbean bean) {This.bean = bean;    Postinvalidate (); }/** * Set mobile listening * * @param onmovelistener */public void Setonmovelistener (Onmovelistener onmoveliste    NER) {this.onmovelistener = Onmovelistener; }}

10, some optimization


Time-sharing line: The server only needs to return the changed points, do not need to return all, these missing points directly using the previous minute completion


Candlestick: Because the K-line data is huge, so if the server calculates a good indicator back to the client, it will make the data volume *1.5 almost, so these indicators are still in the local calculation, only need to be shown, and do not need to repeat the calculation



11,github

Https://github.com/xuzhou4520/AChart1


Teach you how to draw androidk line time-sharing chart and index

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.