当前位置:主页 > android教程 > Android自定义View天气预报折线图

Android自定义View实现天气预报折线图

发布:2023-03-08 16:00:02 59


给网友们整理相关的编程文章,网友萧宏博根据主题投稿了本篇教程内容,涉及到Android、View天气预报折线图、Android天气预报折线图、Android、View折线图、Android自定义View天气预报折线图相关内容,已被241网友关注,相关难点技巧可以阅读下方的电子资料。

Android自定义View天气预报折线图

本文实例为大家分享了Android自定义View画天气预报折线图的具体代码,供大家参考,具体内容如下

效果图如下:

刚开始尝试用第三方画曲线的框架来画效果图,后来发现曲线间的阴影当有负数的度数的时候画不出来,而且不需要点击放大、点点可点的效果,用框架显得很臃肿,所以最后用自定义View来画的折线图。自定义画折线图的大致思路:这个图是有多个四边形组成的(4个点连接起来就是一个四边形),两边延伸:添加四个多余的点,将左右的边距设置成负数即可。

代码如下:

public class WeatherChartView extends View {

    /**
     * x轴集合
     */
    private float mXAxis[] ;

    /**
     * 白天y轴集合
     */
    private float mYAxisDay[] ;

    /**
     * 夜间y轴集合
     */
    private float mYAxisNight[] ;

    /**
     * x,y轴集合数
     */
    private int LENGTH ;

    /**
     * 白天温度集合
     */
    private int mTempDay[] ;

    /**
     * 夜间温度集合
     */
    private int mTempNight[] ;

    /**
     * 控件高
     */
    private int mHeight;

    /**
     * 字体大小
     */
    private float mTextSize;

    /**
     * 圓半径
     */
    private float mRadius ;

    /**
     * 圓半径今天
     */
    private float mRadiusToday ;

    /**
     * 文字移动位置距离
     */
    private float mTextSpace ;

    /**
     * 线的大小
     */
    private float mStokeWidth ;

    /**
     * 白天折线颜色
     */
    private int mColorDay = Color.parseColor("#ffffff");

    /**
     * 夜间折线颜色
     */
    private int mColorNight = Color.parseColor("#ffffff");;

    /**
     * 字体颜色
     */
    private int mTextColor = Color.parseColor("#ffffff");;

    /**
     * 屏幕密度
     */
    private float mDensity;

    /**
     * 控件边的空白空间
     */
    private float mSpace;

    @SuppressWarnings("deprecation")
    public WeatherChartView(Context context, AttributeSet attrs) {
        super(context, attrs); 
        mDensity = getResources().getDisplayMetrics().density;
        mRadius = 3 * mDensity;
        mRadiusToday = 3 * mDensity;
        //mSpace = 3 * mDensity;
        mTextSpace = 10 * mDensity;
        mStokeWidth = 2 * mDensity;
        mTextSize = BreakRuleTools.dip2px(context, 12);
    }

    public WeatherChartView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mHeight == 0) {
            // 设置控件高度,x轴集合
            setHeightAndXAxis();
        }
        // 计算y轴集合数值
        computeYAxisValues();
        // 画白天折线图
        drawChart(canvas, mColorDay, mTempDay, mYAxisDay, 0);
        // 画夜间折线图
        drawChart(canvas, mColorNight, mTempNight, mYAxisNight, 1);
    }

    /**
     * 计算y轴集合数值
     */
    private void computeYAxisValues() {
        // 存放白天最低温度
        int minTempDay = mTempDay[0];
        // 存放白天最高温度
        int maxTempDay = mTempDay[0];
        for (int item : mTempDay) {
            if (item < minTempDay) {
                minTempDay = item;
            }
            if (item > maxTempDay) {
                maxTempDay = item;
            }
        }

        // 存放夜间最低温度
        int minTempNight = mTempNight[0];
        // 存放夜间最高温度
        int maxTempNight = mTempNight[0];
        for (int item : mTempNight) {
            if (item < minTempNight) {
                minTempNight = item;
            }
            if (item > maxTempNight) {
                maxTempNight = item;
            }
        }

        // 白天,夜间中的最低温度
        int minTemp = minTempNight < minTempDay ? minTempNight : minTempDay;
        // 白天,夜间中的最高温度
        int maxTemp = maxTempDay > maxTempNight ? maxTempDay : maxTempNight;

        // 份数(白天,夜间综合温差)
        float parts = maxTemp - minTemp;
        // y轴一端到控件一端的距离
        float length = mSpace + mTextSize + mTextSpace + mRadius;
        // y轴高度
        float yAxisHeight = mHeight - length * 2;

        // 当温度都相同时(被除数不能为0)
        if (parts == 0) {
            for (int i = 0; i < LENGTH; i++) {
                mYAxisDay[i] = yAxisHeight / 2 + length;
                mYAxisNight[i] = yAxisHeight / 2 + length;
            }
        } else {
            float partValue = yAxisHeight / parts;
            for (int i = 0; i < LENGTH; i++) {
                mYAxisDay[i] = mHeight - partValue * (mTempDay[i] - minTemp) - length;
                mYAxisNight[i] = mHeight - partValue * (mTempNight[i] - minTemp) - length;
            }
        }
    }

    /**
     * 画折线图
     *
     * @param canvas 画布
     * @param color  画图颜色
     * @param temp   温度集合
     * @param yAxis  y轴集合
     * @param type   折线种类:0,白天;1,夜间
     */
    private void drawChart(Canvas canvas, int color, int temp[], float[] yAxis, int type) {
        color = Color.parseColor("#ffffff");
        // 线画笔
        Paint linePaint = new Paint();
        // 抗锯齿
        linePaint.setAntiAlias(true);
        // 线宽
        linePaint.setStrokeWidth(mStokeWidth);
        linePaint.setColor(color);
        // 空心
        linePaint.setStyle(Paint.Style.STROKE);

        // 点画笔
        Paint pointPaint = new Paint();
        pointPaint.setAntiAlias(true);
        pointPaint.setColor(color);

        // 字体画笔
        Paint textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setColor(mTextColor);
        textPaint.setTextSize(mTextSize);
        // 文字居中
        textPaint.setTextAlign(Paint.Align.CENTER);

        int alpha1 = 102;
        int alpha2 = 255;
        for (int i = 0; i < LENGTH; i++) {
            // 画线
            if (i < LENGTH - 1) {
                // 昨天
                if (i == -1) {
                    linePaint.setAlpha(alpha1);
                    // 设置虚线效果
                    linePaint.setPathEffect(new DashPathEffect(new float[]{2 * mDensity, 2 * mDensity}, 0));
                    // 路径
                    Path path = new Path();
                    // 路径起点
                    path.moveTo(mXAxis[i], yAxis[i]);
                    // 路径连接到
                    path.lineTo(mXAxis[i + 1], yAxis[i + 1]);
                    canvas.drawPath(path, linePaint);
                } else {
                    if(type == 0) {
                        linePaint.setAlpha(76);
                        linePaint.setPathEffect(null);

                        linePaint.setStyle(Paint.Style.FILL);//设置实心
                        Path path = new Path();                     //Path对象
                        path.moveTo(mXAxis[i], mYAxisDay[i]);                           //起始点
                        path.lineTo(mXAxis[i + 1], mYAxisDay[i + 1]);                           //连线到下一点
                        path.lineTo(mXAxis[i + 1], mYAxisNight[i + 1]);                      //连线到下一点
                        path.lineTo(mXAxis[i], mYAxisNight[i]);                      //连线到下一点
                        path.lineTo(mXAxis[i], mYAxisDay[i]);                      //连线到下一点
                        canvas.drawPath(path, linePaint);                   //绘制任意多边形
                    }
                    //canvas.drawLine(mXAxis[i], yAxis[i], mXAxis[i + 1], yAxis[i + 1], linePaint);
                }
            }

            // 画点
            if (i != 1) {
                // 昨天
                if (i == 0 || i == LENGTH - 1) {
                    /*pointPaint.setAlpha(alpha1);
                    canvas.drawCircle(mXAxis[i], yAxis[i], mRadius, pointPaint);*/
                } else {
                    pointPaint.setAlpha(alpha2);
                    canvas.drawCircle(mXAxis[i], yAxis[i], mRadius, pointPaint);
                }
                // 今天
            } else {
                pointPaint.setAlpha(alpha2);
                canvas.drawCircle(mXAxis[i], yAxis[i], mRadiusToday, pointPaint);
            }

            // 画字
            // 昨天
            if (i == 0 || i == LENGTH - 1) {
                /*textPaint.setAlpha(alpha1);
                drawText(canvas, textPaint, i, temp, yAxis, type);*/
            } else {
                textPaint.setAlpha(alpha2);
                drawText(canvas, textPaint, i, temp, yAxis, type);
            }
        }
    }

    /**
     * 绘制文字
     *
     * @param canvas    画布
     * @param textPaint 画笔
     * @param i         索引
     * @param temp      温度集合
     * @param yAxis     y轴集合
     * @param type      折线种类:0,白天;1,夜间
     */
    private void drawText(Canvas canvas, Paint textPaint, int i, int[] temp, float[] yAxis, int type) {
        switch (type) {
            case 0:
                // 显示白天气温
                canvas.drawText(temp[i] + "°", mXAxis[i], yAxis[i] - mRadius - mTextSpace, textPaint);
                break;
            case 1:
                // 显示夜间气温
                canvas.drawText(temp[i] + "°", mXAxis[i], yAxis[i] + mTextSpace + mTextSize, textPaint);
                break;
        }
    }

    /**
     * 设置高度,x轴集合
     */
    private void setHeightAndXAxis() {
        mHeight = getHeight();
        // 控件宽
        int width = getWidth();
        int i = LENGTH - 2;
        // 每一份宽
        float w = width / (i*2);

        for(int j =0;j

布局代码:

代码引用:

// 设置白天温度曲线
mChartView = (WeatherChartView) findViewById(R.id.line_char);
mChartView.setTempDay(highTemp);//highTemp 高温度集合
// 设置夜间温度曲线
mChartView.setTempNight(lowTemp);//lowTemp 低温集合
mChartView.invalidate();

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。


参考资料

相关文章

  • Android中分析Jetpack Compose动画内部的实现原理

    发布:2023-03-04

    这篇文章主要介绍了Android中分析Jetpack Compose动画内部的实现原理,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下


  • Android项目中引入aar包的正确方法介绍

    发布:2023-03-02

    生成aar之后下一步就是如何引用本地的aar文件,下面这篇文章主要给大家介绍了关于Android项目中引入aar包的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下


  • Android开发OkHttp执行流程源码分析

    发布:2023-03-04

    这篇文章主要为大家介绍了Android开发OkHttp执行流程源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Android开发Compose框架使用开篇

    发布:2023-03-05

    这篇文章主要为大家介绍了Android开发Compose框架使用开篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • MPAndroidChart 自定义图表绘制使用实例

    发布:2023-03-05

    这篇文章主要为大家介绍了MPAndroidChart 自定义图表绘制使用实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • Android实现折线图小工具

    发布:2023-03-08

    这篇文章主要为大家详细介绍了Android实现折线图小工具,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下


  • Android虚拟机与类加载机制详情

    发布:2023-03-05

    这篇文章主要介绍了Android虚拟机与类加载机制详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下


  • Android 性能优化实现全量编译提速的黑科技

    发布:2023-03-04

    这篇文章主要为大家介绍了Android 性能优化实现全量编译提速的黑科技,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


网友讨论