自定义控件篇:
自定义折线图
前言:自定义控件永远都是客户端开发的一个必须攻破的难题
首先得了解需要实现的样式,确定有没有可继承的控件类,若没有就直接继承View。
View也有自己的生命周期,先了解下我们常用的几个自定义View方法:
构造方法 - onMeasure - onLayout - onDraw - onTouchEvent - onAnimationStart
在构造方法里进行画图工具和数据的初始化
srceenWidth = Tool.getWidth(context);
srceenHeight = Tool.getHeight(context);
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true); //去锯齿
paint.setStrokeWidth(2);
paint.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest));
paint.setColor(context.getResources().getColor(R.color._7C7F99));
String text = "08-06";
Rect rect = new Rect();
paint.getTextBounds(text,0,text.length(), rect);
textheight = rect.height();
textWidth = rect.width();
int srceenHeightpf = srceenHeight/100;
YPoint = Tool.dpToPx(10);
YLength = srceenHeightpf*PriceShjListKinView.Ypinf -YPoint;//K线高度缩小给上下留白
YPoint = YPoint -(YPoint/2);//上下各一半
YScale = YLength/YScalenum;//Y轴均分
在onMeasure方法里对View的高度和宽度做屏幕适配
setMeasuredDimension(srceenWidth, Tool.getHeight(context)/3);
在onLayout中可以获取到View中的子View进行高宽的动态变更
在onDraw中进行绘图:重点
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.setBackgroundColor(getResources().getColor(R.color.trade_tab));
//添加X轴刻度和文字
drawYklin(canvas);
//添加X轴刻度和文字
drawXklin(canvas);
/*早盘价折线*/
painm = new Paint();
painm.setStyle(Paint.Style.FILL);
painm.setAntiAlias(true); //去锯齿
painm.setStrokeWidth(2);
painm.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest));
painm.setColor(context.getResources().getColor(R.color._DE9724));
if(coordinatecoyp==null){
coordinatecoyp = new ArrayList<>();
}else {
coordinatecoyp.clear();
}
int YMax = YLength - (YScalenum-1) * YScale;
float KinMax = YLength - (YLength-YScale) * Tool.getSHJcalPrice(upPrice,downPrice,upPrice-downPrice);
float C = KinMax - YMax;
if(Mpricelist!=null){
for(int i=0; i<Mpricelist.size(); i++){
if(i!=Mpricelist.size()-1){
float y = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Mpricelist.get(i).getYlin(),downPrice,upPrice-downPrice);
float y1 = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Mpricelist.get(i+1).getYlin(),downPrice,upPrice-downPrice);
canvas.drawLine( i * XScale + textWidth/2 + addXwidth,y- YScale/2- textheight/2,
(i+1) * XScale+ textWidth/2 + addXwidth,y1- YScale/2- textheight/2, painm);
}
for(SHjKinBean sHjKinBean: coordinate){
if(sHjKinBean.getXlin().equals(Mpricelist.get(i).getXlin())&&sHjKinBean.getCoordinateX()==COORDINATEM){
SHjKinBean sHjKinBean1 = new SHjKinBean();
sHjKinBean1.setCoordinateY(YLength - (YLength-XScale) * Tool.getSHJcalPrice(Mpricelist.get(i).getYlin(),downPrice,upPrice-downPrice));
sHjKinBean1.setCoordinateX( i * XScale+ textWidth/2 + addXwidth);
sHjKinBean1.setXlin(Mpricelist.get(i).getXlin());
coordinatecoyp.add(sHjKinBean1);
}
}
}
}
/*午盘价折线*/
paina = new Paint();
paina.setStyle(Paint.Style.FILL);
paina.setAntiAlias(true); //去锯齿
paina.setStrokeWidth(2);
paina.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest));
paina.setColor(context.getResources().getColor(R.color._10A8F6));
if(Apricelist!=null){
for(int i=0; i<Apricelist.size(); i++){
if(i!=Apricelist.size()-1){
float y = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Apricelist.get(i).getYlin(),downPrice,upPrice-downPrice);
float y1 = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Apricelist.get(i+1).getYlin(),downPrice,upPrice-downPrice);
canvas.drawLine( i * XScale + textWidth/2 + addXwidth,y- YScale/2- textheight/2,
(i+1) * XScale + textWidth/2 + addXwidth,y1- YScale/2- textheight/2, paina);
}
for(SHjKinBean sHjKinBean: coordinate){
if(sHjKinBean.getXlin().equals(Apricelist.get(i).getXlin())&&sHjKinBean.getCoordinateX()==COORDINATEA){
SHjKinBean sHjKinBean1 = new SHjKinBean();
sHjKinBean1.setCoordinateY(YLength - (YLength-XScale) * Tool.getSHJcalPrice(Apricelist.get(i).getYlin(),downPrice,upPrice-downPrice));
sHjKinBean1.setCoordinateX( i * XScale+ textWidth/2 + addXwidth);
sHjKinBean1.setXlin(Apricelist.get(i).getXlin());
coordinatecoyp.add(sHjKinBean1);
}
}
}
}
//画点击弹出的详情
if (needPop&&coordinatecoyp.size()>0){
drawPopView(popX,popY,canvas);
}
}
如果数据变更,我们提供一个供数据返回后页面调用的方法进行View的数据变化
public void PirceSetShjKinData(List<SHJBean> shjlist){
this.shjlist = shjlist;
UpteInvaldata();
invalidate();
}
public void UpteInvaldata(){
upPrice = 0;
downPrice = 0;
boolean isfrist= true;
Mpricelist = new ArrayList<>();
Apricelist = new ArrayList<>();
coordinate = new ArrayList<>();//保存同一天价格高的xy轴坐标做
String coordinatedata = "";
for(SHJBean shjBeans:shjlist){
try {
float coordinatepriceM = -9999 , coordinatepriceA = -9999 ;
float coordinateis = COORDINATEM;//默认早盘
String price = shjBeans.getMprice()!=null?shjBeans.getMprice():shjBeans.getAprice();
if(isfrist){//最低值需要拿第一个值
downPrice = Tool.getSHJDouble2(Double.valueOf(price));
isfrist = false;
}
coordinatedata = shjBeans.getData();
Mpricelist.add(new SHjKinBean(Tool.getSHJDouble2(Double.valueOf(shjBeans.getMprice())),shjBeans.getData()));
Apricelist.add(new SHjKinBean(Tool.getSHJDouble2(Double.valueOf(shjBeans.getAprice())),shjBeans.getData()));
upPrice = upPrice>Tool.getSHJDouble2(Double.valueOf(price))?
upPrice:Tool.getSHJDouble2(Double.valueOf(price));//取出最高值
downPrice = downPrice < Tool.getSHJDouble2(Double.valueOf(price))?
downPrice:Tool.getSHJDouble2(Double.valueOf(price));//取出最低值
if(shjBeans.getMprice()!=null){
coordinatepriceM = Tool.getSHJDouble2(Double.valueOf(price));
}else {
coordinatepriceA = Tool.getSHJDouble2(Double.valueOf(price));
}
/*拿出同一天最高价格是午盘还是早盘*/
coordinateis = coordinatepriceM>coordinatepriceA?COORDINATEM:COORDINATEA;
SHjKinBean KinBean = new SHjKinBean();
KinBean.setCoordinateX(coordinateis);
KinBean.setXlin(coordinatedata);
coordinate.add(KinBean);
}catch (Exception e){
e.printStackTrace();
}
}
XLength = srceenWidth-Tool.dpToPx(45);
XScale = (XLength-(int) textWidth/2)/shjlist.size();
if(shjlist.size()<5){
addXwidth = XScale/2;
}else {
addXwidth = 0;
}
YLabel = new String[YScalenum];
float Ypricepf = Tool.getSHJcalPrice(upPrice,downPrice,YScalenum-1);//均分-1
for(int i=0;i<YScalenum;i++){
float Ypriceft = Tool.getSHJDouble2(Ypricepf*i)+downPrice;
DecimalFormat decimalFormat = new DecimalFormat("0.00");
YLabel[i] = decimalFormat.format(Ypriceft);
}
XLabel = new String[shjlist.size()];
for(int i=0;i<XLabel.length;i++){
XLabel[i] = shjlist.get(i).getData();
}
}
更新绘制需要调用invalidate();如果没有在UI线程里进行,则需要postInvalidate();
定义一个变量通知布局点击显示区域
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(MOVENUM==0){
downX = event.getX();
}
MOVENUM++;
break;
case MotionEvent.ACTION_MOVE:
if(needPop){
isMOVE = true;
popX = event.getX();
popY = event.getY();
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if(!needPop&&!isMOVE){
needPop = !needPop;
}else {
float X = downX>event.getX()?downX-event.getX():event.getX()-downX;
if(X<=Tool.dpToPx(15)&&MOVENUM>1){
MOVENUM=0;
needPop = !needPop;
isMOVE = false;
}
}
popX = event.getX();
popY = event.getY();
invalidate();
downX = event.getX();
break;
}
return true;
}
同样,点击后需要通知View调用invalidate进行布局更新
点击后的手指区域处理代码:
float coorx;//最小的点击差比
int popWith = 0;
private void drawPopView(float x,float y,Canvas canvas){
int position=0;//最小的x轴
popWith = Tool.dpToPx(15);
for(int i=0;i<coordinatecoyp.size();i++){
if(i==0){
coorx = coordinatecoyp.get(i).getCoordinateX()>x?coordinatecoyp.get(i).getCoordinateX()-x:x-coordinatecoyp.get(i).getCoordinateX();
}
float coorxcopy = coordinatecoyp.get(i).getCoordinateX()>x?coordinatecoyp.get(i).getCoordinateX()-x:x-coordinatecoyp.get(i).getCoordinateX();
if(coorx>coorxcopy){
position = i;
coorx = coorxcopy;
}
}
x = coordinatecoyp.get(position).getCoordinateX();
Paint paintzb = new Paint();//竖线
paintzb.setStyle(Paint.Style.FILL);
paintzb.setAntiAlias(true); //去锯齿
paintzb.setStrokeWidth(1);
paintzb.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest));
paintzb.setColor(context.getResources().getColor(R.color.text_usually));
float newx;
if(x>XLength){
newx = XLength;
}else {
newx = x;
}
canvas.drawLine(newx, YLength - YScale/2- textheight/2, newx, YLength - Ypoplin * YScale- YScale/2- textheight/2, paintzb);
// y = coordinatecoyp.get(position).getCoordinateY();
Paint painapop = new Paint();
painapop.setStyle(Paint.Style.STROKE);
painapop.setAntiAlias(true); //去锯齿
painapop.setStrokeWidth(2);
painapop.setColor(context.getResources().getColor(R.color.text_usually));
Path path= new Path();
if(y-popWith*4 <10+ YPoint){
/*超出上边框*/
y = (10+YPoint) - (y-popWith*4) +y;
}else if(y>YLength-YScale/2- textheight/2){
/*超出下边框*/
float yend = y - YLength + textheight/2 + YScale/2;
y = y - yend;
}
String text = "交易日 :0101交易时间";
float width = paint.measureText(text);//文本的宽度
if(x+width>XLength){
/*超出右边框*/
path.moveTo(x-popWith,y-popWith*4);
path.lineTo(x-popWith,y);
path.lineTo(x-width,y);
path.lineTo(x-width,y-popWith*4);
path.lineTo(x-popWith,y-popWith*4);
}else {
path.moveTo(x+popWith,y-popWith*4);
path.lineTo(x+popWith,y);
path.lineTo(x+width,y);
path.lineTo(x+width,y-popWith*4);
path.lineTo(x+popWith,y-popWith*4);
}
canvas.drawPath(path, painapop);
painapop.setStyle(Paint.Style.FILL);
painapop.setColor(context.getResources().getColor(R.color.trade_tab));
canvas.drawPath(path, painapop);
String data="- -",pricem="- -",pricea="- -";
for(int i=0;i<Mpricelist.size();i++){
if(Mpricelist.get(i).getXlin().equals(coordinatecoyp.get(position).getXlin())){
data = Mpricelist.get(i).getXlin();
pricem = ""+Mpricelist.get(i).getYlin();
}
}
for(int i=0;i<Apricelist.size();i++){
if(Apricelist.get(i).getXlin().equals(coordinatecoyp.get(position).getXlin())){
data = Apricelist.get(i).getXlin();
pricea = ""+Apricelist.get(i).getYlin();
}
}
int popHeight = (popWith*4)/8;
if(x+width>XLength){
/*超出右边框*/
canvas.drawText("交易日:"+TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd",data),x-width+Tool.dpToPx(10),y-popWith*4+popHeight*2+Tool.dpToPx(5),paint);
canvas.drawText("早盘价:"+ Utils.pricesFormatFloat(pricem),x-width+Tool.dpToPx(10),y-popWith*4+popHeight*4+Tool.dpToPx(5),painm);
canvas.drawText("午盘价:"+Utils.pricesFormatFloat(pricea),x-width+Tool.dpToPx(10),y-popWith*4+popHeight*6+Tool.dpToPx(5),paina);
}else {
canvas.drawText("交易日:"+TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd",data),x+popWith+Tool.dpToPx(10),y-popWith*4+popHeight*2+Tool.dpToPx(5),paint);
canvas.drawText("早盘价:"+Utils.pricesFormatFloat(pricem),x+popWith+Tool.dpToPx(10),y-popWith*4+popHeight*4+Tool.dpToPx(5),painm);
canvas.drawText("午盘价:"+Utils.pricesFormatFloat(pricea),x+popWith+Tool.dpToPx(10),y-popWith*4+popHeight*6+Tool.dpToPx(5),paina);
}
}
整篇代码在下面贴出来
package com.sh.android.EGold.activity.price; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import com.sh.android.EGold.activity.R; import com.sh.android.EGold.activity.main.SHJBean; import com.sh.android.EGold.lib.kline.Tool; import com.sh.android.EGold.util.TimeDateUtil; import com.sh.android.EGold.util.Utils; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; /** * Created by wzheng on 2017/8/30. */ public class ShjKinView extends View{ private int srceenWidth; private int srceenHeight; private Context context; private int YPoint = 0;//上下边距26 上下边留白写定价值与日期 private int XScale = 0; // X刻度长度 private int YScale = 0; // Y刻度长度 private int XLength = 0;//X的总长度 private int YLength = 0;//Y的总长度 private int YScalenum = 7; private String[] YLabel , XLabel; private List<SHJBean> shjlist; private List<SHjKinBean> Mpricelist ; private List<SHjKinBean> Apricelist ; private float downPrice,upPrice; private List<SHjKinBean> coordinate; private List<SHjKinBean> coordinatecoyp; //这样写的好处是coordinate的顺序不用控制,只需要对应xy轴里的coordinateX存储是否早>午判断存储y轴,用Xlin保存时间 //因为早午盘x轴一样,先使用SHjKinBean private float COORDINATEM = -1 ,COORDINATEA = -2; private boolean needPop = false; private float popX,popY;//弹框 private boolean isMOVE = false; private int MOVENUM = 0; private RecyclerView listView; private Paint painm , paina , paint;//红,蓝色,灰色 private float textheight; private float textWidth; private float addXwidth = 0; private int Ypoplin = 0; public ShjKinView(Context context) { this(context, null); } public ShjKinView(Context context, AttributeSet attrs) { super(context, attrs); this.context=context; init(); } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(srceenWidth, Tool.getHeight(context)/3); } private void init(){ srceenWidth = Tool.getWidth(context); srceenHeight = Tool.getHeight(context); // initTypeText(); paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setAntiAlias(true); //去锯齿 paint.setStrokeWidth(2); paint.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest)); paint.setColor(context.getResources().getColor(R.color._7C7F99)); String text = "08-06"; Rect rect = new Rect(); paint.getTextBounds(text,0,text.length(), rect); textheight = rect.height(); textWidth = rect.width(); int srceenHeightpf = srceenHeight/100; YPoint = Tool.dpToPx(10); YLength = srceenHeightpf*PriceShjListKinView.Ypinf -YPoint;//K线高度缩小给上下留白 YPoint = YPoint -(YPoint/2);//上下各一半 YScale = YLength/YScalenum;//Y轴均分 } public void PirceSetShjKinData(List<SHJBean> shjlist){ this.shjlist = shjlist; UpteInvaldata(); invalidate(); postInvalidate(); } public void UpteInvaldata(){ upPrice = 0; downPrice = 0; boolean isfrist= true; Mpricelist = new ArrayList<>(); Apricelist = new ArrayList<>(); coordinate = new ArrayList<>();//保存同一天价格高的xy轴坐标做 String coordinatedata = ""; for(SHJBean shjBeans:shjlist){ try { float coordinatepriceM = -9999 , coordinatepriceA = -9999 ; float coordinateis = COORDINATEM;//默认早盘 String price = shjBeans.getMprice()!=null?shjBeans.getMprice():shjBeans.getAprice(); if(isfrist){//最低值需要拿第一个值 downPrice = Tool.getSHJDouble2(Double.valueOf(price)); isfrist = false; } coordinatedata = shjBeans.getData(); Mpricelist.add(new SHjKinBean(Tool.getSHJDouble2(Double.valueOf(shjBeans.getMprice())),shjBeans.getData())); Apricelist.add(new SHjKinBean(Tool.getSHJDouble2(Double.valueOf(shjBeans.getAprice())),shjBeans.getData())); upPrice = upPrice>Tool.getSHJDouble2(Double.valueOf(price))? upPrice:Tool.getSHJDouble2(Double.valueOf(price));//取出最高值 downPrice = downPrice < Tool.getSHJDouble2(Double.valueOf(price))? downPrice:Tool.getSHJDouble2(Double.valueOf(price));//取出最低值 if(shjBeans.getMprice()!=null){ coordinatepriceM = Tool.getSHJDouble2(Double.valueOf(price)); }else { coordinatepriceA = Tool.getSHJDouble2(Double.valueOf(price)); } /*拿出同一天最高价格是午盘还是早盘*/ coordinateis = coordinatepriceM>coordinatepriceA?COORDINATEM:COORDINATEA; SHjKinBean KinBean = new SHjKinBean(); KinBean.setCoordinateX(coordinateis); KinBean.setXlin(coordinatedata); coordinate.add(KinBean); }catch (Exception e){ e.printStackTrace(); } } XLength = srceenWidth-Tool.dpToPx(45); XScale = (XLength-(int) textWidth/2)/shjlist.size(); if(shjlist.size()<5){ addXwidth = XScale/2; }else { addXwidth = 0; } YLabel = new String[YScalenum]; float Ypricepf = Tool.getSHJcalPrice(upPrice,downPrice,YScalenum-1);//均分-1 for(int i=0;i<YScalenum;i++){ float Ypriceft = Tool.getSHJDouble2(Ypricepf*i)+downPrice; DecimalFormat decimalFormat = new DecimalFormat("0.00"); YLabel[i] = decimalFormat.format(Ypriceft); } XLabel = new String[shjlist.size()]; for(int i=0;i<XLabel.length;i++){ XLabel[i] = shjlist.get(i).getData(); } } float downX = 0; @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: listView.requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: listView.requestDisallowInterceptTouchEvent(false); break; } return super.dispatchTouchEvent(event); } @Override protected void onAnimationStart() { super.onAnimationStart(); } public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if(MOVENUM==0){ downX = event.getX(); } MOVENUM++; break; case MotionEvent.ACTION_MOVE: if(needPop){ isMOVE = true; popX = event.getX(); popY = event.getY(); invalidate(); } break; case MotionEvent.ACTION_UP: if(!needPop&&!isMOVE){ needPop = !needPop; }else { float X = downX>event.getX()?downX-event.getX():event.getX()-downX; if(X<=Tool.dpToPx(15)&&MOVENUM>1){ MOVENUM=0; needPop = !needPop; isMOVE = false; } } popX = event.getX(); popY = event.getY(); invalidate(); downX = event.getX(); break; } return true; } public void setlistview(RecyclerView listview){ listView = listview; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); this.setBackgroundColor(getResources().getColor(R.color.trade_tab)); //添加X轴刻度和文字 drawYklin(canvas); //添加X轴刻度和文字 drawXklin(canvas); /*早盘价折线*/ painm = new Paint(); painm.setStyle(Paint.Style.FILL); painm.setAntiAlias(true); //去锯齿 painm.setStrokeWidth(2); painm.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest)); painm.setColor(context.getResources().getColor(R.color._DE9724)); if(coordinatecoyp==null){ coordinatecoyp = new ArrayList<>(); }else { coordinatecoyp.clear(); } int YMax = YLength - (YScalenum-1) * YScale; float KinMax = YLength - (YLength-YScale) * Tool.getSHJcalPrice(upPrice,downPrice,upPrice-downPrice); float C = KinMax - YMax; if(Mpricelist!=null){ for(int i=0; i<Mpricelist.size(); i++){ if(i!=Mpricelist.size()-1){ float y = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Mpricelist.get(i).getYlin(),downPrice,upPrice-downPrice); float y1 = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Mpricelist.get(i+1).getYlin(),downPrice,upPrice-downPrice); canvas.drawLine( i * XScale + textWidth/2 + addXwidth,y- YScale/2- textheight/2, (i+1) * XScale+ textWidth/2 + addXwidth,y1- YScale/2- textheight/2, painm); } for(SHjKinBean sHjKinBean: coordinate){ if(sHjKinBean.getXlin().equals(Mpricelist.get(i).getXlin())&&sHjKinBean.getCoordinateX()==COORDINATEM){ SHjKinBean sHjKinBean1 = new SHjKinBean(); sHjKinBean1.setCoordinateY(YLength - (YLength-XScale) * Tool.getSHJcalPrice(Mpricelist.get(i).getYlin(),downPrice,upPrice-downPrice)); sHjKinBean1.setCoordinateX( i * XScale+ textWidth/2 + addXwidth); sHjKinBean1.setXlin(Mpricelist.get(i).getXlin()); coordinatecoyp.add(sHjKinBean1); } } } } /*午盘价折线*/ paina = new Paint(); paina.setStyle(Paint.Style.FILL); paina.setAntiAlias(true); //去锯齿 paina.setStrokeWidth(2); paina.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest)); paina.setColor(context.getResources().getColor(R.color._10A8F6)); if(Apricelist!=null){ for(int i=0; i<Apricelist.size(); i++){ if(i!=Apricelist.size()-1){ float y = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Apricelist.get(i).getYlin(),downPrice,upPrice-downPrice); float y1 = YLength - (YLength-YScale+C) * Tool.getSHJcalPrice(Apricelist.get(i+1).getYlin(),downPrice,upPrice-downPrice); canvas.drawLine( i * XScale + textWidth/2 + addXwidth,y- YScale/2- textheight/2, (i+1) * XScale + textWidth/2 + addXwidth,y1- YScale/2- textheight/2, paina); } for(SHjKinBean sHjKinBean: coordinate){ if(sHjKinBean.getXlin().equals(Apricelist.get(i).getXlin())&&sHjKinBean.getCoordinateX()==COORDINATEA){ SHjKinBean sHjKinBean1 = new SHjKinBean(); sHjKinBean1.setCoordinateY(YLength - (YLength-XScale) * Tool.getSHJcalPrice(Apricelist.get(i).getYlin(),downPrice,upPrice-downPrice)); sHjKinBean1.setCoordinateX( i * XScale+ textWidth/2 + addXwidth); sHjKinBean1.setXlin(Apricelist.get(i).getXlin()); coordinatecoyp.add(sHjKinBean1); } } } } //画点击弹出的详情 if (needPop&&coordinatecoyp.size()>0){ drawPopView(popX,popY,canvas); } } float coorx;//最小的点击差比 int popWith = 0; private void drawPopView(float x,float y,Canvas canvas){ int position=0;//最小的x轴 popWith = Tool.dpToPx(15); for(int i=0;i<coordinatecoyp.size();i++){ if(i==0){ coorx = coordinatecoyp.get(i).getCoordinateX()>x?coordinatecoyp.get(i).getCoordinateX()-x:x-coordinatecoyp.get(i).getCoordinateX(); } float coorxcopy = coordinatecoyp.get(i).getCoordinateX()>x?coordinatecoyp.get(i).getCoordinateX()-x:x-coordinatecoyp.get(i).getCoordinateX(); if(coorx>coorxcopy){ position = i; coorx = coorxcopy; } } x = coordinatecoyp.get(position).getCoordinateX(); Paint paintzb = new Paint();//竖线 paintzb.setStyle(Paint.Style.FILL); paintzb.setAntiAlias(true); //去锯齿 paintzb.setStrokeWidth(1); paintzb.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.font_super_smallest)); paintzb.setColor(context.getResources().getColor(R.color.text_usually)); float newx; if(x>XLength){ newx = XLength; }else { newx = x; } canvas.drawLine(newx, YLength - YScale/2- textheight/2, newx, YLength - Ypoplin * YScale- YScale/2- textheight/2, paintzb); // y = coordinatecoyp.get(position).getCoordinateY(); Paint painapop = new Paint(); painapop.setStyle(Paint.Style.STROKE); painapop.setAntiAlias(true); //去锯齿 painapop.setStrokeWidth(2); painapop.setColor(context.getResources().getColor(R.color.text_usually)); Path path= new Path(); if(y-popWith*4 <10+ YPoint){ /*超出上边框*/ y = (10+YPoint) - (y-popWith*4) +y; }else if(y>YLength-YScale/2- textheight/2){ /*超出下边框*/ float yend = y - YLength + textheight/2 + YScale/2; y = y - yend; } String text = "交易日 :0101交易时间"; float width = paint.measureText(text);//文本的宽度 if(x+width>XLength){ /*超出右边框*/ path.moveTo(x-popWith,y-popWith*4); path.lineTo(x-popWith,y); path.lineTo(x-width,y); path.lineTo(x-width,y-popWith*4); path.lineTo(x-popWith,y-popWith*4); }else { path.moveTo(x+popWith,y-popWith*4); path.lineTo(x+popWith,y); path.lineTo(x+width,y); path.lineTo(x+width,y-popWith*4); path.lineTo(x+popWith,y-popWith*4); } canvas.drawPath(path, painapop); painapop.setStyle(Paint.Style.FILL); painapop.setColor(context.getResources().getColor(R.color.trade_tab)); canvas.drawPath(path, painapop); String data="- -",pricem="- -",pricea="- -"; for(int i=0;i<Mpricelist.size();i++){ if(Mpricelist.get(i).getXlin().equals(coordinatecoyp.get(position).getXlin())){ data = Mpricelist.get(i).getXlin(); pricem = ""+Mpricelist.get(i).getYlin(); } } for(int i=0;i<Apricelist.size();i++){ if(Apricelist.get(i).getXlin().equals(coordinatecoyp.get(position).getXlin())){ data = Apricelist.get(i).getXlin(); pricea = ""+Apricelist.get(i).getYlin(); } } int popHeight = (popWith*4)/8; if(x+width>XLength){ /*超出右边框*/ canvas.drawText("交易日:"+TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd",data),x-width+Tool.dpToPx(10),y-popWith*4+popHeight*2+Tool.dpToPx(5),paint); canvas.drawText("早盘价:"+ Utils.pricesFormatFloat(pricem),x-width+Tool.dpToPx(10),y-popWith*4+popHeight*4+Tool.dpToPx(5),painm); canvas.drawText("午盘价:"+Utils.pricesFormatFloat(pricea),x-width+Tool.dpToPx(10),y-popWith*4+popHeight*6+Tool.dpToPx(5),paina); }else { canvas.drawText("交易日:"+TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd",data),x+popWith+Tool.dpToPx(10),y-popWith*4+popHeight*2+Tool.dpToPx(5),paint); canvas.drawText("早盘价:"+Utils.pricesFormatFloat(pricem),x+popWith+Tool.dpToPx(10),y-popWith*4+popHeight*4+Tool.dpToPx(5),painm); canvas.drawText("午盘价:"+Utils.pricesFormatFloat(pricea),x+popWith+Tool.dpToPx(10),y-popWith*4+popHeight*6+Tool.dpToPx(5),paina); } } /** * X轴刻度 Y轴边线 * */ private void drawYklin(Canvas canvas){ if(XLabel==null){ return; } int left,right,centen; if(XLabel.length%2==0){ centen = XLabel.length/2; } else{ centen = (XLabel.length-1)/2; } if(centen%2==0){ left = centen /2; right =centen+centen /2; }else { left = (centen-1) /2; right = centen+(centen-1)/2; } for(int i=0;i < XLabel.length;i++){ if(i==0||i==centen||i==left||i==right){ canvas.drawText(TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd", XLabel[i]), i * XScale + addXwidth, YLength +Tool.dpToPx(10)- YScale/2, paint);//文字 }else { Rect rect = new Rect(); paint.getTextBounds(TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd", XLabel[i]), 0, TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd", XLabel[i]).length(), rect); if(i==XLabel.length-1){ canvas.drawText(TimeDateUtil.changeDateFormat("yyyyMMdd", "MM-dd", XLabel[i]), i * XScale + addXwidth, YLength +Tool.dpToPx(10)- YScale/2, paint);//文字 } } } } /** * Y轴刻度 X轴边线 * */ private void drawXklin(Canvas canvas){ if(YLabel==null){ return; } paint.setStrokeWidth(1); paint.setColor(context.getResources().getColor(R.color._7C7F99)); for(int i=0; i * YScale < YLength; i++) { if(i >= YLength/YScale){ continue; } Ypoplin = i; canvas.drawLine(0, YLength - i * YScale - YScale/2 - textheight/2, XLength, YLength - i * YScale- YScale/2- textheight/2, paint); //刻度 } paint.setStrokeWidth(2); } class SHjKinBean{ public String Xlin; public float Ylin; public float coordinateX; public float coordinateY; SHjKinBean(){ } SHjKinBean(float ylin,String xlin){ Ylin = ylin; Xlin = xlin; } public float getCoordinateX() { return coordinateX; } public void setCoordinateX(float coordinateX) { this.coordinateX = coordinateX; } public float getCoordinateY() { return coordinateY; } public void setCoordinateY(float coordinateY) { this.coordinateY = coordinateY; } public String getXlin() { return Xlin; } public void setXlin(String xlin) { Xlin = xlin; } public float getYlin() { return Ylin; } public void setYlin(float ylin) { Ylin = ylin; } } /*详细信息屏蔽*/ public void gonePop(){ if(needPop){ needPop = !needPop; MOVENUM=0; isMOVE = false; invalidate(); } } }