自定义view绘制K线图,点击弹出pop及在第一次进入页面时滑屏弹出pop

上一篇中已经实现了用XYMultipleSeriesRenderer绘制K线及弹出pop的功能,但是因为用的第三方jar包,所以一些坐标点的计算非常之麻烦。项目中提出在第一次进入页面时滑屏到当前日期,并且弹出当前日期对应的pop问题,通过api并没有找到解决方法。于是,只有自定义view,通过继承view调用onDraw()方法来绘制。不多说,代码如下:
自定义LineChartView.java
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.TextView;

import com.bonc.businessmanager.activity.R;
import com.bonc.businessmanager.activity.user.UserAcceptToday;

public class LineChartView extends View
{
private Context context = null;
// private ShowChartActivity mSCA = null;
private List<Map<String,String>> mDataMapList = null;
private Map<String, String> mDataMap = null;
private int touchPoint;

private Point pStart = null; // 起始坐标(左上角)
private Point pEnd = null; // 终点坐标(右下角)
private List<PointF> realPointList = null; // 真实坐标点集合
private List<PointF> screenPointList = null;// 屏幕坐标点集合
private float downX = 0f;
private float downY = 0f;
private float upX;
private float upY;
private float offsetX = 0;

private PopupWindow mPopupWindow;
private PopupWindow mPopupWindow1;
private View mPopupView;
private View mPopupView1;
private TextView mPopTxt1;
private TextView mPopTxt2;
private TextView mPopTxt3;
private TextView mPopTxt4;

private int POPWIN_WIDTH ;
private int POPWIN_HEIGHT;
private int POPWIN_WIDTH1 ;
private int POPWIN_HEIGHT1;

/** 轴刻度长度 **/
private final int CHART_SCALE_LEN = 5;
/** 轴文字号 **/
private final int CHART_FONT_SIZE = 16;
/** Y 轴步长 **/
public int CHART_Y_AXIS_STEP = 55;
/** X 轴步长 **/
public int CHART_X_AXIS_STEP = 45;
/** Y 轴等分多少份 **/
private final int CHART_Y_AXIS_MAX = 6;
/** X 轴等分多少份 **/
public int CHART_X_AXIS_MAX = 31;
/** 折线节点半径 **/
private final int CHART_NODE_R = 4;
/** 图表移动监听 **/
private OnMoveListener oml;

public LineChartView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
this.context = context;
// mSCA = new ShowChartActivity();
pStart = new Point(30, 30);
pEnd = new Point(30 + CHART_X_AXIS_STEP * CHART_X_AXIS_MAX,
30 + CHART_Y_AXIS_STEP * CHART_Y_AXIS_MAX);
realPointList = new ArrayList<PointF>();
screenPointList = new ArrayList<PointF>();
initPop();
}

public LineChartView(Context context, List<PointF> listPoint, int x_axis_max)
{
// TODO Auto-generated constructor stub
super(context);
this.context = context;
// mSCA = new ShowChartActivity();
pStart = new Point(30, 30);
CHART_X_AXIS_MAX = x_axis_max;
//这里是为了通过demens.xml设置不同分辨率下不同步长
CHART_X_AXIS_STEP = (int) context.getResources().getDimension(R.dimen.chart_x_axis_step);
CHART_Y_AXIS_STEP = (int) context.getResources().getDimension(R.dimen.chart_y_axis_step);
pEnd = new Point(30 + CHART_X_AXIS_STEP * CHART_X_AXIS_MAX,
30 + CHART_Y_AXIS_STEP * CHART_Y_AXIS_MAX);
realPointList = listPoint;
screenPointList = getScreenPoints(listPoint);
initPop();
}

public void initData(List<Map<String,String>> list)
{
mDataMapList = list;
mDataMap = new HashMap<String, String>();
}

@Override
protected void onDraw(Canvas canvas)
{
// TODO Auto-generated constructor stub
super.onDraw(canvas);//重写onDraw方法

drawBackground(canvas);

drawAxis(canvas);

drawLine(canvas);
}

/**
* 画背景(网格)
* @param canvas
*/
private void drawBackground(Canvas canvas)
{
// System.out.println("-------- drawBackground() --------");

Paint paint_background = new Paint(); // 画笔
paint_background.setAntiAlias(true); // 去锯齿
paint_background.setColor(Color.GRAY); // 颜色

int i = 0;
// 画竖线
for (int x = pStart.x; x < pEnd.x; x += CHART_X_AXIS_STEP)
{
canvas.drawLine(x, pStart.y, x, pEnd.y, paint_background);
// 滚屏后,更新屏幕坐标集合的X 值..此图表目前只支持横向滚屏,所以Y 值不变
if(i < screenPointList.size())
{
screenPointList.get(i).x = x;
i ++;
}
// System.out.println("drawLine(" + x + ", " + pStart.y + ", " + x + ", " + pEnd.y + ")");
}
// 画横线
for (int y = pStart.y; y <= pEnd.y - CHART_Y_AXIS_STEP; y += CHART_Y_AXIS_STEP)
{
canvas.drawLine(pStart.x, y, pEnd.x - CHART_X_AXIS_STEP, y, paint_background);
// System.out.println("drawLine(" + pStart.x + ", " + y + ", " + pEnd.x + ", " + y + ")");
}
}

/**
* 画坐标轴
* @param canvas
*/
private void drawAxis(Canvas canvas)
{
drawYAxis(canvas);
drawXAxis(canvas);
}

/**
* 画Y轴
* @param canvas
*/
private void drawYAxis(Canvas canvas){
Paint paint_axis = new Paint(); // 画笔
paint_axis.setAntiAlias(true); // 去锯齿
paint_axis.setStyle(Paint.Style.STROKE);
paint_axis.setColor(Color.rgb(242, 103, 16)); // 轴颜色

final int SCALE_X = pStart.x - CHART_SCALE_LEN; // Y 轴上刻度坐标的x 值
final String[] AXIS_TEXT_ARRAY = getResources().getStringArray(R.array.axis_text_array);// Y 轴文字,现在是固定的。

//设置Y轴:先画Y轴,再画刻度。
canvas.drawLine(pStart.x, pStart.y, pStart.x, pEnd.y, paint_axis); // Y 轴
for(int y = pStart.y; y <= pEnd.y; y += CHART_Y_AXIS_STEP)
{
canvas.drawLine(pStart.x, y, SCALE_X, y, paint_axis); // Y 轴刻度
}

paint_axis.setColor(Color.rgb(25, 110, 172)); // 文字颜色
paint_axis.setTextSize(CHART_FONT_SIZE); // 文字大小
paint_axis.setTextAlign(Paint.Align.RIGHT); // 对齐方式
//设置Y轴文字
int i = 0;
for(int y = pEnd.y; y >= pStart.y; y -= CHART_Y_AXIS_STEP)
{
canvas.drawText(AXIS_TEXT_ARRAY[i], SCALE_X, y, paint_axis);
i ++;
}
}
/**
* 画X轴
* @param canvas
*/
private void drawXAxis(Canvas canvas){
Paint paint_axis = new Paint(); // 画笔
paint_axis.setAntiAlias(true); // 去锯齿
paint_axis.setStyle(Paint.Style.STROKE);
paint_axis.setColor(Color.rgb(242, 103, 16)); // 轴颜色

final int SCALE_Y = pEnd.y + CHART_SCALE_LEN; // X 轴上刻度坐标的y 值
final int TEXT_Y = pEnd.y + CHART_FONT_SIZE + 5; // X 轴文字坐标的y 值

//设置X轴:先画X轴,再画刻度。
canvas.drawLine(pStart.x, pEnd.y, pEnd.x - CHART_X_AXIS_STEP, pEnd.y, paint_axis);// X 轴
for(int x = pStart.x; x < pEnd.x; x += CHART_X_AXIS_STEP)
{
canvas.drawLine(x, pEnd.y, x, SCALE_Y, paint_axis); // X 轴刻度
}
paint_axis.setColor(Color.rgb(25, 110, 172)); // 文字颜色
paint_axis.setTextSize(CHART_FONT_SIZE); // 文字大小
paint_axis.setTextAlign(Paint.Align.LEFT); // 对齐方式
//设置X轴文字
int j = 1;
for(int x = pStart.x - 5; x < pEnd.x - CHART_X_AXIS_STEP; x += CHART_X_AXIS_STEP)
{
canvas.drawText(String.valueOf(j), x, TEXT_Y, paint_axis);
j ++;
}
}

/**
* 画 K 线
* @param canvas
*/
private void drawLine(Canvas canvas)
{
System.out.println("-------- drawLine() --------");

// int data1[] = { 324225, 144578, 352415, 458125, 268451, 351545, 252145 };
// canvas.drawColor(Color.WHITE);//设置背景颜色

Paint paint_line = new Paint(); // 画笔
paint_line.setStyle(Paint.Style.STROKE);
paint_line.setStrokeWidth(CHART_NODE_R / 2); // 画笔宽度
paint_line.setAntiAlias(true); // 去锯齿
paint_line.setColor(Color.RED); // 颜色

// 画数据 K 线
for(int p = 1; p < screenPointList.size(); p ++)
{
PointF pf1 = screenPointList.get(p - 1);
PointF pf2 = screenPointList.get(p);
canvas.drawLine(pf1.x, pf1.y, pf2.x, pf2.y, paint_line);

}

// 画K 线节点
for(int n = 0; n < screenPointList.size(); n ++)
{
PointF p_node = screenPointList.get(n);
canvas.drawCircle(p_node.x, p_node.y, CHART_NODE_R, paint_line);

// 在节点上绘图片
Bitmap mBitmap = null;
mDataMap = mDataMapList.get(n);
// 根据type,判断节点图片绿or蓝
if("0".equals(mDataMap.get("type").toString()))
{
mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.blue_dot);
}
else
{
mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.green_dot);
}
// - 16 为了使图片中心和节点对齐
canvas.drawBitmap(mBitmap, p_node.x - mBitmap.getWidth() / 2, p_node.y - mBitmap.getHeight() / 2, paint_line);

}
}

/**
* 返回真实节点集合
* @return List<PointF>
*/
public List<PointF> getRealPoints()
{
return this.realPointList;
}

/**
* 返回屏幕节点集合
* @param listReal 真实点集合
* @return List<PointF>
*/
public List<PointF> getScreenPoints(List<PointF> listReal)
{
List<PointF> listScreen = new ArrayList<PointF>();
for(PointF real : listReal)
{
PointF screen = this.toScreenPoint(real);
listScreen.add(screen);
System.out.println("x = " + screen.x + ", y = " + screen.y);
}
return listScreen;
}

/**
* 真实值转换为屏幕坐标值
* @param real_point 节点真实值
* @return PointF
*/
public PointF toScreenPoint(PointF real_point)
{
PointF pf = new PointF(real_point.x, real_point.y);
pf.x = pStart.x + (real_point.x - 1) * CHART_X_AXIS_STEP;
pf.y = pEnd.y - real_point.y * CHART_Y_AXIS_STEP / 10;
return pf;
}

/**
* 真实值转换为 滚屏后的屏幕坐标值
* @param real_point 节点真实值
* @param offset_X 偏移量
* @return PointF
*/
public PointF toScreenPoint(PointF real_point, float offset_X)
{
PointF pf = new PointF(real_point.x, real_point.y);
pf.x = pStart.x + (real_point.x - 1) * CHART_X_AXIS_STEP - offset_X;
pf.y = pEnd.y - real_point.y * CHART_Y_AXIS_STEP / 10;
return pf;
}

/**
* 屏幕坐标换算成图表坐标(真实值)-- 返回浮点坐标
* @param screen_point
* @return PointF
*/
public PointF toRealPoint(PointF screen_point)
{
PointF pf = new PointF(screen_point.x, screen_point.y);
pf.x = (screen_point.x - pStart.x) / CHART_X_AXIS_STEP + 1;
pf.y = (pEnd.y - screen_point.y) / CHART_Y_AXIS_STEP * 10;
return pf;
}

/**
* 屏幕坐标换算成图表坐标(真实值)-- 返回整型坐标
* @param screen_x
* @param screen_y
* @return Point
*/
public Point toRealPoint(float screen_x, float screen_y)
{
PointF pf = new PointF(screen_x, screen_y);
Point p = new Point();
p.x = (int) ((pf.x - pStart.x) / CHART_X_AXIS_STEP + 1);
p.y = (int) ((pEnd.y - pf.y) / CHART_Y_AXIS_STEP * 10);
return p;
}

/**
* 关闭POP 窗口
*/
public void dismissPopupWindow()
{
if (mPopupWindow != null)
{
if (mPopupWindow.isShowing())
{
mPopupWindow.dismiss();
}
mPopupWindow = null;
}
if (mPopupWindow1 != null)
{
if (mPopupWindow1.isShowing())
{
mPopupWindow1.dismiss();
}
mPopupWindow1 = null;
}

}

/**
* 在图表的指定坐标X 处,显示POP 窗口
* @param bi 业务索引值
* @param i 图表X 坐标索引值
* @param isFirst 是否首次载入POP 窗口
*/
public void showPopupWindow(int bi, int i, boolean isFirst)
{
boolean mType = true;
mDataMap = mDataMapList.get(bi);
String bustotal = mDataMap.get("BUSTOTAL").toString();
String busunsuccess = mDataMap.get("BUSUNSUCCESS").toString();
touchPoint = bi;
// 根据type,判断窗口绿or蓝
if("0".equals(mDataMap.get("type").toString()))
{
mType = false;
mPopTxt1.setText("预约" + bustotal + "条");
mPopTxt2.setText(busunsuccess + "条");
}
else
{
mType = true;
mPopTxt4.setText("已办理" + bustotal + "条");
}

// 取屏幕宽、高
int screenWidth = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
int screenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight();
// 取屏幕高,不含标题栏
Rect frame = new Rect();
getWindowVisibleDisplayFrame(frame);
int screenHeight_NoTitle = frame.height();
// 图表原点在窗口中的坐标
int[] loca = new int[2];
this.getLocationInWindow(loca);

Log.v("sn", "loca[0]: " + loca[0] + ", loca[1]: " + loca[1]);
// POP 窗口最终显示坐标
int X_ = (int) screenPointList.get(i).x + loca[0];
int Y_ = 0;
if(isFirst)
{
offsetX = -screenPointList.get(bi).x + i * CHART_X_AXIS_STEP;
// Y_ = (int) screenPointList.get(bi).y + loca[1];
Y_ = (int) screenPointList.get(bi).y + loca[1] + CHART_Y_AXIS_STEP * 5 / 12;
Log.v("sn", "IF---- sY_ = " + Y_);
}
else
{
Y_ = (int) screenPointList.get(i).y + loca[1]- (screenHeight - screenHeight_NoTitle);
Log.v("sn", "ELSE---- screenPointList.get(i).y = " + screenPointList.get(i).y);
}



if (screenWidth - (int) screenPointList.get(i).x < POPWIN_WIDTH)
{
mPopupView.setBackgroundDrawable(getResources().getDrawable(R.drawable.blue_pop_right));
mPopupView.setPadding(0, dip2px(context, 30), dip2px(context, 23), 0);
mPopTxt1.setGravity(Gravity.RIGHT);
mPopTxt2.setGravity(Gravity.RIGHT);
mPopTxt3.setGravity(Gravity.RIGHT);

mPopupView1.setBackgroundDrawable(getResources().getDrawable(R.drawable.green_pop_right));
mPopupView1.setPadding(0, dip2px(context, 30), dip2px(context, 23), 0);
mPopTxt4.setGravity(Gravity.RIGHT);

X_ -= POPWIN_WIDTH;
}
else
{
mPopupView.setBackgroundDrawable(getResources().getDrawable(R.drawable.blue_pop_left));
mPopupView.setPadding(dip2px(context, 23), dip2px(context, 30), 0, 0);
mPopTxt1.setGravity(Gravity.LEFT);
mPopTxt2.setGravity(Gravity.LEFT);
mPopTxt3.setGravity(Gravity.LEFT);

mPopupView1.setBackgroundDrawable(getResources().getDrawable(R.drawable.green_pop_left));
mPopupView1.setPadding(dip2px(context, 20), dip2px(context, 30), 0, 0);
mPopTxt4.setGravity(Gravity.LEFT);
}

mPopupWindow = new PopupWindow(mPopupView, POPWIN_WIDTH, POPWIN_HEIGHT);
mPopupWindow1 = new PopupWindow(mPopupView1, POPWIN_WIDTH1, POPWIN_HEIGHT1);
if(mType)
{
if (mPopupWindow1.isShowing())
{
mPopupWindow1.update(X_, Y_, POPWIN_WIDTH, POPWIN_HEIGHT);
}
else
{
mPopupWindow1.showAtLocation(this, Gravity.NO_GRAVITY, X_, Y_);
}
}
else
{
if (mPopupWindow.isShowing())
{
mPopupWindow.update(X_, Y_, POPWIN_WIDTH, POPWIN_HEIGHT);
}
else
{
mPopupWindow.showAtLocation(this, Gravity.NO_GRAVITY, X_, Y_);
}
}

}

/**
* 初始化POP 窗口
*/
private void initPop()
{
mPopupView = View.inflate(getContext(), R.layout.pop_msg, null);
mPopTxt1 = (TextView) mPopupView.findViewById(R.id.msgText1);
mPopTxt2 = (TextView) mPopupView.findViewById(R.id.msgText2);
mPopTxt3 = (TextView) mPopupView.findViewById(R.id.msgText3);
mPopTxt1.setText(R.string.pop_window_txt1);
mPopTxt2.setText(R.string.pop_window_txt2);
mPopTxt3.setText(R.string.pop_window_txt3);
mPopupView.setOnClickListener(forwardUserAcceptTodayTwoListener);

mPopupView1 = View.inflate(getContext(), R.layout.pop_msg1, null);
mPopTxt4 = (TextView) mPopupView1.findViewById(R.id.msgText4);
mPopTxt4.setText("预约15条");
mPopupView1.setOnClickListener(forwardUserAcceptTodayOneListener);

POPWIN_WIDTH = dip2px(context, 97.2f);
POPWIN_HEIGHT = dip2px(context, 90.6f);
POPWIN_WIDTH1 = dip2px(context, 97.2f);
POPWIN_HEIGHT1 = dip2px(context, 52f);
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
// dismissPopupWindow();

switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
dismissPopupWindow();
downX = event.getX();
downY = event.getY();
Log.v("sn", "downX = " + downX);
Log.v("sn", "downY = " + downY);
break;
case MotionEvent.ACTION_MOVE:
upX = event.getX();
upY = event.getY();
// 屏幕是否位移
offsetX += upX - downX == 0 ? 0 : upX - downX;
// 位移是否超出X 轴原点(是,归0)
offsetX = offsetX > 0 ? 0 : offsetX;
//当滑动到X轴原点处设置监听
if(oml != null){
if(offsetX == 0){
oml.onLeftStop();
}else{
oml.onMove();
}
}
// 位移是否超出X 轴上限(是,置为上限值)
offsetX = offsetX < -CHART_X_AXIS_STEP * (CHART_X_AXIS_MAX - 9)
? -CHART_X_AXIS_STEP * (CHART_X_AXIS_MAX - 9)
: offsetX;
Log.v("sn", "offsetX = " + offsetX);
pStart = new Point(30 + (int)offsetX, 30);
pEnd = new Point(30 + CHART_X_AXIS_STEP * CHART_X_AXIS_MAX + (int)offsetX,
30 + CHART_Y_AXIS_STEP * CHART_Y_AXIS_MAX);
this.invalidate();
downX = upX;
break;
case MotionEvent.ACTION_UP:

for(int n = 0; n < screenPointList.size(); n ++)
{
PointF p_node = screenPointList.get(n);
// * 定义节点点击事件矩阵
Rect rect = new Rect((int)p_node.x - CHART_X_AXIS_STEP / 2, (int)p_node.y - CHART_Y_AXIS_STEP / 2,
(int)p_node.x + CHART_X_AXIS_STEP / 2, (int)p_node.y + CHART_Y_AXIS_STEP / 2);
if(rect.contains((int)downX, (int)downY))
{
Log.v("sn", "Inside rect !!!!!!!!!!!!!!!!!!!!!!!! Node = " + n);
showPopupWindow(n, n, false);
}
else
{
}
}
break;
default:
// this.invalidate();
break;
}
// return super.onTouchEvent(event);
return true;
}

/**
* px 值转换为dip 值
* @param context
* @param pxValue
* @return int
*/
public int px2dip(Context context, float pxValue)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}

/**
* dip 值转换为px 值
* @param context
* @param dipValue
* @return int
*/
public int dip2px(Context context, float dipValue)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}

/**
* 滚动图表至指定X 点处
* @param x
*/
public void jumpTo(int x)
{
pStart = new Point(30 + (int)offsetX - CHART_X_AXIS_STEP * x, 30);
pEnd = new Point(30 + CHART_X_AXIS_STEP * CHART_X_AXIS_MAX + (int)offsetX - CHART_X_AXIS_STEP * x,
30 + CHART_Y_AXIS_STEP * CHART_Y_AXIS_MAX);
this.invalidate();
}

/**
* 监听:每日预受理列表 未成功页
*/
public OnClickListener forwardUserAcceptTodayTwoListener = new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
dismissPopupWindow();
Intent intent = new Intent(context, UserAcceptToday.class);
intent.putExtra("position", 2);
intent.putExtra("todayStr", getTodayStr());

context.startActivity(intent);
// ((Activity) context).finish();

}
};

/**
* 监听:每日预受理列表 成功页
*/
public OnClickListener forwardUserAcceptTodayOneListener = new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
dismissPopupWindow();
Intent intent = new Intent(context, UserAcceptToday.class);
intent.putExtra("position", 1);
intent.putExtra("todayStr", getTodayStr());

context.startActivity(intent);
// ((Activity) context).finish();
}
};

// 返回日期字符串
private String getTodayStr()
{
String touchPointStr = "";
if ((touchPoint + 1) <= 9)
{
touchPointStr = "0"+(touchPoint+1);
}else{
touchPointStr = ""+(touchPoint+1);
}
String todayStr = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()).substring(0, 8)+touchPointStr;
Log.v("sn", "todayStr: " + todayStr);

return todayStr;
}

/**
* 设置移动监听
* @param obml
*/
public void setOnMoveListener(OnMoveListener oml){
this.oml = oml;
}


/**
* 移动监听
* @author
*
*/
public interface OnMoveListener{
/**
* 当滑动到原点位置时回调此方法
*/
public void onLeftStop();
/**
* 移动时回调此方法
*/
public void onMove();
}

}


调用方式:

private void initChartView()
{



for (int x = 0; x < mDataMapList.size(); x++)
{
// 填x,y值
mDataMap = mDataMapList.get(x);
// X轴从1开始,所以x+1
PointF pData = new PointF(x + 1, Float.parseFloat(mDataMap.get("BUSTOTAL")));
mDataListPoint.add(pData);
System.out.println("x = " + (x + 1) + " | y = " + Integer.parseInt(mDataMap.get("BUSTOTAL")));
}

// 生成图表视图
mLCV = new LineChartView(this, mDataListPoint, getCurrentMonthLastDay()); // 假数据+1, 3月份
mLCV.initData(mDataMapList);
// mLCV.setOnTouchListener(lineChartViewOnTouchListener);
mLCV.setId(0);

// 添加至父容器
// mHSV = (MyHorizontalScrollView) findViewById(R.id.scroll_chart);
containerbody = (FrameLayout) findViewById(R.id.container_chart);
containerbody.addView(mLCV, new LayoutParams(mLCV.CHART_X_AXIS_STEP * getCurrentMonthLastDay() + 20,
LayoutParams.WRAP_CONTENT)); // 注意设置宽度
// containerbody.setOnTouchListener(lineChartViewOnTouchListener);

// 第一次载入图表,默认弹出当前日期POP 窗口
// 取当前日期几号
int today = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
// today = 4;
Log.v("sn", "DAY_OF_MONTH is: " + today);
// 判断当前日期,位于图表的第几屏,10个数一屏
if(today > 10 && today <= 20)
{
mLCV.jumpTo(10); // 滚屏,第二屏
mLCV.showPopupWindow(today - 1, today - 1 - 10, true); // 滚屏后,图表起点位置变为滚屏后的坐标X,减去X 才是当前要显示的位置
}
else if(today > 20 && today <= 30)
{
mLCV.jumpTo(20); // 滚屏,第三屏
mLCV.showPopupWindow(today - 1, today - 1 - 20, true);
}
else if(today > 30)
{
mLCV.jumpTo(21); // 滚屏,第四屏。。最大日期31,所以滚到21即可
mLCV.showPopupWindow(today - 1, today - 1 - 21, true);
}
else if(today <= 10)
{
// 第一屏内,不需要滚屏
mLCV.showPopupWindow(today - 1, today - 1, true);
}

mChartTitle.setVisibility(View.VISIBLE);

mLCV.setOnMoveListener(new OnMoveListener() {

@Override
public void onLeftStop() {
if(yView != null){
containerbody.removeView(yView);
}
}

@Override
public void onMove() {

//因为containerbody的第一个子view一定是画图的LineChartView,
//所以取第二个
if(containerbody.getChildAt(1) == null){
containerbody.addView(yView);
}
}
});

yView = new LineChartYAxis(ShowChartActivity.this);
containerbody.addView(yView,new LayoutParams(31,
LayoutParams.WRAP_CONTENT));
}

其中,因为一进入页面就滑动到当前日期,导致Y轴显示不出来,所以讲Y轴的绘制拿出来作为一个单独的view叠加到绘图view以实现Y轴一直存在的目的,当绘图view滑动到最左端原点位置的时候,yView移除掉。
LineChartYAxis.java
package com.bonc.businessmanager.view;

import com.bonc.businessmanager.activity.R;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.view.View;

/**
*
* @author 图表视图的纵坐标
*
*/
public class LineChartYAxis extends View{

private Point pStart = null; // 起始坐标(左上角)
private Point pEnd = null; // 终点坐标(右下角)
/** 轴刻度长度 **/
private final int CHART_SCALE_LEN = 5;
/** Y 轴步长 **/
public int CHART_Y_AXIS_STEP = 55;
/** Y 轴等分多少份 **/
private final int CHART_Y_AXIS_MAX = 6;
/** 轴文字号 **/
private final int CHART_FONT_SIZE = 16;
/** X 轴步长 **/
public int CHART_X_AXIS_STEP = 45;
/** X 轴等分多少份 **/
public int CHART_X_AXIS_MAX = 31;
public LineChartYAxis(Context context) {
super(context);
init(context);
}

private void init(Context context){
pStart = new Point(30, 30);
CHART_X_AXIS_STEP = (int) context.getResources().getDimension(R.dimen.chart_x_axis_step);
CHART_Y_AXIS_STEP = (int) context.getResources().getDimension(R.dimen.chart_y_axis_step);
pEnd = new Point(30 + CHART_X_AXIS_STEP * CHART_X_AXIS_MAX,
30 + CHART_Y_AXIS_STEP * CHART_Y_AXIS_MAX);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);//画布为白色不透明
drawYAxis(canvas);
}

/**
* 画Y轴
* @param canvas
*/
private void drawYAxis(Canvas canvas){
Paint paint_axis = new Paint(); // 画笔
paint_axis.setAntiAlias(true); // 去锯齿
paint_axis.setStyle(Paint.Style.STROKE);
paint_axis.setColor(Color.rgb(242, 103, 16)); // 轴颜色

final int SCALE_X = pStart.x - CHART_SCALE_LEN; // Y 轴上刻度坐标的x 值
final String[] AXIS_TEXT_ARRAY = getResources().getStringArray(R.array.axis_text_array);// Y 轴文字,现在是固定的。

//设置Y轴:先画Y轴,再画刻度。
canvas.drawLine(pStart.x, pStart.y, pStart.x, pEnd.y, paint_axis); // Y 轴
for(int y = pStart.y; y <= pEnd.y; y += CHART_Y_AXIS_STEP)
{
canvas.drawLine(pStart.x, y, SCALE_X, y, paint_axis); // Y 轴刻度
}

paint_axis.setColor(Color.rgb(25, 110, 172)); // 文字颜色
paint_axis.setTextSize(CHART_FONT_SIZE); // 文字大小
paint_axis.setTextAlign(Paint.Align.RIGHT); // 对齐方式
//设置Y轴文字
int i = 0;
for(int y = pEnd.y; y >= pStart.y; y -= CHART_Y_AXIS_STEP)
{
canvas.drawText(AXIS_TEXT_ARRAY[i], SCALE_X, y, paint_axis);
i ++;
}
}

}

截图:
一进入页面时:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值