先上张效果图
这种趋势图,线条更圆滑些,个人感觉比那种折线效果要好。
这个界面我是封装了一个view,代码简单,废话不多,直接上代码。
WeatherTempLineView.java
/**
* 天气趋势折线图
*
*/
public class WeatherTempLineView extends View {
// 用于控制曲线精细度,越大越精细
private static final int STEPS = 20;
private Paint mPointPaint;//圆点
private Paint mTextPaint;//文字
private int x[] = new int[5];//五条天气信息
private float radius = 5;//圆的半径
private List<Integer> bottomPointsX;//同一天的最低温度
private List<Integer> bottomPointsY;
private List<Integer> topPointsX;//同一天的最高温度
private List<Integer> topPointsY;
private Path curvePath;
private Paint paint;
private List<WeatherModel> weatherModels;
private int temperUnit = 0;
private int maxTopTem = -100;
private int temspace = 8;
private Typeface typeface ;
public WeatherTempLineView(Context context) {
super(context);
init();
}
public WeatherTempLineView(Context context, AttributeSet attr) {
super(context, attr);
init();
}
private void init() {
typeface = FontUtils.getHelveticalTime(getContext());
bottomPointsX = new ArrayList<Integer>();
topPointsX = new ArrayList<Integer>();
bottomPointsY = new ArrayList<Integer>();
topPointsY = new ArrayList<Integer>();
weatherModels = new ArrayList<WeatherModel>();
curvePath = new Path();
mPointPaint = new Paint();
mPointPaint.setAntiAlias(true);
mPointPaint.setColor(Color.WHITE);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(25F);
mTextPaint.setTextAlign(Align.CENTER);
if (typeface != null) {
mTextPaint.setTypeface(typeface);
}
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
temperUnit = SharedPreferencesUitl.getUserDefaultInteger(Constants.CurrentWeatherTemperatureUnit, 0);
}
public void setPosition(int a, int b, int c, int d, int e) {
x[0] = a;
x[1] = b;
x[2] = c;
x[3] = d;
x[4] = e;
}
public void setWidthHeight(int w, int h) {
x[0] = w / 10;
x[1] = w * 3 / 10;
x[2] = w * 5 / 10;
x[3] = w * 7 / 10;
x[4] = w * 9 / 10;
}
public void setTemperature(List<WeatherModel> weatherModels,LinearLayout linWeather,WeatherTempLineView tempLineView) {
this.bottomPointsX.clear();
this.bottomPointsY.clear();
this.topPointsX.clear();
this.topPointsY.clear();
this.weatherModels.clear();
curvePath.reset();
this.weatherModels = weatherModels;
maxTopTem = -100;
int minTopTem = 1000;
for (int i = 0; i < weatherModels.size(); i++) {
if (maxTopTem < weatherModels.get(i).temp_max) {
maxTopTem = (int) weatherModels.get(i).temp_max;
}
if (minTopTem > weatherModels.get(i).temp_min) {
minTopTem = (int) weatherModels.get(i).temp_min;
}
}
FontMetrics fontMetrics = mTextPaint.getFontMetrics();
float fontHeight = fontMetrics.bottom - fontMetrics.top;
LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams) linWeather.getLayoutParams();
layoutParams2.height = TCommonUtils.dip2px(getContext(), 180) + 100 + (int) fontHeight * 2 + Math.abs((int) (maxTopTem - minTopTem)) * temspace;
linWeather.setLayoutParams(layoutParams2);
LinearLayout.LayoutParams layoutParams3 = (LinearLayout.LayoutParams) tempLineView.getLayoutParams();
layoutParams3.height = 100 + (int) fontHeight * 2 + Math.abs((int) (maxTopTem - minTopTem)) * temspace;
tempLineView.setLayoutParams(layoutParams3);
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float space = 0f;
this.topPointsX.clear();
this.topPointsY.clear();
this.bottomPointsX.clear();
this.bottomPointsX.clear();
curvePath.reset();
FontMetrics fontMetrics = mTextPaint.getFontMetrics();
// 计算文字高度
float fontHeight = fontMetrics.bottom - fontMetrics.top;
int h = 100;
for (int i = 0; i < weatherModels.size(); i++) {
if (weatherModels.get(i).icon != null && !weatherModels.get(i).icon.equals("")) {
if (weatherModels.get(i).temp_max == maxTopTem) {
topPointsX.add(x[i]);
topPointsY.add(h);
canvas.drawText( getTempText(weatherModels.get(i),(int) weatherModels.get(i).temp_max ), x[i], h - fontHeight, mTextPaint);
canvas.drawCircle(x[i], h, radius, mPointPaint);
} else {
int leng = Math.abs((int) (maxTopTem - weatherModels.get(i).temp_max));
space = leng * temspace;
topPointsX.add(x[i]);
topPointsY.add((int) (h + space));
canvas.drawText( getTempText(weatherModels.get(i),(int) weatherModels.get(i).temp_max), x[i], (int) (h + space) - fontHeight, mTextPaint);
canvas.drawCircle(x[i], (int) (h + space), radius, mPointPaint);
}
//for temp_min
int leng = Math.abs((int) (maxTopTem - weatherModels.get(i).temp_min));
space = leng * temspace;
bottomPointsX.add(x[i]);
bottomPointsY.add((int) (h + space));
canvas.drawText(getTempText(weatherModels.get(i),(int) weatherModels.get(i).temp_min), x[i], (int) (h + space) + fontHeight, mTextPaint);
canvas.drawCircle(x[i], (int) (h + space), radius, mPointPaint);
} else {
topPointsX.add(x[i]);
topPointsY.add(h / 2);
canvas.drawCircle(x[i], h / 2, radius, mPointPaint);
bottomPointsX.add(x[i]);
bottomPointsY.add(h / 2);
canvas.drawCircle(x[i], h / 2, radius, mPointPaint);
}
}
drawCurve(canvas, topPointsX, topPointsY);
drawCurve(canvas, bottomPointsX, bottomPointsY);
}
/**
*获取温度
**/
private String getTempText(WeatherModel weatherModel,float temp) {
String tempText = "";
if (temperUnit == 0) {
if (TCommUtil.WTIsSimpleChinese()) {
tempText = (int) temp + "°C";
} else {
tempText = (int) weatherModel.celsiusToFahrenheit(temp) + "°F";
}
} else if (temperUnit == 1) {
tempText = (int) temp + "°C";
} else if (temperUnit == 2) {
tempText = (int) weatherModel.celsiusToFahrenheit(temp) + "°F";
}
return tempText;
}
/**
* 画曲线.
*
* @param canvas
*/
private void drawCurve(Canvas canvas, List<Integer> x, List<Integer> y) {
if (x == null || y == null || x.size() <= 2 || y.size() <= 2) {
return;
}
List<Cubic> calculate_x = calculate(x);
List<Cubic> calculate_y = calculate(y);
curvePath.moveTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
for (int i = 0; i < calculate_x.size(); i++) {
for (int j = 1; j <= STEPS; j++) {
float u = j / (float) STEPS;
curvePath.lineTo(calculate_x.get(i).eval(u), calculate_y.get(i).eval(u));
}
}
canvas.drawPath(curvePath, paint);
}
/**
* 计算曲线.
* 这个是参考的网上的一种写法。
* @param x
* @return
*/
private List<Cubic> calculate(List<Integer> x) {
int n = x.size() - 1;
float[] gamma = new float[n + 1];
float[] delta = new float[n + 1];
float[] D = new float[n + 1];
int i;
gamma[0] = 1.0f / 2.0f;
for (i = 1; i < n; i++) {
gamma[i] = 1 / (4 - gamma[i - 1]);
}
gamma[n] = 1 / (2 - gamma[n - 1]);
delta[0] = 3 * (x.get(1) - x.get(0)) * gamma[0];
for (i = 1; i < n; i++) {
delta[i] = (3 * (x.get(i + 1) - x.get(i - 1)) - delta[i - 1]) * gamma[i];
}
delta[n] = (3 * (x.get(n) - x.get(n - 1)) - delta[n - 1]) * gamma[n];
D[n] = delta[n];
for (i = n - 1; i >= 0; i--) {
D[i] = delta[i] - gamma[i] * D[i + 1];
}
/* now compute the coefficients of the cubics */
List<Cubic> cubics = new LinkedList<Cubic>();
for (i = 0; i < n; i++) {
Cubic c = new Cubic(x.get(i), D[i], 3 * (x.get(i + 1) - x.get(i)) - 2 * D[i] - D[i + 1], 2 * (x.get(i) - x.get(i + 1)) + D[i] + D[i + 1]);
cubics.add(c);
}
return cubics;
}
}