实现天气趋势图

先上张效果图

这里写图片描述

这种趋势图,线条更圆滑些,个人感觉比那种折线效果要好。
这个界面我是封装了一个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;
    }
}

猜你喜欢

转载自blog.csdn.net/qin_shi/article/details/71046389