Android 仿墨迹天气24小时预报

效果目标:

1.现在到未来24小时温度点连成贝塞尔曲线

2.指示器跟随选中每小时空气质量移动

3.合并相同风力与天气icon

4.显示区域的icon在屏幕可视范围内左右居中

5.显示区域的风力等级在屏幕可视范围内左右居中


最终效果:


实现过程:

1.首先绘制贝塞尔曲线

 //绘制温度贝塞尔曲线
    private void drawCurve(Canvas canvas, List<Point> points) {
        Path curvePath = new Path();
        //绘制点的 x,y轴 集合
        points_x.clear();
        points_y.clear();
        //遍历 把points的x,y点添加到集合里
        for (int i = 0; i < points.size(); i++) {
            if (points.get(i) == null) {
                break;
            }
            if (i == points.size() - 1) {
                points_x.add(points.get(i).x);
                points_x.add(points.get(i).x + ITEM_WIDTH);
                points_y.add(points.get(i).y);
            } else {
                points_x.add(points.get(i).x);
            }
            points_y.add(points.get(i).y);
        }
        //把点转换 实现圆润的效果
        List<Cubic> calculate_x = calculate(points_x);
        List<Cubic> calculate_y = calculate(points_y);
        //从 x,y的0点绘制
        curvePath.moveTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
        //循环绘制  STEPS越大 绘制的点越密
        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, curveLinePaint);
    }

点转换的方法

 /**
     * 计算 贝塞尔曲线的 点
     *
     * @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;
    }

 然后绘制曲线到底部的背景

/**
     * 绘制 曲线下背景和分割线
     * <p>
     * 1. 先把曲线找到 然后画曲线到右下 右下画左下 左下到 曲线0点
     * 2.闭合1画的路径 设置渐变
     * 3.把记录需要画分割线的下标遍历绘制
     */
    private void onDrawLineBg(Canvas canvas, List<Point> points) {
        //背景的path
        Path curvePath = new Path();
        //分割线的patn
        Path linePath = new Path();
        points_x.clear();
        points_y.clear();
        for (int i = 0; i < points.size(); i++) {
            if (points.get(i) == null) {
                break;
            }
            if (i == points.size() - 1) {
                points_x.add(points.get(i).x);
                points_x.add(points.get(i).x + ITEM_WIDTH);
                points_y.add(points.get(i).y);
            } else {
                points_x.add(points.get(i).x);
            }
            points_y.add(points.get(i).y);
        }
        List<Cubic> calculate_x = calculate(points_x);
        List<Cubic> calculate_y = calculate(points_y);
        //从 0 点开始画
        curvePath.moveTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
        linePath.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));
                linePath.lineTo(calculate_x.get(i).eval(u), calculate_y.get(i)
                        .eval(u));
                dashLinePaint.setShader(new LinearGradient(calculate_x.get(i).eval(u), calculate_y.get(i)
                        .eval(u), calculate_x.get(i).eval(u), (mHeight - bottomTextHeight - DisplayUtil.dip2px(getContext(), 20)), getResources().getColor(R.color.color_9945A0FD), getResources().getColor(R.color.color_00E0EFFF), Shader.TileMode.MIRROR));

            }
            //循环 需不需要画分割线eval(1) 是最大点 eval(0)是最小点
            for (Integer postion : postions) {
                if (postion == i && i != ITEM_SIZE - 1) {
                    linePath.lineTo(calculate_x.get(i).eval(1), (mHeight - bottomTextHeight - DisplayUtil.dip2px(getContext(), 20)));
                    linePath.lineTo(calculate_x.get(i).eval(1), calculate_y.get(i).eval(1));
                }
            }


//            curvePath.lineTo(calculate_x.get(i).eval(0), calculate_y.get(i).eval(0));
        }
        //连接所有点
        curvePath.lineTo(calculate_x.get(calculate_x.size() - 1).eval(1), (mHeight - bottomTextHeight - DisplayUtil.dip2px(getContext(), 20)));
        curvePath.lineTo(calculate_x.get(0).eval(0), (mHeight - bottomTextHeight - DisplayUtil.dip2px(getContext(), 20)));
        curvePath.lineTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
        //闭合路径
        curvePath.close();
  
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值