Android繪制雙折線圖的方法
更新時間:2022年02月16日 10:17:14 作者:Legnen24
這篇文章主要為大家詳細介紹了Android繪制雙折線圖的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了Android繪制雙折線圖的具體代碼,供大家參考,具體內(nèi)容如下
自定義View實現(xiàn)雙折線圖,可點擊,點擊后帶標簽描述,暫未實現(xiàn)拖動的功能,實現(xiàn)效果如下:
代碼如下:
首先,自定義布局屬性:
<declare-styleable name="LineChart"> ? ? <!--type2.LineChart(雙折線圖)--> ? ? <attr name="maxYValue" format="integer" /> ? ? <attr name="yLabelCount" format="integer" /> ? ? <attr name="xLabelTextSize" format="dimension" /> ? ? <attr name="xLabelTextColor" format="color" /> ? ? <attr name="xLabelTextMarginTop" format="dimension" /> ? ? <attr name="showYLabelText" format="boolean" /> ? ? <attr name="yLabelTextSize" format="dimension" /> ? ? <attr name="yLabelTextColor" format="color" /> ? ? <attr name="yLabelTextMarginLeft" format="dimension" /> ? ? <attr name="axisWidth" format="dimension" /> ? ? <attr name="axisColor" format="color" /> ? ? <attr name="showScale" format="boolean" /> ? ? <attr name="scaleLength" format="dimension" /> ? ? <attr name="showGrid" format="boolean" /> ? ? <attr name="gridWidth" format="dimension" /> ? ? <attr name="gridDashInterval" format="dimension" /> ? ? <attr name="gridDashLength" format="dimension" /> ? ? <attr name="gridColor" format="color" /> ? ? <attr name="lineWidth" format="dimension" /> ? ? <attr name="lineColor1" format="color" /> ? ? <attr name="lineColor2" format="color" /> ? ? <attr name="labelWidth" format="dimension" /> ? ? <attr name="labelHeight" format="dimension" /> ? ? <attr name="labelBackgroundColor" format="color" /> ? ? <attr name="labelRadius" format="dimension" /> ? ? <attr name="labelTextSize" format="dimension" /> ? ? <attr name="labelTextColor" format="color" /> ? ? <attr name="labelArrowWidth" format="dimension" /> ? ? <attr name="labelArrowHeight" format="dimension" /> ? ? <attr name="labelArrowOffset" format="dimension" /> ? ? <attr name="labelArrowMargin" format="dimension" /> ? ? <attr name="clickAble" format="boolean" /> ? ? <attr name="leftMargin" format="dimension" /> ? ? <attr name="topMargin" format="dimension" /> ? ? <attr name="rightMargin" format="dimension" /> ? ? <attr name="bottomMargin" format="dimension" /> </declare-styleable>
LineChart的實現(xiàn)如下:
class LineChart @JvmOverloads constructor( ? ? context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { ? ? ? companion object { ? ? ? ? private val DEFAULT_MAX_YVALUE = 5000 ? ? ? ? private val DEFAULT_YLABEL_COUNT = 4 ? ? ? ? private val DEFAULT_XLABEL_TEXT_SIZE = SizeUtil.sp2px(10f) ? ? ? ? private val DEFAULT_XLABEL_TEXT_COLOR = Color.parseColor("#999999") ? ? ? ? private val DEFAULT_XLABEL_TEXT_MARGIN_TOP = SizeUtil.dp2px(10f) ? ? ? ? private val DEFAULT_SHOW_YLABEL_TEXT = false ? ? ? ? private val DEFAULT_YLABEL_TEXT_SIZE = SizeUtil.sp2px(11f) ? ? ? ? private val DEFAULT_YLABEL_TEXT_COLOR = Color.BLACK ? ? ? ? private val DEFAULT_YLABEL_TEXT_MARGIN_LEFT = SizeUtil.dp2px(15f) ? ? ? ? private val DEFAULT_AXIS_WIDTH = SizeUtil.dp2px(0.5f) ? ? ? ? private val DEFAULT_AXIS_COLOR = Color.parseColor("#F1F1F1") ? ? ? ? private val DEFAULT_SHOW_SCALE = true ? ? ? ? private val DEFAULT_SCALE_LENGTH = SizeUtil.dp2px(4f) ? ? ? ? private val DEFAULT_SHOW_GRID = true ? ? ? ? private val DEFAULT_GRID_WIDTH = SizeUtil.dp2px(0.5f) ? ? ? ? private val DEFAULT_GRID_DASH_INTERVAL = SizeUtil.dp2px(1f) ? ? ? ? private val DEFAULT_GRID_DASH_LENGTH = SizeUtil.dp2px(2f) ? ? ? ? private val DEFAULT_GRID_COLOR = Color.parseColor("#F1F1F1") ? ? ? ? private val DEFAULT_LINE_WIDTH = SizeUtil.dp2px(1.5f) ? ? ? ? private val DEFAULT_LINE_COLOR1 = Color.parseColor("#60BF56") ? ? ? ? private val DEFAULT_LINE_COLOR2 = Color.parseColor("#108EE9") ? ? ? ? private val DEFAULT_LABEL_WIDTH = SizeUtil.dp2px(135f) ? ? ? ? private val DEFAULT_LABEL_HEIGHT = SizeUtil.dp2px(78f) ? ? ? ? private val DEFAULT_LABEL_BACKGROUND_COLOR = Color.WHITE ? ? ? ? private val DEFAULT_LABEL_RADIUS = SizeUtil.dp2px(3f) ? ? ? ? private val DEFAULT_LABEL_TEXT_SIZE = SizeUtil.sp2px(11f) ? ? ? ? private val DEFAULT_LABEL_TEXT_COLOR = Color.parseColor("#333333") ? ? ? ? private val DEFAULT_LABEL_ARROW_WIDTH = SizeUtil.dp2px(8f) ? ? ? ? private val DEFAULT_LABEL_ARROW_HEIGHT = SizeUtil.dp2px(2f) ? ? ? ? private val DEFAULT_LABEL_ARROW_OFFSET = SizeUtil.dp2px(31f) ? ? ? ? private val DEFAULT_LABEL_ARROW_MARGIN = SizeUtil.dp2px(14.5f) ? ? ? ? private val DEFAULT_CLICKABLE = true ? ? ? ? private val DEFAULT_LEFT_MARGIN = SizeUtil.dp2px(15f) ? ? ? ? private val DEFAULT_TOP_MARGIN = SizeUtil.dp2px(118f) ? ? ? ? private val DEFAULT_RIGHT_MARGIN = SizeUtil.dp2px(15f) ? ? ? ? private val DEFAULT_BOTTOM_MARGIN = SizeUtil.dp2px(70f) ? ? } ? ? ? //Y軸最大值 ? ? var maxYValue: Int = DEFAULT_MAX_YVALUE ? ? //Y軸上的刻度值個數(shù) ? ? var yLabelCount: Int = DEFAULT_YLABEL_COUNT ? ? //X軸刻度值文本字體大小 ? ? var xLabelTextSize: Float = DEFAULT_XLABEL_TEXT_SIZE ? ? //X軸刻度值文本字體顏色 ? ? var xLabelTextColor: Int = DEFAULT_XLABEL_TEXT_COLOR ? ? //X軸刻度值文本到X軸的上邊距 ? ? var xLabelTextMarginTop: Float = DEFAULT_XLABEL_TEXT_MARGIN_TOP ? ? //是否顯示Y軸刻度值文本 ? ? var showYLabelText: Boolean = DEFAULT_SHOW_YLABEL_TEXT ? ? //Y軸刻度值文本字體大小 ? ? var yLabelTextSize: Float = DEFAULT_YLABEL_TEXT_SIZE ? ? //Y軸刻度值文本字體顏色 ? ? var yLabelTextColor: Int = DEFAULT_YLABEL_TEXT_COLOR ? ? //Y軸刻度值文本到屏幕左側(cè)的左邊距 ? ? var yLabelTextMarginLeft: Float = DEFAULT_YLABEL_TEXT_MARGIN_LEFT ? ? //X軸寬度 ? ? var axisWidth: Float = DEFAULT_AXIS_WIDTH ? ? //X軸顏色 ? ? var axisColor: Int = DEFAULT_AXIS_COLOR ? ? //是否顯示軸線上的小刻度線,默認顯示 ? ? var showScale: Boolean = DEFAULT_SHOW_SCALE ? ? //X軸上的小刻度線長度 ? ? var scaleLength: Float = DEFAULT_SCALE_LENGTH ? ? //是否顯示網(wǎng)格,默認顯示 ? ? var showGrid: Boolean = DEFAULT_SHOW_GRID ? ? //網(wǎng)格線寬度 ? ? var gridWidth: Float = DEFAULT_GRID_WIDTH ? ? //網(wǎng)格線組成虛線的線段之間的間隔 ? ? var gridDashInterval: Float = DEFAULT_GRID_DASH_INTERVAL ? ? //網(wǎng)格線組成虛線的線段長度 ? ? var gridDashLength: Float = DEFAULT_GRID_DASH_LENGTH ? ? //網(wǎng)格線顏色 ? ? var gridColor: Int = DEFAULT_GRID_COLOR ? ? //折線寬度 ? ? var lineWidth: Float = DEFAULT_LINE_WIDTH ? ? //折線一顏色 ? ? var lineColor1: Int = DEFAULT_LINE_COLOR1 ? ? //折線二顏色 ? ? var lineColor2: Int = DEFAULT_LINE_COLOR2 ? ? //標簽的矩形寬度 ? ? var labelWidth: Float = DEFAULT_LABEL_WIDTH ? ? //標簽的矩形高度 ? ? var labelHeight: Float = DEFAULT_LABEL_HEIGHT ? ? //標簽背景顏色 ? ? var labelBackgroundColor = DEFAULT_LABEL_BACKGROUND_COLOR ? ? //標簽的矩形圓角 ? ? var labelRadius: Float = DEFAULT_LABEL_RADIUS ? ? //標簽內(nèi)文本字體大小 ? ? var labelTextSize: Float = DEFAULT_LABEL_TEXT_SIZE ? ? //標簽內(nèi)文本字體顏色 ? ? var labelTextColor: Int = DEFAULT_LABEL_TEXT_COLOR ? ? //標簽的箭頭寬度 ? ? var labelArrowWidth: Float = DEFAULT_LABEL_ARROW_WIDTH ? ? //標簽的箭頭高度 ? ? var labelArrowHeight: Float = DEFAULT_LABEL_ARROW_HEIGHT ? ? //標簽的箭頭到標簽左側(cè)或右側(cè)的偏移量 ? ? var labelArrowOffset: Float = DEFAULT_LABEL_ARROW_OFFSET ? ? //標簽的箭頭到坐標軸最上方的下邊距 ? ? var labelArrowMargin: Float = DEFAULT_LABEL_ARROW_MARGIN ? ? //是否可點擊 ? ? var clickAble: Boolean = DEFAULT_CLICKABLE ? ? //坐標軸到View左側(cè)的邊距,多出來的空間可以用來繪制Y軸刻度文本 ? ? var leftMargin: Float = DEFAULT_LEFT_MARGIN ? ? //坐標軸到View頂部的邊距,多出來的空間可以用來繪制標簽信息 ? ? var topMargin: Float = DEFAULT_TOP_MARGIN ? ? //坐標軸到View右側(cè)的邊距 ? ? var rightMargin: Float = DEFAULT_RIGHT_MARGIN ? ? //坐標軸到View底部的邊距,多出來的空間可以用來繪制X軸刻度文本 ? ? var bottomMargin: Float = DEFAULT_BOTTOM_MARGIN ? ? ? private var mCurrentDrawIndex = 0 ? ? ? private lateinit var mAxisPaint: Paint ? ? //繪制軸線和軸線上的小刻度線 ? ? private lateinit var mGridPaint: Paint ? ? //繪制網(wǎng)格線 ? ? private lateinit var mLinePaint: Paint ? ? //繪制折線 ? ? private lateinit var mLabelPaint: Paint ? ?//繪制最上方標簽 ? ? private lateinit var mLabelBgPaint: Paint ?//繪制標簽背景,帶陰影效果 ? ? private lateinit var mTextPaint: Paint ? ? //繪制文本 ? ? private lateinit var mLabelRectF: RectF ? ?//最上方的標簽對應的矩形 ? ? ? private var mWidth: Int = 0 ? ? private var mHeight: Int = 0 ? ? private var mXPoint: Float = 0f ? //原點的X坐標 ? ? private var mYPoint: Float = 0f ? //原點的Y坐標 ? ? private var mXScale: Float = 0f ? //X軸刻度長度 ? ? private var mYScale: Float = 0f ? //Y軸刻度長度 ? ? private var mXLength: Float = 0f ?//X軸長度 ? ? private var mYLength: Float = 0f ?//Y軸長度 ? ? private var mClickIndex: Int = 0 ?//點擊時的下標 ? ? ? private var mDataList1: MutableList<Float> = mutableListOf() ? ? //折線一(交易收益)對應數(shù)據(jù) ? ? private var mDataList2: MutableList<Float> = mutableListOf() ? ? //折線二(返現(xiàn)收益)對應數(shù)據(jù) ? ? //記錄每個數(shù)據(jù)點的X、Y坐標 ? ? private var mDataPointList1: MutableList<PointF> = mutableListOf() ? ? private var mDataPointList2: MutableList<PointF> = mutableListOf() ? ? private var mXLabelList: MutableList<String> = mutableListOf() ?//X軸刻度值 ? ? private var mYLabelList: MutableList<String> = mutableListOf() ?//Y軸刻度值 ? ? ? init { ? ? ? ? setLayerType(LAYER_TYPE_SOFTWARE, null) ?//關(guān)閉硬件加速,解決在部分手機無法實現(xiàn)虛線效果 ? ? ? ? attrs?.let { ? ? ? ? ? ? parseAttribute(getContext(), it) ? ? ? ? } ? ? ? ? initPaint() ? ? ? ? setYLable() ? ? } ? ? ? //初始化Y軸刻度值 ? ? private fun setYLable() { ? ? ? ? mYLabelList.clear() ? ? ? ? val increment = maxYValue / yLabelCount.toFloat() ? ? ? ? for (i in 0..yLabelCount) { ? ? ? ? ? ? var text = "" ? ? ? ? ? ? if (i == 0) { ? ? ? ? ? ? ? ? text = "0" ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? val value = (increment * i * 100).toInt() / 100f ? ? ? ? ? ? ? ? if (value == value.toInt().toFloat()) { ? ? ? ? ? ? ? ? ? ? text = value.toInt().toString() ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? text = value.toString() ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? mYLabelList.add(text) ? ? ? ? } ? ? } ? ? ? //獲取布局屬性并設置屬性默認值 ? ? private fun parseAttribute(context: Context, attrs: AttributeSet) { ? ? ? ? val ta = context.obtainStyledAttributes(attrs, R.styleable.LineChart) ? ? ? ? maxYValue = ta.getInt(R.styleable.LineChart_maxYValue, DEFAULT_MAX_YVALUE) ? ? ? ? yLabelCount = ta.getInt(R.styleable.LineChart_yLabelCount, DEFAULT_YLABEL_COUNT) ? ? ? ? xLabelTextSize = ta.getDimension(R.styleable.LineChart_xLabelTextSize, DEFAULT_XLABEL_TEXT_SIZE) ? ? ? ? xLabelTextColor = ta.getColor(R.styleable.LineChart_xLabelTextColor, DEFAULT_XLABEL_TEXT_COLOR) ? ? ? ? xLabelTextMarginTop = ta.getDimension(R.styleable.LineChart_xLabelTextMarginTop, DEFAULT_XLABEL_TEXT_MARGIN_TOP) ? ? ? ? showYLabelText = ta.getBoolean(R.styleable.LineChart_showYLabelText, DEFAULT_SHOW_YLABEL_TEXT) ? ? ? ? yLabelTextSize = ta.getDimension(R.styleable.LineChart_yLabelTextSize, DEFAULT_YLABEL_TEXT_SIZE) ? ? ? ? yLabelTextColor = ta.getColor(R.styleable.LineChart_yLabelTextColor, DEFAULT_YLABEL_TEXT_COLOR) ? ? ? ? yLabelTextMarginLeft = ta.getDimension(R.styleable.LineChart_yLabelTextMarginLeft, DEFAULT_YLABEL_TEXT_MARGIN_LEFT) ? ? ? ? axisWidth = ta.getDimension(R.styleable.LineChart_axisWidth, DEFAULT_AXIS_WIDTH) ? ? ? ? axisColor = ta.getColor(R.styleable.LineChart_axisColor, DEFAULT_AXIS_COLOR) ? ? ? ? showScale = ta.getBoolean(R.styleable.LineChart_showScale, DEFAULT_SHOW_SCALE) ? ? ? ? scaleLength = ta.getDimension(R.styleable.LineChart_scaleLength, DEFAULT_SCALE_LENGTH) ? ? ? ? showGrid = ta.getBoolean(R.styleable.LineChart_showGrid, DEFAULT_SHOW_GRID) ? ? ? ? gridWidth = ta.getDimension(R.styleable.LineChart_gridWidth, DEFAULT_GRID_WIDTH) ? ? ? ? gridDashInterval = ta.getDimension(R.styleable.LineChart_gridDashInterval, DEFAULT_GRID_DASH_INTERVAL) ? ? ? ? gridDashLength = ta.getDimension(R.styleable.LineChart_gridDashLength, DEFAULT_GRID_DASH_LENGTH) ? ? ? ? gridColor = ta.getColor(R.styleable.LineChart_gridColor, DEFAULT_GRID_COLOR) ? ? ? ? lineWidth = ta.getDimension(R.styleable.LineChart_lineWidth, DEFAULT_LINE_WIDTH) ? ? ? ? lineColor1 = ta.getColor(R.styleable.LineChart_lineColor1, DEFAULT_LINE_COLOR1) ? ? ? ? lineColor2 = ta.getColor(R.styleable.LineChart_lineColor2, DEFAULT_LINE_COLOR2) ? ? ? ? labelWidth = ta.getDimension(R.styleable.LineChart_labelWidth, DEFAULT_LABEL_WIDTH) ? ? ? ? labelHeight = ta.getDimension(R.styleable.LineChart_labelHeight, DEFAULT_LABEL_HEIGHT) ? ? ? ? labelBackgroundColor = ta.getColor(R.styleable.LineChart_labelBackgroundColor, DEFAULT_LABEL_BACKGROUND_COLOR) ? ? ? ? labelRadius = ta.getDimension(R.styleable.LineChart_labelRadius, DEFAULT_LABEL_RADIUS) ? ? ? ? labelTextSize = ta.getDimension(R.styleable.LineChart_labelTextSize, DEFAULT_LABEL_TEXT_SIZE) ? ? ? ? labelTextColor = ta.getColor(R.styleable.LineChart_labelTextColor, DEFAULT_LABEL_TEXT_COLOR) ? ? ? ? labelArrowWidth = ta.getDimension(R.styleable.LineChart_labelArrowWidth, DEFAULT_LABEL_ARROW_WIDTH) ? ? ? ? labelArrowHeight = ta.getDimension(R.styleable.LineChart_labelArrowHeight, DEFAULT_LABEL_ARROW_HEIGHT) ? ? ? ? labelArrowOffset = ta.getDimension(R.styleable.LineChart_labelArrowMargin, DEFAULT_LABEL_ARROW_OFFSET) ? ? ? ? labelArrowMargin = ta.getDimension(R.styleable.LineChart_labelArrowMargin, DEFAULT_LABEL_ARROW_MARGIN) ? ? ? ? clickAble = ta.getBoolean(R.styleable.LineChart_clickAble, DEFAULT_CLICKABLE) ? ? ? ? leftMargin = ta.getDimension(R.styleable.LineChart_leftMargin, DEFAULT_LEFT_MARGIN) ? ? ? ? topMargin = ta.getDimension(R.styleable.LineChart_topMargin, DEFAULT_TOP_MARGIN) ? ? ? ? rightMargin = ta.getDimension(R.styleable.LineChart_rightMargin, DEFAULT_RIGHT_MARGIN) ? ? ? ? bottomMargin = ta.getDimension(R.styleable.LineChart_bottomMargin, DEFAULT_BOTTOM_MARGIN) ? ? ? ? ta.recycle() ? ? } ? ? ? //初始化畫筆 ? ? private fun initPaint() { ? ? ? ? mAxisPaint = Paint() ? ? ? ? with(mAxisPaint) { ? ? ? ? ? ? isAntiAlias = true ? ? ? ? ? ? color = axisColor ? ? ? ? ? ? strokeWidth = axisWidth ? ? ? ? } ? ? ? ? mGridPaint = Paint() ? ? ? ? with(mGridPaint) { ? ? ? ? ? ? isAntiAlias = true ? ? ? ? ? ? color = gridColor ? ? ? ? ? ? strokeWidth = gridWidth ? ? ? ? ? ? setPathEffect(DashPathEffect(floatArrayOf(gridDashLength, gridDashInterval), 0f)) ?//設置虛線效果 ? ? ? ? } ? ? ? ? mLinePaint = Paint() ? ? ? ? with(mLinePaint) { ? ? ? ? ? ? isAntiAlias = true ? ? ? ? ? ? strokeWidth = lineWidth ? ? ? ? ? ? style = Paint.Style.STROKE ? ? ? ? } ? ? ? ? mLabelPaint = Paint() ? ? ? ? with(mLabelPaint) { ? ? ? ? ? ? isAntiAlias = true ? ? ? ? } ? ? ? ? mLabelBgPaint = Paint() ? ? ? ? with(mLabelBgPaint) { ? ? ? ? ? ? isAntiAlias = true ? ? ? ? ? ? color = labelBackgroundColor ? ? ? ? } ? ? ? ? mTextPaint = Paint() ? ? ? ? with(mTextPaint) { ? ? ? ? ? ? isAntiAlias = true ? ? ? ? ? ? textAlign = Paint.Align.CENTER ? ? ? ? } ? ? ? ? mLabelRectF = RectF() ? ? } ? ? ? override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { ? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec) ? ? ? ? val heightMode = MeasureSpec.getMode(heightMeasureSpec) ? ? ? ? val heightSize = MeasureSpec.getSize(heightMeasureSpec) ? ? ? ? var height = 0 ? ? ? ? if (heightMode == MeasureSpec.EXACTLY) { ? ? ? ? ? ? height = heightSize ? ? ? ? } else { ? ? ? ? ? ? height = SizeUtil.dp2px(308f).toInt() ? ? ? ? ? ? if (heightMode == MeasureSpec.AT_MOST) { ? ? ? ? ? ? ? ? height = Math.min(height, heightSize) ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? setMeasuredDimension(measuredWidth, height) ? ? } ? ? ? override fun onTouchEvent(event: MotionEvent?): Boolean { ? ? ? ? val touchX = event?.getX() ?: 0f ? ? ? ? for (i in 0..mDataPointList1.size - 1) { ? ? ? ? ? ? val centerX = mDataPointList1[i].x ? ? ? ? ? ? var beginX = centerX - mXScale / 2f ? ? ? ? ? ? var endX = centerX + mXScale / 2f ? ? ? ? ? ? if (i == 0) { ? ? ? ? ? ? ? ? beginX = 0f ? ? ? ? ? ? } ? ? ? ? ? ? if (i == mDataPointList1.size - 1) { ? ? ? ? ? ? ? ? endX = mWidth.toFloat() ? ? ? ? ? ? } ? ? ? ? ? ? if (beginX < touchX && touchX < endX) { ? ? ? ? ? ? ? ? mClickIndex = i ? ? ? ? ? ? ? ? invalidate() ? ? ? ? ? ? ? ? break ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return true ? ? } ? ? ? override fun onDraw(canvas: Canvas?) { ? ? ? ? canvas?.let { ? ? ? ? ? ? initSize(width, height) ? ?//初始化尺寸信息 ? ? ? ? ? ? drawCoordinate(it) ? ? ? ? //繪制坐標軸 ? ? ? ? ? ? drawLine(it) ? ? ? ? ? ? ? //繪制折線 ? ? ? ? ? ? drawLabel(it) ? ? ? ? ? ? ?//繪制點擊后的效果 ? ? ? ? ? ? drawBottomDescription(it) ?//繪制底部類型說明 ? ? ? ? } ? ? } ? ? ? //初始化尺寸信息 ? ? private fun initSize(width: Int, height: Int) { ? ? ? ? mWidth = width ? ? ? ? mHeight = height ? ? ? ? mXLength = mWidth - leftMargin - rightMargin ? ? ? ? mYLength = mHeight - topMargin - bottomMargin ? ? ? ? mXPoint = leftMargin ? ? ? ? mYPoint = mHeight - bottomMargin ? ? ? ? mXScale = mXLength / (mXLabelList.size - 1) ? ? ? ? mYScale = mYLength / yLabelCount ? ? ? ? mDataPointList1.clear() ? ? ? ? if (hasOnlyOneData()) { ? ? ? ? ? ? mDataPointList1.add(PointF(mXPoint + mXLength / 2f, calculateYPosition(mDataList1.get(0)))) ?//居中 ? ? ? ? } else { ? ? ? ? ? ? for (i in 0..mDataList1.size - 1) { ? ? ? ? ? ? ? ? mDataPointList1.add(PointF(mXPoint + i * mXScale, calculateYPosition(mDataList1.get(i)))) ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? mDataPointList2.clear() ? ? ? ? if (hasOnlyOneData()) { ? ? ? ? ? ? mDataPointList2.add(PointF(mXPoint + mXLength / 2f, calculateYPosition(mDataList2.get(0)))) ?//居中 ? ? ? ? } else { ? ? ? ? ? ? for (i in 0..mDataList2.size - 1) { ? ? ? ? ? ? ? ? mDataPointList2.add(PointF(mXPoint + i * mXScale, calculateYPosition(mDataList2.get(i)))) ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? //繪制坐標軸 ? ? private fun drawCoordinate(canvas: Canvas) { ? ? ? ? //繪制X軸 ? ? ? ? canvas.drawLine(mXPoint - axisWidth / 2f, mYPoint, mXPoint + mXLength + axisWidth / 2f, mYPoint, mAxisPaint) ? ? ? ? with(mTextPaint) { ? ? ? ? ? ? textSize = xLabelTextSize ? ? ? ? ? ? color = xLabelTextColor ? ? ? ? } ? ? ? ? val fm = mTextPaint.getFontMetrics() ? ? ? ? val yOffset = mYPoint + xLabelTextMarginTop - fm.ascent ? ? ? ? for (i in 0..mXLabelList.size - 1) { ? ? ? ? ? ? //繪制X軸的刻度值文本 ? ? ? ? ? ? if (i == 0) { ?//第一個刻度值文本 ? ? ? ? ? ? ? ? if (hasOnlyOneData()) { ?//只有一條數(shù)據(jù)時居中顯示 ? ? ? ? ? ? ? ? ? ? mTextPaint.textAlign = Paint.Align.CENTER ? ? ? ? ? ? ? ? ? ? canvas.drawText(mXLabelList[i], mDataPointList1[i].x, yOffset, mTextPaint) ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? mTextPaint.textAlign = Paint.Align.LEFT ? ? ? ? ? ? ? ? ? ? canvas.drawText(mXLabelList[i], mXPoint, yOffset, mTextPaint) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else if (i == mXLabelList.size - 1) { ?//最后一個刻度值文本 ? ? ? ? ? ? ? ? mTextPaint.textAlign = Paint.Align.RIGHT ? ? ? ? ? ? ? ? canvas.drawText(mXLabelList[i], mXPoint + mXLength, yOffset, mTextPaint) ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? mTextPaint.textAlign = Paint.Align.CENTER ? ? ? ? ? ? ? ? canvas.drawText(mXLabelList[i], mXPoint + i * mXScale, yOffset, mTextPaint) ? ? ? ? ? ? } ? ? ? ? ? ? //繪制X軸上的小刻度線 ? ? ? ? ? ? if (showScale) { ? ? ? ? ? ? ? ? canvas.drawLine( ? ? ? ? ? ? ? ? ? ? mXPoint + i * mXScale, ? ? ? ? ? ? ? ? ? ? mYPoint, ? ? ? ? ? ? ? ? ? ? mXPoint + i * mXScale, ? ? ? ? ? ? ? ? ? ? mYPoint - scaleLength, ? ? ? ? ? ? ? ? ? ? mAxisPaint ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? for (i in 0..yLabelCount - 1) { ? ? ? ? ? ? //繪制網(wǎng)格線:橫刻線 ? ? ? ? ? ? if (showGrid) { ? ? ? ? ? ? ? ? mGridPaint.color = gridColor ? ? ? ? ? ? ? ? canvas.drawLine( ? ? ? ? ? ? ? ? ? ? mXPoint, ? ? ? ? ? ? ? ? ? ? mYPoint - (i + 1) * mYScale, ? ? ? ? ? ? ? ? ? ? mXPoint + mXLength, ? ? ? ? ? ? ? ? ? ? mYPoint - (i + 1) * mYScale, ? ? ? ? ? ? ? ? ? ? mGridPaint ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? } ? ? ? ? ? ? //繪制Y軸上的刻度值 ? ? ? ? ? ? if (showYLabelText) { ? ? ? ? ? ? ? ? with(mTextPaint) { ? ? ? ? ? ? ? ? ? ? textSize = yLabelTextSize ? ? ? ? ? ? ? ? ? ? color = yLabelTextColor ? ? ? ? ? ? ? ? ? ? textAlign = Paint.Align.LEFT ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? if (i == 0) { ? ? ? ? ? ? ? ? ? ? canvas.drawText(mYLabelList[i], yLabelTextMarginLeft, mYPoint, mTextPaint) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? val yLabelFm = mTextPaint.getFontMetrics() ? ? ? ? ? ? ? ? val yLabelYOffset = mYPoint + (yLabelFm.descent - yLabelFm.ascent) / 2f - yLabelFm.descent - (i + 1) * mYScale ? ? ? ? ? ? ? ? canvas.drawText(mYLabelList[i + 1], yLabelTextMarginLeft, yLabelYOffset, mTextPaint) ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? //繪制折線 ? ? private fun drawLine(canvas: Canvas) { ? ? ? ? if (mDataList1 == null || mDataList1.size <= 0 || mDataList2 == null || mDataList2.size <= 0) { ? ? ? ? ? ? return ? ? ? ? } ? ? ? ? if (hasOnlyOneData()) { ?//處理只有一條數(shù)據(jù)的情況 ? ? ? ? ? ? //繪制第一條直線 ? ? ? ? ? ? mLinePaint.color = lineColor1 ? ? ? ? ? ? canvas.drawLine(mXPoint, mDataPointList1[0].y, mXPoint + mXLength, mDataPointList1[0].y, mLinePaint) ? ? ? ? ? ? //繪制第二條直線 ? ? ? ? ? ? mLinePaint.color = lineColor2 ? ? ? ? ? ? canvas.drawLine(mXPoint, mDataPointList2[0].y, mXPoint + mXLength, mDataPointList2[0].y, mLinePaint) ? ? ? ? ? ? return ? ? ? ? } ? ? ? ? for (i in 0..mDataPointList1.size - 2) { ? ? ? ? ? ? if (i <= mCurrentDrawIndex) { ? ? ? ? ? ? ? ? //繪制第一條折線 ? ? ? ? ? ? ? ? //繪制折線 ? ? ? ? ? ? ? ? mLinePaint.color = lineColor1 ? ? ? ? ? ? ? ? canvas.drawLine( ? ? ? ? ? ? ? ? ? ? mDataPointList1[i].x, mDataPointList1[i].y, ? ? ? ? ? ? ? ? ? ? mDataPointList1[i + 1].x, mDataPointList1[i + 1].y, mLinePaint ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? ? ? //繪制折線交點 ? ? ? ? ? ? ? ? canvas.drawCircle(mDataPointList1[i].x, mDataPointList1[i].y, lineWidth * 1.5f, mLinePaint) ? ? ? ? ? ? ? ? mLinePaint.color = Color.WHITE ? ? ? ? ? ? ? ? canvas.drawCircle(mDataPointList1[i].x, mDataPointList1[i].y, lineWidth * 0.5f, mLinePaint) ? ? ? ? ? ? ? ? ? //繪制第二條折線 ? ? ? ? ? ? ? ? //繪制折線 ? ? ? ? ? ? ? ? mLinePaint.color = lineColor2 ? ? ? ? ? ? ? ? canvas.drawLine( ? ? ? ? ? ? ? ? ? ? mDataPointList2[i].x, mDataPointList2[i].y, ? ? ? ? ? ? ? ? ? ? mDataPointList2[i + 1].x, mDataPointList2[i + 1].y, mLinePaint ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? ? ? //繪制折線交點 ? ? ? ? ? ? ? ? canvas.drawCircle(mDataPointList2[i].x, mDataPointList2[i].y, lineWidth * 1.5f, mLinePaint) ? ? ? ? ? ? ? ? mLinePaint.color = Color.WHITE ? ? ? ? ? ? ? ? canvas.drawCircle(mDataPointList2[i].x, mDataPointList2[i].y, lineWidth * 0.5f, mLinePaint) ? ? ? ? ? ? ? ? ? //繪制最后一個折線交點 ? ? ? ? ? ? ? ? if (i == mDataPointList1.size - 2) { ? ? ? ? ? ? ? ? ? ? mLinePaint.color = lineColor1 ? ? ? ? ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList1[mDataPointList1.size - 1].x, ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList1[mDataPointList1.size - 1].y, ? ? ? ? ? ? ? ? ? ? ? ? lineWidth * 1.5f, ? ? ? ? ? ? ? ? ? ? ? ? mLinePaint ? ? ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? ? ? ? ? mLinePaint.color = Color.WHITE ? ? ? ? ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList1[mDataPointList1.size - 1].x, ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList1[mDataPointList1.size - 1].y, ? ? ? ? ? ? ? ? ? ? ? ? lineWidth * 0.5f, ? ? ? ? ? ? ? ? ? ? ? ? mLinePaint ? ? ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? ? ? ? ? ? mLinePaint.color = lineColor2 ? ? ? ? ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList2[mDataPointList2.size - 1].x, ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList2[mDataPointList2.size - 1].y, ? ? ? ? ? ? ? ? ? ? ? ? lineWidth * 1.5f, ? ? ? ? ? ? ? ? ? ? ? ? mLinePaint ? ? ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? ? ? ? ? mLinePaint.color = Color.WHITE ? ? ? ? ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList2[mDataPointList2.size - 1].x, ? ? ? ? ? ? ? ? ? ? ? ? mDataPointList2[mDataPointList2.size - 1].y, ? ? ? ? ? ? ? ? ? ? ? ? lineWidth * 0.5f, ? ? ? ? ? ? ? ? ? ? ? ? mLinePaint ? ? ? ? ? ? ? ? ? ? ) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? //計算數(shù)值對應的Y坐標 ? ? private fun calculateYPosition(data: Float): Float = mYPoint - data / maxYValue * mYLength ? ? ? //繪制點擊后的詳情展示 ? ? private fun drawLabel(canvas: Canvas) { ? ? ? ? if (clickAble && mDataList1.size > 0) { ? ? ? ? ? ? //繪制點擊后的豎刻線 ? ? ? ? ? ? mLabelPaint.color = Color.parseColor("#EBEBEB") ? ? ? ? ? ? mLabelPaint.strokeWidth = DEFAULT_GRID_WIDTH * 2 ? ? ? ? ? ? canvas.drawLine( ? ? ? ? ? ? ? ? mDataPointList1[mClickIndex].x, ? ? ? ? ? ? ? ? mYPoint, ? ? ? ? ? ? ? ? mDataPointList1[mClickIndex].x, ? ? ? ? ? ? ? ? topMargin - labelArrowMargin, ? ? ? ? ? ? ? ? mLabelPaint ? ? ? ? ? ? ) ? ? ? ? ? ? //繪制點擊后的折線交點 ? ? ? ? ? ? mLabelPaint.color = lineColor1 ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? mDataPointList1[mClickIndex].x, ? ? ? ? ? ? ? ? mDataPointList1[mClickIndex].y, ? ? ? ? ? ? ? ? lineWidth * 2.3f, ? ? ? ? ? ? ? ? mLabelPaint ? ? ? ? ? ? ) ? ? ? ? ? ? mLabelPaint.color = lineColor2 ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? mDataPointList2[mClickIndex].x, ? ? ? ? ? ? ? ? mDataPointList2[mClickIndex].y, ? ? ? ? ? ? ? ? lineWidth * 2.3f, ? ? ? ? ? ? ? ? mLabelPaint ? ? ? ? ? ? ) ? ? ? ? ? ? //繪制最上方標簽信息 ? ? ? ? ? ? with(mLabelRectF) { ? ? ? ? ? ? ? ? bottom = topMargin - labelArrowMargin - labelArrowHeight ? ? ? ? ? ? ? ? top = bottom - labelHeight; ? ? ? ? ? ? ? ? left = mDataPointList1[mClickIndex].x - labelArrowWidth / 2f - labelArrowOffset ? ? ? ? ? ? ? ? right = left + labelWidth ? ? ? ? ? ? ? ? //處理點擊第一項出現(xiàn)標簽偏離整個折線圖現(xiàn)象 ? ? ? ? ? ? ? ? if (left < 0) { ? ? ? ? ? ? ? ? ? ? left = SizeUtil.dp2px(5f) ? ? ? ? ? ? ? ? ? ? right = left + labelWidth ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? //處理點擊最后一項出現(xiàn)標簽偏離整個折線圖現(xiàn)象 ? ? ? ? ? ? ? ? if (right > mWidth) { ? ? ? ? ? ? ? ? ? ? right = mWidth.toFloat() - SizeUtil.dp2px(5f) ? ? ? ? ? ? ? ? ? ? left = right - labelWidth ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? //繪制圓角矩形 ? ? ? ? ? ? mLabelBgPaint.setShadowLayer( ? ? ? ? ? ? ? ? SizeUtil.dp2px(12f), ?//陰影效果 ? ? ? ? ? ? ? ? SizeUtil.dp2px(2.5f), ? ? ? ? ? ? ? ? SizeUtil.dp2px(1.5f), ? ? ? ? ? ? ? ? Color.parseColor("#C7C7C7") ? ? ? ? ? ? ) ? ? ? ? ? ? canvas.drawRoundRect(mLabelRectF, labelRadius, labelRadius, mLabelBgPaint) ? ? ? ? ? ? //繪制箭頭 ? ? ? ? ? ? val arrowPath = Path() ? ? ? ? ? ? with(arrowPath) { ? ? ? ? ? ? ? ? moveTo(mDataPointList1[mClickIndex].x, topMargin - labelArrowMargin) ? ? ? ? ? ? ? ? val baseY = topMargin - labelArrowMargin - labelArrowHeight - SizeUtil.dp2px(1f) ? ? ? ? ? ? ? ? lineTo(mDataPointList1[mClickIndex].x - labelArrowWidth / 2f, baseY) ? ? ? ? ? ? ? ? lineTo(mDataPointList1[mClickIndex].x + labelArrowWidth / 2f, baseY) ? ? ? ? ? ? ? ? close() ? ? ? ? ? ? } ? ? ? ? ? ? mLabelPaint.color = labelBackgroundColor ? ? ? ? ? ? canvas.drawPath(arrowPath, mLabelPaint) ? ? ? ? ? ? mLabelPaint.color = Color.parseColor("#F1F1F1") ? ? ? ? ? ? mLabelPaint.strokeWidth = gridWidth ? ? ? ? ? ? canvas.drawLine( ? ? ? ? ? ? ? ? mLabelRectF.left + SizeUtil.dp2px(10f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(52f), ? ? ? ? ? ? ? ? mLabelRectF.right - SizeUtil.dp2px(10f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(52f), mLabelPaint ? ? ? ? ? ? ) ? ? ? ? ? ? //繪制文字 ? ? ? ? ? ? with(mTextPaint) { ? ? ? ? ? ? ? ? color = labelTextColor ? ? ? ? ? ? ? ? textSize = labelTextSize ? ? ? ? ? ? ? ? textAlign = Paint.Align.LEFT ? ? ? ? ? ? } ? ? ? ? ? ? canvas.drawText( ? ? ? ? ? ? ? ? mXLabelList[mClickIndex], ? ? ? ? ? ? ? ? mLabelRectF.left + SizeUtil.dp2px(9.5f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(61f), mTextPaint ? ? ? ? ? ? ) ? ? ? ? ? ? canvas.drawText( ? ? ? ? ? ? ? ? "交易收益 ?¥${mDataList1[mClickIndex]}", ? ? ? ? ? ? ? ? mLabelRectF.left + SizeUtil.dp2px(19.5f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(32.5f), mTextPaint ? ? ? ? ? ? ) ? ? ? ? ? ? canvas.drawText( ? ? ? ? ? ? ? ? "返現(xiàn)收益 ?¥${mDataList2[mClickIndex]}", ? ? ? ? ? ? ? ? mLabelRectF.left + SizeUtil.dp2px(19.5f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(12.5f), mTextPaint ? ? ? ? ? ? ) ? ? ? ? ? ? mTextPaint.color = lineColor1 ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? mLabelRectF.left + SizeUtil.dp2px(12.5f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(36f), ? ? ? ? ? ? ? ? SizeUtil.dp2px(2.5f), mTextPaint ? ? ? ? ? ? ) ? ? ? ? ? ? mTextPaint.color = lineColor2 ? ? ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? ? ? mLabelRectF.left + SizeUtil.dp2px(12.5f), ? ? ? ? ? ? ? ? mLabelRectF.bottom - SizeUtil.dp2px(16f), ? ? ? ? ? ? ? ? SizeUtil.dp2px(2.5f), mTextPaint ? ? ? ? ? ? ) ? ? ? ? } ? ? } ? ? ? //繪制底部類型說明 ? ? private fun drawBottomDescription(canvas: Canvas) { ? ? ? ? if (mDataList1 == null || mDataList1.size == 0 || mDataList2 == null || mDataList2.size == 0) { ? ? ? ? ? ? return ? ? ? ? } ? ? ? ? mTextPaint.color = lineColor1 ? ? ? ? val centerX1 = mWidth / 2f - SizeUtil.dp2px(75.5f) ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? centerX1, mHeight - SizeUtil.dp2px(20f), ? ? ? ? ? ? SizeUtil.dp2px(3.5f), mTextPaint ? ? ? ? ) ? ? ? ? mTextPaint.color = lineColor2 ? ? ? ? val centerX2 = mWidth / 2f + SizeUtil.dp2px(16f) ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? centerX2, mHeight - SizeUtil.dp2px(20f), ? ? ? ? ? ? SizeUtil.dp2px(3.5f), mTextPaint ? ? ? ? ) ? ? ? ? mTextPaint.color = Color.WHITE ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? centerX1, mHeight - SizeUtil.dp2px(20f), ? ? ? ? ? ? SizeUtil.dp2px(2.2f), mTextPaint ? ? ? ? ) ? ? ? ? canvas.drawCircle( ? ? ? ? ? ? centerX2, mHeight - SizeUtil.dp2px(20f), ? ? ? ? ? ? SizeUtil.dp2px(2.2f), mTextPaint ? ? ? ? ) ? ? ? ? with(mTextPaint) { ? ? ? ? ? ? color = labelTextColor ? ? ? ? ? ? textSize = SizeUtil.sp2px(12f) ? ? ? ? } ? ? ? ? canvas.drawText( ? ? ? ? ? ? "交易收益", centerX1 + SizeUtil.dp2px(8f), ? ? ? ? ? ? mHeight - SizeUtil.dp2px(15.5f), mTextPaint ? ? ? ? ) ? ? ? ? canvas.drawText( ? ? ? ? ? ? "返現(xiàn)收益", centerX2 + SizeUtil.dp2px(8f), ? ? ? ? ? ? mHeight - SizeUtil.dp2px(15.5f), mTextPaint ? ? ? ? ) ? ? } ? ? ? //格式化標簽內(nèi)的數(shù)值文本 ? ? private fun formatValue(value: Float): String { ? ? ? ? val scale = maxYValue / yLabelCount.toFloat() ? ? ? ? if (scale < 10 && (value != value.toInt().toFloat()) && (value >= 0.01f)) { ? ? ? ? ? ? return "${(value * 100).toInt().toFloat() / 100}" ?//保留2位小數(shù),但不四舍五入 ? ? ? ? } ? ? ? ? return "${value.toInt()}" ? ? } ? ? ? //是否只有一條數(shù)據(jù) ? ? private fun hasOnlyOneData(): Boolean = mDataList1.size == 1 && mDataList2.size == 1 && mXLabelList.size == 1 ? ? ? //設置數(shù)據(jù),startAnim:是否開啟動畫,動畫默認一條一條折線的畫 ? ? //list1和list2的數(shù)據(jù)個數(shù)要相同,dateList的數(shù)據(jù)個數(shù)大于等于list1和list2的數(shù)據(jù)個數(shù) ? ? fun drawData(list1: MutableList<Float>, list2: MutableList<Float>, dateList: MutableList<String>, startAnim: Boolean = false) { ? ? ? ? if (list1.size != list2.size) { ? ? ? ? ? ? throw RuntimeException("the size of list1 must be equal to the size of list2") ? ? ? ? } ? ? ? ? if (dateList.size < list1.size) { ? ? ? ? ? ? throw RuntimeException("the size of dateList can not less than the size of list1") ? ? ? ? } ? ? ? ? var maxValue = 0f ? ? ? ? for (item in list1) { ? ? ? ? ? ? if (maxValue <= item) { ? ? ? ? ? ? ? ? maxValue = item ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? for (item in list2) { ? ? ? ? ? ? if (maxValue <= item) { ? ? ? ? ? ? ? ? maxValue = item ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? mDataList1 = list1 ? ? ? ? mDataList2 = list2 ? ? ? ? mXLabelList = dateList ? ? ? ? maxYValue = calculateMaxValue(maxValue) ? ? ? ? mClickIndex = 0 ? ? ? ? setYLable() ?//重新設置Y軸刻度值 ? ? ? ? if (startAnim) { ? ? ? ? ? ? val animator = ValueAnimator.ofInt(0, mDataList1.size - 2) ? ? ? ? ? ? animator.setDuration(1500) ? ? ? ? ? ? animator.addUpdateListener { ? ? ? ? ? ? ? ? mCurrentDrawIndex = it.getAnimatedValue() as Int ? ? ? ? ? ? ? ? invalidate() ? ? ? ? ? ? } ? ? ? ? ? ? animator.interpolator = LinearInterpolator() ? ? ? ? ? ? animator.start() ? ? ? ? } else { ? ? ? ? ? ? mCurrentDrawIndex = mDataList1.size - 2 ? ? ? ? ? ? invalidate() ? ? ? ? } ? ? } ? ? ? //計算Y軸最大值和單位,計算規(guī)則:最高位數(shù)加1取整 ? ? private fun calculateMaxValue(value: Float): Int { ? ? ? ? val valueStr = value.toLong().toString() ? ? ? ? val length = valueStr.length ?//整數(shù)的位數(shù) ? ? ? ? val unit = Math.pow(10.0, (length - 1).toDouble()).toInt() ? ? ? ? if (value == 0f) { ? ? ? ? ? ? return DEFAULT_MAX_YVALUE ?//如果最大值是0,即所有數(shù)據(jù)都是0,取默認的最大值 ? ? ? ? } else if (value % unit == 0f) { ? ? ? ? ? ? return value.toInt() ? ? ? ? } else { ? ? ? ? ? ? return ((value / unit).toInt() + 1) * unit ? ? ? ? } ? ? } ? }
使用舉例:
private fun createType2Data(count: Int, isDateMore: Boolean = false, startAnim: Boolean = false, showYLabelText: Boolean = false) { ? ? ? ? val list1: MutableList<Float> = mutableListOf() ? ? ? ? val list2: MutableList<Float> = mutableListOf() ? ? ? ? val dateList: MutableList<String> = mutableListOf() ? ? ? ? for (i in 0..count) { ? ? ? ? ? ? list1.add(Random.nextDouble(80.0).toFloat()) ? ? ? ? ? ? list2.add(Random.nextDouble(80.0).toFloat()) ? ? ? ? ? ? dateList.add(DateUtil.getDistanceDateByDay(i - count, DateUtil.M_D)) ? ? ? ? } ? ? ? ? if (isDateMore) { ? ? ? ? ? ? dateList.add(DateUtil.getDistanceDateByDay(1, DateUtil.M_D)) ? ? ? ? } ? ? ? ? if (showYLabelText) { ? ? ? ? ? ? binding.type2Lc.leftMargin = SizeUtil.dp2px(40f) ? ? ? ? } else { ? ? ? ? ? ? binding.type2Lc.leftMargin = SizeUtil.dp2px(15f) ? ? ? ? } ? ? ? ? binding.type2Lc.showYLabelText = showYLabelText ? ? ? ? binding.type2Lc.drawData(list1, list2, dateList, startAnim) ?}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Flutter app頁面路由以及路由攔截的實現(xiàn)
本篇介紹了介紹了Flutter如何使用路由來實現(xiàn)頁面的跳轉(zhuǎn),從而簡化頁面之間的耦合,并可以實現(xiàn)路由攔截。2021-06-06RxJava+Retrofit實現(xiàn)網(wǎng)絡請求封裝的方法
Retrofit是當前應用非常廣泛的網(wǎng)絡請求框架,通常結(jié)合RxJava來進行網(wǎng)絡請求,本文將展示一個采用RxJava+Retrofit的網(wǎng)絡請求demo,感興趣的可以了解一下2019-04-04Android 自動化測試經(jīng)驗分享 UiObejct.getFromParent()的使用方法
本篇文章對Android中UiObejct.getFromParent()的使用進行了詳細的分析介紹。需要的朋友參考下2013-05-05