

如果按照两个View去做,就会有这种局限性。相交的点就会被切。所以这儿就从头修改了这个自定义View。
有了上面的需求,那么就开端咱们的设计了。首要为了咱们自定义View的能比较好的通用性,咱们需求把一些可能会变的东西提取出来。这儿仅仅提取一些很常用的特点,其他需求自定义的,可自己加上。直接看代码
<declare-styleable name="NewWeatherChartView">
<!--开端的x坐标-->
<attr name="new_start_point_x" format="dimension"/>
<!--两点之间x坐标的间隔-->
<attr name="new_point_x_margin" format="dimension"/>
<!--显现温度的字体大小-->
<attr name="temperature_text_size" format="dimension"/>
<!--圆点的半径-->
<attr name="point_radius" format="dimension"/>
<!--选中气候项,温度字体的色彩-->
<attr name="select_temperature_text_color" format="reference|color"/>
<!--未选中气候项,温度字体的色彩-->
<attr name="unselect_temperature_text_color" format="reference|color"/>
<!--选中气候项,圆点的色彩-->
<attr name="select_point_color" format="reference|color"/>
<!--未选中气候项,圆点的色彩-->
<attr name="unselect_point_color" format="reference|color"/>
<!--连接线的色彩-->
<attr name="line_color" format="reference|color"/>
<!--连接线的类型,能够是实线,也能够是虚线,默许是虚线。0虚线,1实线-->
<attr name="line_type" format="integer"/>
</declare-styleable>
public class NewWeatherChartView extends View {
private final static String TAG = "NewWeatherChartView";
private List<WeatherInfo> items;//温度的数据源
//都是能够在XML里边装备的特点,现在项目里边都是用的默许装备。
private int mLineColor;
private int mSelectTemperatureColor;
private int mUnSelectTemperatureColor;
private int mSelectPointColor;
private int mUnselectPointColor;
private int mLineType;
private int mTemperatureTextSize;
private int mPointStartX = 0;
private int mPointXMargin = 0;
private int mPointRadius;
private Point[] mHighPoints; //高温的点的坐标
private Point[] mLowPoints; //低温的点的坐标
//这儿是为了便利写代码,多创建了几个画笔,也能够用一个画笔,然后装备不同的特点
private Paint mLinePaint; //用于画线画笔
private Paint mTextPaint; // 用于画小圆点周围的温度文字的画笔
private Paint mCirclePaint;//用来画小圆点的画笔
private Float mMaxTemperature = Float.MIN_VALUE;//最高温度
private Float mMinTemperature = Float.MAX_VALUE;//最低温度
private Path mPath;//连接线的途径
private DecimalFormat mDecimalFormat;
private int mTodayIndex = -1;//用于判断哪一个被选中
private Context mContext;
...
}
以上便是一些初始化的东西了,那么现在就来思考一下,怎样去画这些东西,上面的初始化也说明了,咱们主要是画线,画文字,然后画圆点。那么应该从哪开端呢?首要是从点坐标开端,因为无论是线,还是文字,他们的位置和点都有联系。那么找到点的坐标便是首要的作业。怎样找点的坐标,以及最开端的X坐标是多少。第一个点的X坐标是根据咱们的装备来的,那么第二个点的x坐标呢?,第二个点的x坐标便是第一个点的x坐标加上他们之间的在X方向上间隔,而在x方向上的间隔也是根据特点装备的。所以咱们能够很简单得到一切点的x坐标。那么圆点的y坐标呢?首要咱们看一张图。

咱们的点,应该是均匀分布在剩下高度里边的。
剩下高度 = 控件高度-2*文字的高度。
点的y坐标为
*剩下高度-((当时温度-最低温度)/(最高温度-最低温度)剩下高度)+文字高度
看起来有点杂乱,可是有公式的话,代码会比较简单。接下来就需求看初始化的代码了和计算点坐标的代码了
代码如下:
//首要从两个参数的构造函数里边获取各种装备的值
public NewWeatherChartView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NewWeatherChartView);
mPointStartX = (int) typedArray.getDimension(R.styleable.NewWeatherChartView_new_start_point_x, 0);
mPointXMargin = (int) typedArray.getDimension(R.styleable.NewWeatherChartView_new_point_x_margin, 0);
mTemperatureTextSize = (int) typedArray.getDimension(R.styleable.NewWeatherChartView_temperature_text_size, 20);
mPointRadius = (int) typedArray.getDimension(R.styleable.NewWeatherChartView_point_radius, 8);
mSelectPointColor = typedArray.getColor(R.styleable.NewWeatherChartView_select_point_color, context.getResources().getColor(R.color.weather_select_point_color));
mUnselectPointColor = typedArray.getColor(R.styleable.NewWeatherChartView_unselect_point_color, context.getResources().getColor(R.color.weather_unselect_point_color));
mLineColor = typedArray.getColor(R.styleable.NewWeatherChartView_line_color, context.getResources().getColor(R.color.weather_line_color));
mSelectTemperatureColor = typedArray.getColor(R.styleable.NewWeatherChartView_select_temperature_text_color, context.getResources().getColor(R.color.weather_select_temperature_color));
mUnSelectTemperatureColor = typedArray.getColor(R.styleable.NewWeatherChartView_unselect_temperature_text_color, context.getResources().getColor(R.color.weather_unselect_temperature_color));
mLineType = typedArray.getInt(R.styleable.NewWeatherChartView_line_type, 0);
this.mContext = context;
typedArray.recycle();
}
private void initData() {
//初始化线的画笔
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setStyle(Paint.Style.STROKE);
mLinePaint.setStrokeWidth(2);
mLinePaint.setDither(true);
//装备虚线
if (mLineType == 0) {
DashPathEffect pathEffect = new DashPathEffect(new float[]{10, 5}, 1);
mLinePaint.setPathEffect(pathEffect);
}
mPath = new Path();
//初始化文字的画笔
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(sp2px(mTemperatureTextSize));
mTextPaint.setTextAlign(Paint.Align.CENTER);
// 初始化圆点的画笔
mCirclePaint = new Paint();
mCirclePaint.setStyle(Paint.Style.FILL);
mDecimalFormat = new DecimalFormat("0");
for (int i = 0; i < items.size(); i++) {
float highY = items.get(i).getHigh();
float lowY = items.get(i).getLow();
if (highY > mMaxTemperature) {
mMaxTemperature = highY;
}
if (lowY < mMinTemperature) {
mMinTemperature = lowY;
}
if (DateUtil.fromTodayDate(items.get(i).getDate()) == 0) {
mTodayIndex = i;
}
}
float span = mMaxTemperature - mMinTemperature;
//这种状况是为了避免一切温度都一样的状况
if (span == 0) {
span = 6.0f;
}
mMaxTemperature = mMaxTemperature + span / 6.0f;
mMinTemperature = mMinTemperature - span / 6.0f;
mHighPoints = new Point[items.size()];
mLowPoints = new Point[items.size()];
}
public int sp2px(float spValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, Resources.getSystem().getDisplayMetrics());
}
public int dip2px(float dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, Resources.getSystem().getDisplayMetrics());
}
这些准备作业昨晚之后,咱们就能够去onDraw里边画图了。
protected void onDraw(Canvas canvas) {
Logging.d(TAG, "onDraw: ");
if (items == null) {
return;
}
int pointX = mPointStartX; // 开端的X坐标
int textHeight = sp2px(mTemperatureTextSize);//文字的高度
int remainingHeight = getHeight() - textHeight * 2;//除掉文字后,剩下的高度
// 计算每一个点的X和Y坐标
for (int i = 0; i < items.size(); i++) {
int x = pointX + mPointXMargin * i;
float highTemp = items.get(i).getHigh();
float lowTemp = items.get(i).getLow();
int highY = remainingHeight - (int) (remainingHeight * ((highTemp - mMinTemperature) / (mMaxTemperature - mMinTemperature))) + textHeight;
int lowY = remainingHeight - (int) (remainingHeight * ((lowTemp - mMinTemperature) / (mMaxTemperature - mMinTemperature))) + textHeight;
mHighPoints[i] = new Point(x, highY);
mLowPoints[i] = new Point(x, lowY);
}
// 画线
drawLine(mHighPoints, canvas);
drawLine(mLowPoints, canvas);
for (int i = 0; i < mHighPoints.length; i++) {
// 画文本度数 例如:3
String yHighText = mDecimalFormat.format(items.get(i).getHigh());
String yLowText = mDecimalFormat.format(items.get(i).getLow());
int highDrawY = mHighPoints[i].y - dip2px(mPointRadius + 8);
int lowDrawY = mLowPoints[i].y + dip2px(mPointRadius + 8 + sp2px(mTemperatureTextSize));
if (i == mTodayIndex) {
mTextPaint.setColor(mSelectTemperatureColor);
mCirclePaint.setColor(mSelectPointColor);
} else {
mTextPaint.setColor(mUnSelectTemperatureColor);
mCirclePaint.setColor(mUnselectPointColor);
}
canvas.drawText(yHighText + "", mHighPoints[i].x, highDrawY, mTextPaint);
canvas.drawText(yLowText + "", mLowPoints[i].x, lowDrawY, mTextPaint);
canvas.drawCircle(mHighPoints[i].x, mHighPoints[i].y, mPointRadius, mCirclePaint);
canvas.drawCircle(mLowPoints[i].x, mLowPoints[i].y, mPointRadius, mCirclePaint);
}
}
private void drawLine(Point[] ps, Canvas canvas) {
Point startp;
Point endp;
mPath.reset();
mLinePaint.setAntiAlias(true);
for (int i = 0; i < ps.length - 1; i++) {
startp = ps[i];
endp = ps[i + 1];
mLinePaint.setColor(mLineColor);
canvas.drawLine(startp.x, startp.y, endp.x, endp.y, mLinePaint);
}
}
以上便是一切要害代码了,当然,还有一个赋值的代码
public void setData(List<WeatherInfo> list) {
this.items = list;
initData();
}
来看一下最终的效果图吧。


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。