最近有关区块链的项目层出不穷,在项目中碰到了绘制比特币涨幅走势图的需求,在网上搜了一些案例,大致就是利用绘制贝塞尔曲线来完成。
Recent projects relating to block chains have evolved, encountered the need for a Bitcoin upscaling map in the project, and examined some cases online, largely using the Bézier curve.
思路来源于绘制股票走势图,主要内容在于自定义K_View,效果图:
The idea stems from the mapping of stock trends, mainly in custom K_View, impact maps:
大致步骤:
General steps:
1、绘制X、Y坐标轴并绘制坐标;
1. Draw the X-Y-coordinate axis and draw the coordinates;
2、根据数据绘制走势图,其实就是根据返回数据的多个点连成的平滑曲线;
(ii) The mapping of trends based on data, which is a smooth curve linked to multiple points of returned data;
3、根据手势找点,然后绘制当前所在点并显示具体数据。
3. Find points based on gestures and then draw current points and display specific data.
相关数据对象类
Relevant data object class
public class FundMode? implements Serializable {
//x轴原始时间数据,ms
//x axis raw time data, ms
? ? public Stringtime;
public Stringlast;
public float dataY;
//在自定义view:FundView中的位置坐标
// in custom view: FundView
? ? public float floatX;
public float floatY;
}
public class XYEntityimplements Serializable{
public Listxlist;
public Listylist;
}
这里的内容只是让一些小白们看的更容易理解,早对象可以根据需求随意改动,各取所需。
The content here is simply easier for some white people to see, and the early audience can vary according to demand.
Xml布局中代码
The code in the Xml layout /i>
<XXXXX....K_VIew
? ? android:id="@+id/k_view"
? ? android:layout_width="match_parent"
? ? android:layout_height="@dimen/base130dp"
? ? app:xyTextSize="@dimen/base8sp"
? ? app:loadingTextSize="@dimen/base12sp"
? ? app:longPressTextSize="@dimen/base10sp"
? ? app:loadingText="正在加载数据...."
♪ App:loading Text= "loading data..."
? ? app:xBottomTopPadding="@dimen/base8dp"
? ? app:reactWidth="@dimen/base100dp"
? ? app:reactHeight="@dimen/base38dp"
? ? app:reactTextMargin_top="@dimen/base8dp"
? ? app:reactTextMargin_bottom="@dimen/base23dp"
? ? app:paddingTop_FV="@dimen/base10dp"
? ? app:paddingBottom_FV="@dimen/base20dp"
? ? app:paddingRight_FV="@dimen/base10dp"
? ? app:yTextPadding="@dimen/base10dp"
? ? app:yTextRightPadding="@dimen/base5dp"
? ? android:background="#fff"/>
attrs.xml 中内容大致就是一些自定义属性,内容如下
The contents of anatrs.xml are broadly defined properties, as follows:
activity 中需要执行的操作很少,从服务器获取到数据后 直接调用 k_view.setData(apiResult)即可;
Very few operations to perform in activity, call k_view.setData(apiResult) as soon as the data are obtained from the server;
下面是自定义view具体代码,所有逻辑都包括在里面了
Here's the custom code for the view. All the logic is in it.
public class K_View? extends View {
//控件默认宽高
// Control default width
private static final float DEF_WIDTH=650;
private static final float DEF_HIGHT=400;
//数据源
/ / data sources
? ApiResult2<List< FundMode>,XYEntity>>apiResult;
//ApiResult2 服务器返回的数据,FundMode平滑曲线上的点,XYEntity X、Y对应坐标,下面贴出数据结构
/ApiResult2 server returns data, FundMode smooth curve points, XYEntity X, Y corresponding coordinates, post the data structure below
//控件宽高
// Control width
? ? int mWidth;
int mHeight;
//上下左右padding
/ /padding up and down
? ? int mPaddingTop=30;
int mPaddingBottom=50;
int yTextPadding=20;
float mPaddingLeft=70;
int mPaddingRight=30;
int yTextRightPadding=5;
float textTopPadding=5;
int reactHeight=80;
int reactWidth=210;
int reactTextMargin_top=20;
int reactTextMargin_bottom=50
FundMode mMinFundMode;
FundMode mMaxFundMode;
float maxY;
float minY;
//X、Y轴每一个data对应的大小
//X, the size of each data at the Y axis
? ? float mPerX;
float mPerY;
//正在加载中
/ / loading in progress
? ? Paint mLoadingPaint;
int mLoadingTextSize=20;
String mLoadingText="";
boolean mDrawLoadingPaint=true;
Paint xyPaint;
//外围X、Y轴线文字
/ Perimeter X, Y axis text
? ? Paint mXYPaint;
Paint longPressPaint;
//x、y轴指示文字字体的大小
//x, y-axis indicates the font size of the text
? ? Paint rectTextPaint;
private int mXYTextSize=20;
//左侧文字距离左边线线的距离
// left text distance from left line
? ? final float mLeftTxtPadding=5;
//底部文字距离底部线的距离
// Bottom text distance from bottom line
? ? int xBottomTopPadding=20;
float halfTextWidth_X=22;
private ListpointData=new ArrayList<>();
private int pointCount;
//内部X轴虚线
// Internal X-axis
? ? Paint mInnerXPaint;
float mInnerXStrokeWidth=1;
//折线
Line / / / Line / Line / Line / Line / Line / Line / Line / Line / Line / Line / Line / Line / Line / Line / Line /
? ? Paint mBrokenPaint;
Paint rectBGPaint;
Paint alphaPaint;
//单位:dp
/ Unit: dp
//长按的十字线
// Long-pressed crosslines
? ? Paint mLongPressPaint;
Paint blueLinePaint;
boolean mDrawLongPressPaint=false;
//长按处理
// Long press process
? ? long mPressTime;
//默认多长时间算长按
// Default length of time
? ? final long DEF_LONGPRESS_LENGTH=200;
float mPressX;
float mPressY;
//最上面默认显示累计收益金额
Accumulated amount of proceeds shown by default above/above
? ? final float mDefAllIncomeTextSize=20;
//长按情况下x轴和y轴要显示的文字
Text to display in x-axis and y-axis in case of length
? ? Paint mLongPressTxtPaint;
int mLongPressTextSize=25;
public K_View(Context context) {
this(context,null);
}
public K_View(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public K_View(Context context, @Nullable AttributeSet attrs,int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.K_View);
mXYTextSize=a.getDimensionPixelSize(R.styleable.K_View_xyTextSize, mXYTextSize);
mLoadingTextSize=a.getDimensionPixelSize(R.styleable.K_View_loadingTextSize, mLoadingTextSize);
mLongPressTextSize=a.getDimensionPixelSize(R.styleable.K_View_longPressTextSize, mLongPressTextSize);
mLoadingText=a.getString(R.styleable.K_View_loadingText);
xBottomTopPadding=a.getDimensionPixelSize(R.styleable.K_View_xBottomTopPadding, xBottomTopPadding);
reactWidth=a.getDimensionPixelSize(R.styleable.K_View_reactWidth, reactWidth);
reactHeight=a.getDimensionPixelSize(R.styleable.K_View_reactHeight, reactHeight);
reactTextMargin_top=a.getDimensionPixelSize(R.styleable.K_View_reactTextMargin_top, reactTextMargin_top);
reactTextMargin_bottom=a.getDimensionPixelSize(R.styleable.K_View_reactTextMargin_bottom, reactTextMargin_bottom);
mPaddingTop=a.getDimensionPixelSize(R.styleable.K_View_paddingTop_FV, mPaddingTop);
mPaddingBottom=a.getDimensionPixelSize(R.styleable.K_View_paddingBottom_FV, mPaddingBottom);
mPaddingRight=a.getDimensionPixelSize(R.styleable.K_View_paddingRight_FV, mPaddingRight);
yTextPadding=a.getDimensionPixelSize(R.styleable.K_View_yTextPadding, yTextPadding);
yTextRightPadding=a.getDimensionPixelSize(R.styleable.K_View_yTextRightPadding, yTextRightPadding);
initAttrs();
}
@Override
protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode=MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize=MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize=MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode==AT_MOST && heightSpecMode==AT_MOST) {
setMeasuredDimension((int) DEF_WIDTH, (int) DEF_HIGHT);
}else if (widthSpecMode==AT_MOST) {
setMeasuredDimension((int) DEF_WIDTH, heightSpecSize);
}else if (heightSpecMode==AT_MOST) {
setMeasuredDimension(widthSpecSize, (int) DEF_HIGHT);
}else {
setMeasuredDimension(widthSpecSize, heightSpecSize);
}
mWidth=getMeasuredWidth();
mHeight=getMeasuredHeight();
}
@Override
protected void onLayout(boolean changed,int left,int top,int right,int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//默认加载loading界面
/ / Default loading interface
? ? ? ? showLoadingPaint(canvas);
if (apiResult==null || apiResult.data.size()==0)return;
drawInnerXPaint(canvas);
drawBrokenPaint(canvas);
drawXYPaint(canvas);
drawLongPress(canvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//? ? ? ? ? ? ? ? mPressTime=event.getDownTime();
? ? ? ? ? ? ? ? mPressX=event.getX();
mPressY=event.getY();
//处理长按后的逻辑
/ / Process long after logic
? ? ? ? ? ? ? ? showLongPressView();
break;
case MotionEvent.ACTION_MOVE:
mPressX=event.getX();
mPressY=event.getY();
//处理长按后的逻辑
/ / Process long after logic
? ? ? ? ? ? ? ? ? ? showLongPressView();
//? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? break;
case MotionEvent.ACTION_UP:
//处理松手后的逻辑
// Deal with the logic of letting go
? ? ? ? ? ? ? ? hiddenLongPressView();
break;
default:
break;
}
return true;
}
private void initAttrs() {
intXYLintPaint();
initRectBGPaint();
initLoadingPaint();
initRectTextPaint();
initInnerXPaint();
initXYPaint();
initBrokenPaint();
initAlphaPaint();
initLongPressPaint();
initYLinePaint();
//? ? ? ? initTopTxt();
? ? }
private void intXYLintPaint() {
xyPaint=new Paint();
xyPaint.setColor(getColor(R.color.gray));
xyPaint.setStrokeWidth(mInnerXStrokeWidth);
}
private void initRectBGPaint() {
rectBGPaint=getRectBGPaint();
}
private void initLoadingPaint() {
mLoadingPaint=new Paint();
mLoadingPaint.setColor(getColor(R.color.gray));
mLoadingPaint.setTextSize(mLoadingTextSize);
mLoadingPaint.setAntiAlias(true);
}
//初始化绘制虚线的画笔
// Initialize the brushing of the dotted line
? ? private void initInnerXPaint() {
mInnerXPaint=new Paint();
mInnerXPaint.setColor(getColor(R.color.bg_lsj));
mInnerXPaint.setStrokeWidth(mInnerXStrokeWidth);
mInnerXPaint.setAlpha(40);
mInnerXPaint.setStyle(Paint.Style.STROKE);
}
private void initXYPaint() {
mXYPaint=new Paint();
mXYPaint.setColor(getColor(R.color.text_dz));
mXYPaint.setTextSize(mXYTextSize);
mXYPaint.setAntiAlias(true);
}
private void initLongPressTextPaint() {
longPressPaint=new Paint();
longPressPaint.setColor(getColor(R.color.text_dz));
longPressPaint.setTextSize(mXYTextSize);
longPressPaint.setAntiAlias(true);
}
private void initRectTextPaint() {
rectTextPaint=new Paint();
rectTextPaint.setColor(getColor(R.color.white));
rectTextPaint.setTextSize(mXYTextSize);
rectTextPaint.setAntiAlias(true);
}
private void initBrokenPaint() {
mBrokenPaint=new Paint();
mBrokenPaint.setColor(getColor(R.color.all_k_color));
mBrokenPaint.setStyle(Paint.Style.STROKE);
mBrokenPaint.setAntiAlias(true);
mBrokenPaint.setStrokeWidth(convertDp2Px(mInnerXStrokeWidth));
}
private void initAlphaPaint() {
alphaPaint=new Paint();
alphaPaint.setColor(getResources().getColor(R.color.all_k_color));
alphaPaint.setAntiAlias(true);
alphaPaint.setAlpha(40);
alphaPaint.setStyle(Paint.Style.FILL);
}
private void initLongPressPaint() {
mLongPressPaint=new Paint();
mLongPressPaint.setColor(getColor(R.color.white));
mLongPressPaint.setStyle(Paint.Style.FILL);
mLongPressPaint.setAntiAlias(true);
mLongPressPaint.setTextSize(mLongPressTextSize);
}
private void initYLinePaint() {
blueLinePaint=new Paint();
blueLinePaint.setColor(getColor(R.color.bg_lsj));
blueLinePaint.setStrokeWidth(1);
blueLinePaint.setAntiAlias(true);
}
private void showLoadingPaint(Canvas canvas) {
if (!mDrawLoadingPaint)return;
//这里特别注意,x轴的起始点要减去文字宽度的一半
// Particular attention is given here that the starting point of the x-axis is less than half the width of the text
? ? ? ? canvas.drawText(mLoadingText, mWidth /2 - mLoadingPaint.measureText(mLoadingText) /2, mHeight /2, mLoadingPaint);
}
private void drawInnerXPaint(Canvas canvas) {
//画5条横轴的虚线
// Draws a thin line of 5 horizontal axes
//首先确定最大值和最小值的位置
/// First determine the location of maximum and minimum values
? ? ? ? float perHight=(mHeight - mPaddingBottom - mPaddingTop) /3;
canvas.drawLine(mPaddingLeft,mPaddingTop,mPaddingLeft,mHeight - mPaddingBottom,xyPaint);
canvas.drawLine(mPaddingLeft,mHeight - mPaddingBottom,mPaddingLeft+mPerX*(apiResult.data.size()-1),mHeight - mPaddingBottom,xyPaint);
canvas.drawLine(0 + mPaddingLeft, mPaddingTop,
mPaddingLeft+mPerX*(apiResult.data.size()-1), mPaddingTop, mInnerXPaint);//最上面的那一条
mPadddingLft+mPerX* (apiResult.data.size(()-1), mPadddingTop, mInnerXPaint);//
? ? ? ? canvas.drawLine(0 + mPaddingLeft, mPaddingTop + perHight *1,
mPaddingLeft+mPerX*(apiResult.data.size()-1), mPaddingTop + perHight *1, mInnerXPaint);//2
? ? ? ? canvas.drawLine(0 + mPaddingLeft, mPaddingTop + perHight *2,
mPaddingLeft+mPerX*(apiResult.data.size()-1), mPaddingTop + perHight *2, mInnerXPaint);//4
? ? }
private void drawBrokenPaint(Canvas canvas) {
if(pointData.size()>0){//清空所有点
if (pointData.size()>0) {/ emptied all points
? ? ? ? ? ? pointData.clear();
}
//先画第一个点
/// Draw the first dot first
? ? ? ? FundMode fundMode=apiResult.data.get(0);
Path path=new Path();
//这里需要说明一下,x轴的起始点,其实需要加上mPerX,但是加上之后不是从起始位置开始,不好看。
The starting point of the x-axis actually needs to be added to mPerX, but then it doesn't start from the beginning. It's not good.
// 同理,for循环内x轴其实需要(i+1)。现在这样处理,最后会留一点空隙,其实挺好看的。
/ Similarly, the x-axis in the for cycle actually need (i+1) to be dealt with now and eventually leave a little space, which is really pretty.
? ? ? ? float floatY=mHeight - mPaddingBottom - mPerY * ((Float.parseFloat(fundMode.last) - minY));
fundMode.floatX=mPaddingLeft;
fundMode.floatY=floatY;
Path timeAlphaPath=new Path();
timeAlphaPath.moveTo(mPaddingLeft, mHeight - mPaddingBottom);
timeAlphaPath.lineTo(mPaddingLeft, floatY);
for (int i=0; i < apiResult.data.size(); i++) {
FundMode fm=apiResult.data.get(i);
float floatX1=mPaddingLeft + mPerX * i;
float floatY1=mHeight - mPaddingBottom - mPerY * ((Float.parseFloat(fm.last) - minY));
fm.floatX=floatX1;
fm.floatY=floatY1;
if(i%pointCount==0||i==apiResult.data.size()-1){
pointData.add(fm);
}
if(i
float floatX2=mPaddingLeft + mPerX * (i+1);
float floatY2=mHeight - mPaddingBottom - mPerY * ( (Float.parseFloat(apiResult.data.get(i+1).last) - minY));
float wt=(floatX1 + floatX2) /2;
float floatX1_last=wt;
float floatY1_last=floatY1;
float floatX2_next=wt;
float floatY2_next=floatY2;
if(i==0){
path.moveTo(floatX1, floatY1);
}
path.cubicTo(floatX1_last, floatY1_last, floatX2_next, floatY2_next, floatX2, floatY2);
timeAlphaPath.cubicTo(floatX1_last, floatY1_last, floatX2_next, floatY2_next, floatX2, floatY2);
}else {
timeAlphaPath.lineTo(floatX1 , mHeight - mPaddingBottom);
Paint paint=new Paint();
paint.setColor(getColor(R.color.bg_lsj));
paint.setAntiAlias(true);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);
paint.setAlpha(40);
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(timeAlphaPath, paint);
}
}
}
private void drawXYPaint(Canvas canvas) {
//先处理y轴方向文字
// Deal with y-axis text first
? ? ? ? drawYPaint(canvas);
//处理x轴方向文字
// Process x-axis text
? ? ? ? drawXPaint(canvas);
}
*
* @param canvas
*/
private void drawLongPress(Canvas canvas) {
if (!mDrawLongPressPaint)return;
//获取距离最近按下的位置的model
// Get the model from the nearest position
? ? ? ? float pressX=mPressX;
//循环遍历,找到距离最短的x轴的mode
//Coop through, find the shortest x-axis mode
? ? ? ? FundMode finalFundMode=pointData.get(0);
float minXLen=Integer.MAX_VALUE;
for (int i=0; i < pointData.size(); i++) {
FundMode currFunMode=pointData.get(i);
float abs=Math.abs(pressX - currFunMode.floatX);
if (abs < minXLen) {
finalFundMode=currFunMode;
minXLen=abs;
}
}
//x
? ? ? ? float topY=mHeight - mPaddingBottom - mPerY *? (maxY - minY);
int left=(int)finalFundMode.floatX-reactWidth>=mPaddingLeft?(int)finalFundMode.floatX-reactWidth:(int)finalFundMode.floatX;
int right=(int)finalFundMode.floatX-reactWidth>=mPaddingLeft?(int)finalFundMode.floatX:reactWidth+(int)finalFundMode.floatX;
int top=(int)finalFundMode.floatY-reactHeight>=(int)topY?(int)finalFundMode.floatY-reactHeight:(int)topY;
int bottom=(int)finalFundMode.floatY-reactHeight>=(int)topY?(int)finalFundMode.floatY:(int)topY+reactHeight;
Rect topDirty=new Rect(left, top, right, bottom);
canvas.drawRect(topDirty, rectBGPaint);
canvas.drawText(finalFundMode.time +"",
left+(reactWidth-mLongPressPaint.measureText(finalFundMode.time+""))/2,top+reactTextMargin_top+getFontHeight(mLongPressTextSize, mLongPressPaint) /2 , mLongPressPaint);
canvas.drawText("¥"+AppConfig.formatNum(finalFundMode.last) ,
left+(reactWidth-mLongPressPaint.measureText(finalFundMode.time+""))/2,top+reactTextMargin_bottom+getFontHeight(mLongPressTextSize, mLongPressPaint) /2 , mLongPressPaint);
}
public Paint getRectBGPaint() {
Paint paint=new Paint();
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setStrokeWidth(mInnerXStrokeWidth);
paint.setAlpha(85);
paint.setStyle(Paint.Style.FILL);
return paint;
}
//找到最大时间、最小时间和中间时间显示即可
/ / Find maximum time, minimum time and mid-time displays sufficient
? ? private void drawXPaint(Canvas canvas) {
if(apiResult.ext.xlist.size()>=6){
String firstX=apiResult.ext.xlist.get(0);
String secondX=apiResult.ext.xlist.get(1);
String thirdX=apiResult.ext.xlist.get(2);
String forthX=apiResult.ext.xlist.get(3);
String fifthX=apiResult.ext.xlist.get(4);
String sixX=apiResult.ext.xlist.get(5);
//x轴文字的高度
Height of //x-axis text
? ? ? ? ? ? halfTextWidth_X=mXYPaint.measureText(firstX)/2;
float hight=mHeight - mPaddingBottom + xBottomTopPadding;
canvas.drawText(firstX,
mPaddingLeft-halfTextWidth_X,
hight+textTopPadding, mXYPaint);
canvas.drawText(secondX,
mPaddingLeft + (mWidth - mPaddingLeft - mPaddingRight) /6-halfTextWidth_X,
hight+textTopPadding, mXYPaint);
canvas.drawText(thirdX,
mPaddingLeft + (mWidth - mPaddingLeft - mPaddingRight) /3f-halfTextWidth_X,
hight+textTopPadding, mXYPaint);
canvas.drawText(forthX,
mPaddingLeft + (mWidth - mPaddingLeft - mPaddingRight) /2-halfTextWidth_X,
hight+textTopPadding, mXYPaint);
canvas.drawText(fifthX,
mPaddingLeft + (mWidth - mPaddingLeft - mPaddingRight)*2 /3-halfTextWidth_X,
hight+textTopPadding, mXYPaint);
canvas.drawText(sixX,
mPaddingLeft + (mWidth - mPaddingLeft - mPaddingRight)*5/6-halfTextWidth_X,
hight+textTopPadding, mXYPaint);
}
}
private void drawYPaint(Canvas canvas) {
//现将最小值、最大值画好
//The minimum, maximum value is now done
//draw min
? ? ? ? if(apiResult.ext.ylist.size()>=4){
String firstY=apiResult.ext.ylist.get(0);
String secondY=apiResult.ext.ylist.get(1);
String thirdY=apiResult.ext.ylist.get(2);
String forthY=apiResult.ext.ylist.get(3);
float txtWigth=mXYPaint.measureText(firstY) ;
float perYWidth=(mHeight - mPaddingBottom - mPaddingTop) /3;
canvas.drawText(AppConfig.formatNum(firstY),
mPaddingLeft - txtWigth- yTextRightPadding,
mHeight - mPaddingBottom, mXYPaint);
//draw max
? ? ? ? ? ? canvas.drawText(AppConfig.formatNum(secondY),
mPaddingLeft - txtWigth- yTextRightPadding,
mPaddingTop+perYWidth*2+getFontHeight(mXYTextSize, mXYPaint) /4, mXYPaint);
canvas.drawText(AppConfig.formatNum(thirdY),
mPaddingLeft - txtWigth- yTextRightPadding,
mPaddingTop+perYWidth+getFontHeight(mXYTextSize, mXYPaint) /4, mXYPaint);
canvas.drawText(AppConfig.formatNum(forthY),
mPaddingLeft - txtWigth- yTextRightPadding,
mPaddingTop+getFontHeight(mXYTextSize, mXYPaint) /4, mXYPaint);
}
}
private void showLongPressView() {
mDrawLongPressPaint=true;
invalidate();
}
private void hiddenLongPressView() {
//实现蚂蚁金服延迟消失十字线
/// Delayed disappearance of ants
? ? ? ? postDelayed(new Runnable() {
@Override
public void run() {
mDrawLongPressPaint=false;
invalidate();
}
},200);
}
// 只需要把画笔颜色置为透明即可
/ / All you need to do is make the brush color transparent.
? ? private void hiddenLoadingPaint() {
mLoadingPaint.setColor(0x00000000);
mDrawLoadingPaint=false;
}
private void showLoadingPaint() {
mLoadingPaint.setColor(getColor(R.color.gray));
mDrawLoadingPaint=true;
}
private int getColor(@ColorResint colorId) {
return getResources().getColor(colorId);
}
private float convertDp2Px(float dpValue) {
final float scale=getContext().getResources().getDisplayMetrics().density;
return (dpValue * scale +0.5f);
}
public float getFontHeight(float fontSize, Paint paint) {
paint.setTextSize(fontSize);
Paint.FontMetrics fm=paint.getFontMetrics();
return (float) (Math.ceil(fm.descent - fm.top) +2);
}
? ? public void setData(ApiResult2, XYEntity> apiResult) {
this.apiResult=apiResult;
if (apiResult==null || apiResult.data.size()==0) {
showLoadingPaint();
invalidate();
}else {
if(apiResult.ext.ylist.size()>=4){
mPaddingLeft=mXYPaint.measureText(apiResult.ext.ylist.get(3))+yTextPadding;
maxY=Float.parseFloat(apiResult.ext.ylist.get(3));
minY=Float.parseFloat(apiResult.ext.ylist.get(0));
}
mPerX=(mWidth - mPaddingLeft - mPaddingRight) / (apiResult.data.size()-1);
mPerY=((mHeight - mPaddingTop - mPaddingBottom) /? (maxY - minY));
pointCount=(apiResult.data.size()-1)/24;
//数据过来,隐藏加载更多
/// Data come over, hide more loads
? ? ? ? ? ? hiddenLoadingPaint();
//刷新界面
// Refresh Interface
? ? ? ? ? ? invalidate();
}
}
}
自定义K_View中代码没做封装提取,理解起来相对容易。具体内容都是一些尺寸计算,看起来有点烧脑,但是静下心来慢慢咀嚼,会发现其实整个实现过程非常简单。在这基础上朋友们可以根据需求随意改动,实现更丰富多彩的效果。
Customizing the code in K_View without an encapsulation is relatively easy to understand. It's a few size calculations, it looks a little cerebral, but slowly chewing, and it turns out that the whole process of realization is very simple. On that basis, friends can change them as they want.
注册有任何问题请添加 微信:MVIP619 拉你进入群
打开微信扫一扫
添加客服
进入交流群
发表评论