RecyclerChart的KLine的繪制
正文
繼上次章節(jié)介紹完RecyclerChart的一些動(dòng)態(tài)屬性之后,本章節(jié)開始基于RecyclerChart繪制新的圖表,股票相關(guān)的Chart,筆者花了大概一天,繪制如下的一個(gè)效果,發(fā)現(xiàn)換了電腦之后沒有裝PS,所以CandleChart的顏色自己隨意取的。其實(shí)無(wú)論繪制什么業(yè)務(wù)的圖形,最終交給圖表的不過是一堆要展示的數(shù)據(jù)而已。
下面是gif圖,還有好些功能沒有加,比如高亮用的是原來(lái)的RecyclerChart之前的樣式。Kline作為CombineChart,還有5日、10日、20日均線的繪制等以及底部一系列的比如MACD, 成交量圖等待該系列后續(xù)漸漸實(shí)現(xiàn)

基于RecyclerChart繪制一種新的圖表,類似于搭積木一樣,之前的心電圖也是如此。
繪制前列一個(gè)提綱,然后依此逐一實(shí)現(xiàn)即可:
1.創(chuàng)建 StockAttr、StockBean, StockEntity.
2.創(chuàng)建 StockChartRecyclerView, StockChartRenderer,StockChartItemDecoration,
StockValueFormatter
3. 繪制主體的 drawChart.
4. Mock Bean, Entity數(shù)據(jù)。
5. 繪制 HighLight
6. 繪制 XAxis
7. 繪制 YAxis, 最大、最小值局部留有 padding
8. 嘗試添加縮放, OnScaleGestureListener; Matrix , onTouch . 根據(jù)縮放比例,調(diào)整 RecyclerChart的 displayNumber, notifyDataChange。
繪制蠟燭圖
1.計(jì)算 color, 參照上個(gè)Entry的 close大小。 定義 mStockAttrs 里的兩種 color值,并且是否 Fill。
2. 畫上引線、下引線。
圖表的樣式跟它所依賴的數(shù)據(jù)是相對(duì)應(yīng)的,然后就是一個(gè)業(yè)務(wù)數(shù)據(jù)到Chart數(shù)據(jù)的一個(gè)轉(zhuǎn)化,然后圖表依照Chart數(shù)據(jù)進(jìn)行繪制即可。這里的YAxis、XAxis、board, HighLight 好些跟之前的都是相通的,部分可以復(fù)用;注意一些邊界上的處理。
主要是CandleChart的繪制,其實(shí)里面的主體邏輯跟之前的BarChart也是類似的;這里看看代碼吧:
fun <Y : YAxis> drawStockChart(canvas: Canvas, parent: RecyclerView, yAxis: Y) {
val parentRight = (parent.width - parent.paddingRight).toFloat()
val parentLeft = parent.paddingLeft.toFloat()
val childCount = parent.childCount
for (i in 0 until childCount) {
val child = parent.getChildAt(i)
val stockEntry = child.tag as StockEntry
val rectMain = getStockRectF(child, parent, yAxis, mStockAttrs, stockEntry)
val radius = 1f
val color = if (stockEntry.isRise) mStockAttrs.riseColor else mStockAttrs.downColor
mBarChartPaint.color = color
//todo 注意RTL
drawChart(canvas, rectMain, parent.left.toFloat(), parent.right.toFloat(), radius)
mHighLightLinePaint.color = color
if (stockEntry.mShadowHigh > Math.max(stockEntry.mClose, stockEntry.mOpen)){
drawTopLine(stockEntry.mShadowHigh, canvas, rectMain, yAxis, parent)
}
if (stockEntry.mShadowLow < Math.min(stockEntry.mClose, stockEntry.mOpen)){
drawDownLine(stockEntry.mShadowLow, canvas, rectMain, yAxis, parent)
}
}
}
這里包含了主體柱子Chart的繪制,以及上引線、下引線的繪制。
//繪制上引線、下引線
private fun drawTopLine(value:Float, canvas: Canvas, rectF: RectF, yAxis: YAxis, parent: RecyclerView){
canvas.save()
val y = getYPosition(value, parent, yAxis, mStockAttrs)
val x = (rectF.left + rectF.right)/2
if (DecimalUtil.bigOrEquals(x, parent.left.toFloat()) && DecimalUtil.smallOrEquals(x, parent.right.toFloat())){
canvas.drawLine(x, rectF.top, x, y, mHighLightLinePaint)
canvas.restore()
}
}
//下引線
private fun drawDownLine(value:Float, canvas: Canvas, rectF: RectF, yAxis: YAxis, parent: RecyclerView){
canvas.save()
val y = getYPosition(value, parent, yAxis, mStockAttrs)
val x = (rectF.left + rectF.right)/2
if (DecimalUtil.bigOrEquals(x, parent.left.toFloat()) && DecimalUtil.smallOrEquals(x, parent.right.toFloat())){
canvas.drawLine(x, rectF.bottom, x, y, mHighLightLinePaint)
canvas.restore()
}
}
繪制Chart 主體,按照先前的繪制,左右邊界的處理。目前還是有些bug, 先處理主邏輯,后續(xù)修復(fù)吧。
private fun drawChart(canvas: Canvas, rectF: RectF, parentLeft: Float, parentRight: Float, radius: Float) {
// 浮點(diǎn)數(shù)的 == 比較需要注意
if (DecimalUtil.smallOrEquals(rectF.right, parentLeft)) {
//continue 會(huì)閃,原因是end == parentLeft 沒有過濾掉,顯示出來(lái)柱狀圖了。
} else if (rectF.left < parentLeft && rectF.right > parentLeft) {
//左邊部分滑入的時(shí)候,處理柱狀圖的顯示
rectF.left = parentLeft
val path = CanvasUtil.createRectRoundPath(rectF, radius, RoundRectType.TYPE_RIGHT_TOP)
mBarChartPaint.color = mBarChartAttrs.chartEdgeColor
canvas.drawPath(path, mBarChartPaint)
} else if (DecimalUtil.bigOrEquals(rectF.left, parentLeft) && DecimalUtil.smallOrEquals(rectF.right, parentRight)) {
// 中間部分的Item
val path = CanvasUtil.createRectRoundPath(rectF, radius, RoundRectType.TYPE_ALL)
canvas.drawPath(path, mBarChartPaint)
// canvas.drawRoundRect(rectF, radius, radius, mBarChartPaint);
} else if (DecimalUtil.smallOrEquals(rectF.left, parentRight) && rectF.right > parentRight) {
//右邊部分滑出的時(shí)候,處理柱狀圖,文字的顯示
val distance = parentRight - rectF.left
rectF.right = rectF.left + distance
val path = CanvasUtil.createRectRoundPath(rectF, radius, RoundRectType.TYPE_LEFT_TOP)
mBarChartPaint.color = mBarChartAttrs.chartEdgeColor
canvas.drawPath(path, mBarChartPaint)
}
}總體大致上,思路還是蠻簡(jiǎn)單的,關(guān)于動(dòng)態(tài)加載數(shù)據(jù),高亮,Y軸在滑動(dòng)過程中動(dòng)態(tài)調(diào)整,隨時(shí)更改Max/Min值等功能都是公用之前的邏輯。
然后就是下一章節(jié)的需要實(shí)現(xiàn)的均線跟Candle Chart 在一個(gè)For循環(huán)里繪制,省開銷,計(jì)劃將均線的Bean數(shù)據(jù)放StockEntity,方便在一個(gè)For里拿去。再就是里面草稿大綱里提到的第8項(xiàng),圖表的縮放的功能,大致的思路如上所述,待實(shí)現(xiàn)。
以上就是RecyclerChart的KLine的繪制的詳細(xì)內(nèi)容,更多關(guān)于RecyclerChart KLine繪制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)統(tǒng)計(jì)在線人數(shù)功能的方法詳解
很多人在筆試或者面試中問到:現(xiàn)在要你實(shí)現(xiàn)一個(gè)統(tǒng)計(jì)在線人數(shù)的功能,你該怎么設(shè)計(jì)?不知道的朋友,這篇文章就來(lái)告訴你具體實(shí)現(xiàn)方法2022-08-08
Java Web請(qǐng)求與響應(yīng)實(shí)例詳解
這篇文章主要介紹了Java Web請(qǐng)求與響應(yīng)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-05-05
Spring Boot3整合Mybatis Plus的詳細(xì)過程(數(shù)據(jù)庫(kù)為MySQL)
這篇文章主要介紹了Spring Boot3整合Mybatis Plus的詳細(xì)過程(數(shù)據(jù)庫(kù)為MySQL),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-07-07
MyBatis批量更新(update foreach)報(bào)錯(cuò)問題
這篇文章主要介紹了MyBatis批量更新(update foreach)報(bào)錯(cuò)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Java中import java.util.Scanner的用處詳解
文章主要介紹Java中的Scanner類及其常用方法next()和nextLine()的區(qū)別,next()方法在遇到空格、Tab鍵、回車鍵等分隔符時(shí)結(jié)束輸入,而nextLine()方法則接收所有輸入,直到遇到回車鍵2024-11-11
java 出現(xiàn)Zipexception 異常的解決辦法
這篇文章主要介紹了java 出現(xiàn)Zipexception 異常的解決辦法的相關(guān)資料,出現(xiàn) java.util.zip.ZipException: error in opening zip file 異常的原因及解決方法,需要的朋友可以參考下2017-08-08

