`

Android折线图

阅读更多

CommonChartView.java:

 

package com.cz.hello.widget;

/**
 *@版权所有者 iamwsbear@gmail.com
 */

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.cz.hello.R;
import com.cz.hello.utils.Utils;

public class CommonChartView extends View {

    private int bgColor = Color.rgb(Integer.parseInt("4d", 16),
            Integer.parseInt("af", 16), Integer.parseInt("ea", 16));// 整体的背景色

    private int singleColumnFillColor = Color.rgb(Integer.parseInt("e7", 16),
            Integer.parseInt("e7", 16), Integer.parseInt("e9", 16));// 单数列的背景色

    private int doubleColumnFillColor = Color.rgb(Integer.parseInt("4d", 16),
            Integer.parseInt("af", 16), Integer.parseInt("ea", 16));// 单数行的背景色

    private int fillDownColor = Color.rgb(Integer.parseInt("45", 16),
            Integer.parseInt("64", 16), Integer.parseInt("bf", 16));// 填充下面部分的背景色

    private int xyLineColor = Color.rgb(Integer.parseInt("a9", 16),
            Integer.parseInt("d8", 16), Integer.parseInt("f5", 16));// 表格的线颜色

    private int chartLineColor = Color.WHITE;// 绘制趋势线的颜色

    private int shadowLineColor = Color.rgb(Integer.parseInt("1a", 16),
            Integer.parseInt("49", 16), Integer.parseInt("84", 16));// 趋势线阴影的颜色

    private String yUnit = "℃";// Y轴单位

    private boolean isDrawY = false;// 是否绘制Y轴

    private boolean isDrawX = true;// 是否绘制X轴

    private boolean isDrawInsideX = true;// 是否绘制内部的X轴

    private boolean isDrawInsedeY = false;// 是否绘制内部的Y轴

    private boolean isFillDown = false;// 是否填充点的下面部分

    private boolean isFillUp = false;// 是否填充点的上面部分(暂未实现)

    private boolean isAppendX = true;// X轴是否向左突出一点

    private boolean isDemo = false;// 是否demo测试数据

    private int ScreenX;// view的宽度

    private int ScreenY;// view的高度

    private int numberOfX = 6;// 默认X轴放6个值

    private int numberOfY = 5;// 默认Y轴放5个值(越多显示的值越精细)

    private int paddingTop = 10;// 默认上下左右的padding

    private int paddingLeft = Utils.getScreenW(getContext())/12;// 默认上下左右的padding

    private int paddingRight = Utils.getScreenW(getContext())/12;// 默认上下左右的padding

    private int paddingDown = 50;// 默认上下左右的padding

    private int appendXLength = 10;// 向左X轴突出的长度

    private float maxNumber = 0;// Y轴最大值

    private List<List<Float>> pointList;// 传入的数据

    private List<Integer> bitmapList;// 传入的颜色值

    private List<Integer> lineColorList;

    private List<String> titleXList;// 传入的X轴标题

    private List<String> titleYList;// 计算得出的Y轴标题

    public CommonChartView(Context context) {
        super(context);
        demo();

    }

    public CommonChartView(Context context, AttributeSet attr) {
        super(context, attr);
        demo();
    }
    
    private void demo() {
        if (!isDemo) {
            return;
        }
        pointList = new ArrayList<List<Float>>();
        titleXList = new ArrayList<String>();
		lineColorList = new ArrayList<Integer>();
        lineColorList.add(Color.WHITE);
        lineColorList.add(Color.GREEN);
        lineColorList.add(Color.YELLOW);
        // TODO 测试
        for (int i = 0; i < 3; i++) {
            List<Float> pointInList = new ArrayList<Float>();
            for (int j = 0; j < 6; j++) {
                Random r = new Random();
                Float z = r.nextFloat()*100;
                pointInList.add(z);
                titleXList.add("12." + (i + 1) + "1");
            }
            pointList.add(pointInList);
        }
    }

    /**
     * 计算得出View的宽高
     * 
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int measuredHeight = measureHeight(heightMeasureSpec);

        int measuredWidth = measureWidth(widthMeasureSpec);

        setMeasuredDimension(measuredWidth, measuredHeight);

        ScreenX = measuredWidth;

        ScreenY = measuredHeight;

    }

    private int measureHeight(int measureSpec) {

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        int result = 300;
        if (specMode == MeasureSpec.AT_MOST) {

            result = specSize;
        }
        else if (specMode == MeasureSpec.EXACTLY) {

            result = specSize;
        }

        return result;
    }

    private int measureWidth(int measureSpec) {
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        int result = 450;
        if (specMode == MeasureSpec.AT_MOST) {
            result = specSize;
        }

        else if (specMode == MeasureSpec.EXACTLY) {

            result = specSize;
        }

        return result;
    }

    /**
     * 绘画View方法
     * 
     * @param canvas
     */
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        maxNumber = 0;
        List<Point> listX = initNumberOfX();// 计算出X轴平均后的坐标
        List<Point> listY = initNumberOfY();// 计算出Y轴平均后的坐标
        canvas.drawColor(bgColor);// 背景色
        fillColor(listX, canvas);// 根据需求,对每一个框做不同的填充颜色

        // 画背景表格
        Paint paint = new Paint();
        paint.setColor(xyLineColor);// //表格线颜色
        if (isDrawX) {
            int appendX = 0;
            if (isAppendX) {
                appendX = appendXLength;
            }
            canvas.drawLine(paddingLeft - appendX, paddingTop + listY.get(0).y, listY.get(0).x
                    + paddingLeft,
                    paddingTop + listY.get(0).y, paint);
        }
        if (isDrawY) {
            canvas.drawLine(listX.get(0).x, paddingTop, listX.get(0).x, listX.get(0).y + paddingTop
                    , paint);
        }
        if (isDrawInsedeY) {// 绘制纵向的
            for (Point point : listX) {
                if (!isDrawX) {
                    isDrawX = !isDrawX;
                    continue;
                }
                canvas.drawLine(point.x, paddingTop, point.x, point.y + paddingTop, paint);
            }
        }
        if (isDrawInsideX) {// 绘制横向的
            for (Point point : listY) {
                if (!isDrawY) {
                    isDrawY = !isDrawY;
                    continue;
                }
                int appendX = 0;
                if (isAppendX) {
                    appendX = appendXLength;
                }
                canvas.drawLine(paddingLeft - appendX, paddingTop + point.y, point.x + paddingLeft,
                        paddingTop + point.y, paint);
            }
        }

        setYTitle(listY, canvas);// 画折线图Y的单位,同时计算出最大的Y轴值

        List<List<Point>> positionList = countListPosition(listX);// 计算像素位置
        drawFill(canvas, positionList);// 填充折线和边框
        drawChart(canvas, positionList);// 画折线
        drawCicle(canvas, positionList);// 画点

        setXTitle(listX, canvas);// 画折线图X的单位

    }

    private void drawFill(Canvas canvas, List<List<Point>> positionList) {
        if (!isFillDown) {
            return;
        }
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(fillDownColor);
        paint.setAlpha(76);
        for (int i = 0; i < positionList.size(); i++) {
            Path path = new Path();
            path.moveTo(paddingLeft, ScreenY - paddingDown);
            for (int j = 0; j < positionList.get(i).size(); j++) {
                path.lineTo(positionList.get(i).get(j).x, positionList.get(i).get(j).y);
            }
            path.lineTo(ScreenX - paddingRight, ScreenY - paddingDown);
            path.close();
            canvas.drawPath(path, paint);
        }
    }

    private void drawCicle(Canvas canvas, List<List<Point>> positionList) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.GREEN);
        // Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
        // R.drawable.comm_chart_point);
        int resouceId;
        for (int i = 0; i < positionList.size(); i++) {
            // canvas.drawCircle(positionList.get(i).x, positionList.get(i).y,
            // 7, paint);

            if (bitmapList != null && bitmapList.get(i) != null) {
                resouceId = bitmapList.get(i);
            } else {
                resouceId = R.drawable.comm_chart_point;
            }
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                    resouceId);
            for (int j = 0; j < positionList.get(i).size(); j++) {
                canvas.drawBitmap(bitmap, positionList.get(i).get(j).x + 0.5f - bitmap.getWidth()
                        / 2,
                        positionList.get(i).get(j).y + 0.5f - bitmap.getHeight() / 2, paint);
            }
        }
    }

    private List<List<Point>> countListPosition(List<Point> listX) {
        List<List<Point>> positionList = new ArrayList<List<Point>>();
        if (pointList == null) {
            pointList = new ArrayList<List<Float>>();
            List<Float> pointInList = new ArrayList<Float>();
            for (int i = 0; i < numberOfX; i++) {
                pointInList.add(0f);
            }
            pointList.add(pointInList);
        }
        for (int i = 0; i < pointList.size(); i++) {
            List<Point> positionInList = new ArrayList<Point>();
            for (int j = 0; j < pointList.get(i).size(); j++) {
                Point point = new Point();
                Float z = pointList.get(i).get(j);
                point.x = listX.get(j).x;
                point.y = listX.get(j).y + paddingTop
                        - (int) ((listX.get(j).y) * (float) z / (float) maxNumber);
                positionInList.add(point);
            }
            positionList.add(positionInList);
        }
        return positionList;
    }

    private void drawChart(Canvas canvas, List<List<Point>> positionList) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(chartLineColor);
        paint.setStrokeWidth(3);// 默认线宽为3,到时候提升到全局变量,用于设置
        Paint shadowPaint = new Paint();
        shadowPaint.setAntiAlias(true);
        shadowPaint.setColor(shadowLineColor);
        shadowPaint.setStrokeWidth(1);// 默认线宽为3,到时候提升到全局变量,用于设置
        shadowPaint.setAlpha(178);
        for (int i = 0; i < positionList.size(); i++) {
            if (lineColorList != null && lineColorList.get(i) != null) {
                paint.setColor(lineColorList.get(i));
            }
            for (int j = 0; j < positionList.get(i).size() - 1; j++) {
                canvas.drawLine(positionList.get(i).get(j).x, positionList.get(i).get(j).y + 2,
                        positionList.get(i).get(j + 1).x, positionList.get(i).get(j + 1).y + 2,
                        shadowPaint);
                canvas.drawLine(positionList.get(i).get(j).x, positionList.get(i).get(j).y,
                        positionList.get(i).get(j + 1).x, positionList.get(i).get(j + 1).y, paint);
            }
        }
    }

    private void fillColor(List<Point> listX, Canvas canvas) {
        Paint paint = new Paint();
        paint.setStyle(Style.FILL);
        for (int i = 0; i < numberOfX - 1; i++) {
            if (i % 2 == 0) {
                paint.setColor(singleColumnFillColor);
                paint.setAlpha(102);
            } else {
                paint.setColor(doubleColumnFillColor);
                paint.setAlpha(255);
            }
            canvas.drawRect(listX.get(i).x, paddingTop, listX.get(i + 1).x, ScreenY - paddingDown,
                    paint);
        }
    }

    private void setYTitle(List<Point> listY, Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        if (pointList == null) {
            titleYList = new ArrayList<String>();
            for (int i = 1; i <= numberOfY; i++) {
                titleYList.add(String.valueOf(100 / i));
            }
        } else {
            for (int i = 0; i < pointList.size(); i++) {
                for (int j = 0; j < pointList.get(i).size(); j++) {

                    if (pointList.get(i).get(j) > maxNumber) {
                        maxNumber = pointList.get(i).get(j);
                    }
                }
            }
            maxNumber = maxNumber + maxNumber / 3;
            titleYList = new ArrayList<String>();
            for (int i = 0; i < numberOfY; i++) {
                titleYList.add(String.valueOf((int) (0 + i * (maxNumber / (numberOfY - 1)))));
            }
        }
        for (int i = 0; i < numberOfY; i++) {
            int appendX = 0;
            if (isAppendX) {
                appendX = appendXLength;
            }
            if (i != 0) {
                canvas.drawText(titleYList.get(i), paddingLeft - appendX - paddingLeft / 3,
                        paddingTop
                                + listY.get(i).y, paint);
            } else {
                canvas.drawText(titleYList.get(i) + yUnit,
                        paddingLeft - appendX - paddingLeft / 3, paddingTop
                                + listY.get(i).y, paint);
            }
        }
    }

    private void setXTitle(List<Point> listX, Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        if (titleXList == null) {
            titleXList = new ArrayList<String>();
            for (int i = 1; i <= numberOfX; i++) {
                titleXList.add("title" + i);
            }
        }
        for (int i = 0; i < numberOfX; i++) {
            canvas.save();
            canvas.rotate(30, listX.get(i).x,
                    listX.get(i).y + paddingTop + paddingDown / 2);
            canvas.drawText(titleXList.get(i), listX.get(i).x-10,
                    listX.get(i).y + paddingTop + paddingDown / 2
                    , paint);
            canvas.restore();
        }
    }

    private List<Point> initNumberOfX() {
        int num = (ScreenX - paddingLeft - paddingRight) / (numberOfX - 1);
        List<Point> list = new ArrayList<Point>();
        for (int i = 0; i < numberOfX; i++) {
            Point point = new Point();
            point.y = ScreenY - paddingDown - paddingTop;
            point.x = paddingLeft + num * i;
            list.add(point);
        }
        return list;
    }

    private List<Point> initNumberOfY() {
        int num = (ScreenY - paddingDown - paddingTop) / (numberOfY - 1);
        List<Point> list = new ArrayList<Point>();
        for (int i = 0; i < numberOfY; i++) {
            Point point = new Point();
            point.x = ScreenX - paddingLeft - paddingRight;
            point.y = ScreenY - paddingDown - paddingTop - num * i;
            list.add(point);
        }
        return list;
    }

    public boolean isDrawY() {
        return isDrawY;
    }

    public void setDrawY(boolean isDrawY) {
        this.isDrawY = isDrawY;
    }

    public boolean isDrawX() {
        return isDrawX;
    }

    public void setDrawX(boolean isDrawX) {
        this.isDrawX = isDrawX;
    }

    public boolean isFillDown() {
        return isFillDown;
    }

    public void setFillDown(boolean isFillDown) {
        this.isFillDown = isFillDown;
    }

    public boolean isFillUp() {
        return isFillUp;
    }

    public void setFillUp(boolean isFillUp) {
        this.isFillUp = isFillUp;
    }

    public int getScreenX() {
        return ScreenX;
    }

    public void setScreenX(int screenX) {
        ScreenX = screenX;
    }

    public int getScreenY() {
        return ScreenY;
    }

    public void setScreenY(int screenY) {
        ScreenY = screenY;
    }

    public int getNumberOfX() {
        return numberOfX;
    }

    public void setNumberOfX(int numberOfX) {
        this.numberOfX = numberOfX;
    }

    public int getNumberOfY() {
        return numberOfY;
    }

    public void setNumberOfY(int numberOfY) {
        this.numberOfY = numberOfY;
    }

    public boolean isDrawInsideX() {
        return isDrawInsideX;
    }

    public void setDrawInsideX(boolean isDrawInsideX) {
        this.isDrawInsideX = isDrawInsideX;
    }

    public boolean isDrawInsedeY() {
        return isDrawInsedeY;
    }

    public void setDrawInsedeY(boolean isDrawInsedeY) {
        this.isDrawInsedeY = isDrawInsedeY;
    }

    public boolean isAppendX() {
        return isAppendX;
    }

    public void setAppendX(boolean isAppendX) {
        this.isAppendX = isAppendX;
    }

    public int getPaddingTop() {
        return paddingTop;
    }

    public void setPaddingTop(int paddingTop) {
        this.paddingTop = paddingTop;
    }

    public int getPaddingLeft() {
        return paddingLeft;
    }

    public void setPaddingLeft(int paddingLeft) {
        this.paddingLeft = paddingLeft;
    }

    public int getPaddingRight() {
        return paddingRight;
    }

    public void setPaddingRight(int paddingRight) {
        this.paddingRight = paddingRight;
    }

    public int getPaddingDown() {
        return paddingDown;
    }

    public void setPaddingDown(int paddingDown) {
        this.paddingDown = paddingDown;
    }

    public int getAppendXLength() {
        return appendXLength;
    }

    public void setAppendXLength(int appendXLength) {
        this.appendXLength = appendXLength;
    }

    public float getMaxNumber() {
        return maxNumber;
    }

    public void setMaxNumber(float maxNumber) {
        this.maxNumber = maxNumber;
    }

    public List<String> getTitleXList() {
        return titleXList;
    }

    public void setTitleXList(List<String> titleXList) {
        this.titleXList = titleXList;
    }

    public List<String> getTitleYList() {
        return titleYList;
    }

    public void setTitleYList(List<String> titleYList) {
        this.titleYList = titleYList;
    }

    public int getBgColor() {
        return bgColor;
    }

    public void setBgColor(int bgColor) {
        this.bgColor = bgColor;
    }

    public int getSingleColumnFillColor() {
        return singleColumnFillColor;
    }

    public void setSingleColumnFillColor(int singleColumnFillColor) {
        this.singleColumnFillColor = singleColumnFillColor;
    }

    public int getDoubleColumnFillColor() {
        return doubleColumnFillColor;
    }

    public void setDoubleColumnFillColor(int doubleColumnFillColor) {
        this.doubleColumnFillColor = doubleColumnFillColor;
    }

    public int getFillDownColor() {
        return fillDownColor;
    }

    public void setFillDownColor(int fillDownColor) {
        this.fillDownColor = fillDownColor;
    }

    public int getXyLineColor() {
        return xyLineColor;
    }

    public void setXyLineColor(int xyLineColor) {
        this.xyLineColor = xyLineColor;
    }

    public int getShadowLineColor() {
        return shadowLineColor;
    }

    public void setShadowLineColor(int shadowLineColor) {
        this.shadowLineColor = shadowLineColor;
    }

    public int getChartLineColor() {
        return chartLineColor;
    }

    public void setChartLineColor(int chartLineColor) {
        this.chartLineColor = chartLineColor;
    }

    public String getyUnit() {
        return yUnit;
    }

    public void setyUnit(String yUnit) {
        this.yUnit = yUnit;
    }

    public List<List<Float>> getPointList() {
        return pointList;
    }

    public void setPointList(List<List<Float>> pointList) {
        this.pointList = pointList;
    }

    public List<Integer> getBitmapList() {
        return bitmapList;
    }

    public void setBitmapList(List<Integer> bitmapList) {
        this.bitmapList = bitmapList;
    }

    public List<Integer> getLineColorList() {
        return lineColorList;
    }

    public void setLineColorList(List<Integer> lineColorList) {
        this.lineColorList = lineColorList;
    }

}

 

 

 

 

 

 

<com.cz.hello.widget.CommonChartView
			    android:id="@+id/temp_view"
			    android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

 

 

原文转自于:http://blog.csdn.net/iamws/article/details/23875089

 

 

  • 大小: 6.3 KB
分享到:
评论

相关推荐

    android 折线图 (柱状图、饼状图)

    在Android中,我们可以使用多种库来绘制折线图,如MPAndroidChart、AChartEngine和AndroidPlot等。这里我们主要讨论AChartEngine库。AChartEngine是一个轻量级且功能丰富的图表库,支持多种图表类型,包括折线图。要...

    Android折线图多条数据实时动态更新,控制折线图上数据的精度

    总结来说,利用MPAndroidChart在Android应用中创建折线图并实时更新多条数据是一项实用的功能。通过精细控制数据精度,可以提供更直观、高效的可视化体验。同时,还可以通过定制图表样式和交互性,提升用户的使用...

    Android折线图,柱状图,仿股票基金走势图

    本资源提供了实现Android折线图和柱状图的功能,适用于创建类似股票基金走势的展示效果。 在Android平台上,我们可以使用多种库来实现这种功能,如MPAndroidChart、AChartEngine等。其中,MPAndroidChart是一个广泛...

    android折线图demo

    "android折线图demo"是一个示例项目,展示了如何在Android应用中实现动态的、可定制的折线图。这个项目主要关注的是使用折线图来表示数据变化,允许开发者根据需要调整横轴和纵轴的刻度线以及圆点的颜色,同时能够...

    使用Achartengine实现Android折线图开发

    Achartengine是一个开源的图表库,适用于Android平台,可以方便地创建各种类型的图表,如折线图、柱状图、饼图等。本篇将详细介绍如何使用Achartengine库在Android项目中实现折线图的开发。 首先,我们需要在项目中...

    android 折线图控件demo

    在Android开发中,折线图是一种常见的数据可视化方式,它能直观地展示数据的变化趋势,尤其适用于统计和分析。本示例"android 折线图控件demo"提供了一个实现折线图功能的实例,可以帮助开发者更好地理解和运用这类...

    Android 折线图(模仿支付宝月账单的折线图)

    本项目"Android 折线图(模仿支付宝月账单的折线图)"旨在实现一个与支付宝月账单类似的折线图表,通过使用Android内置的`Path`类来绘制动态的、具有交互性的图表。 首先,我们要理解`Path`类在Android中的作用。`...

    android折线图

    在Android应用开发中,视觉数据展示是至关重要的,其中折线图是一种常见且直观的数据可视化方式。本知识点将深入探讨如何在Android环境中自定义折线图,并基于提供的`ChartView-master`项目进行分析。 首先,要创建...

    android 折线图demo

    "android 折线图demo"是一个使用GraphView库实现的Android应用程序示例,用于展示如何在Android设备上绘制动态和交互式的折线图。GraphView是一个强大的开源库,它允许开发者轻松地在Android应用中添加各种图表,...

    android 折线图

    在Android开发中,折线图是一种常见的数据可视化方式,它能直观地展示数据的变化趋势,常用于统计分析、性能监控等场景。本篇文章将详细探讨如何在Android中实现折线图的功能。 首先,我们需要了解Android中实现...

    Android 实时动态折线图Linechart

    通过以上步骤,你可以构建一个功能强大的、实时更新的Android折线图,为用户提供直观的数据展示。在实际项目中,还可以根据需求添加更多功能,如数据点的标注、图表动画效果等,进一步提升用户体验。

    android_折线图相关源码

    本资料提供的是一个关于Android折线图的源码实现,包括了布局文件、自定义折线图类、Fragment和Activity的调用方法。以下是对这些内容的详细解释: 1. **自定义折线图类**: 自定义视图是Android开发中的重要技巧...

    Android 折线图(模仿支付宝)

    在Android开发中,创建自定义视图是一种常见的需求,尤其是对于数据可视化,如折线图。"Android 折线图(模仿支付宝)"项目就是这样一个示例,它利用Android内置的Path类来构建一个类似支付宝应用中的折线图表。Path类...

    android实现折线图

    总的来说,实现一个Android折线图涉及到Canvas的基本绘图操作,以及自定义View的使用。通过不断优化和扩展,我们可以构建出功能丰富的数据可视化工具,满足各种需求。记住,良好的设计和用户体验是任何图表应用成功...

    android自定义折线图曲线图

    在Android开发中,自定义视图是实现特定图形或交互效果的重要手段,而自定义折线图和曲线图则是数据可视化中的常见需求。本篇将深入探讨如何在Android环境中实现这两种图表。 首先,我们需要理解折线图和曲线图的...

    android折线图小例子

    首先,我们从标题“android折线图小例子”来看,这可能涉及到一个简单的Android应用,该应用展示了一个折线图的实例。在Android中,可以使用`ondraw()`方法来自定义View来绘制图形,包括折线图。`ondraw()`方法是...

    android 折线图滑动 - 防小米天气24小时预报折线图

    在Android开发中,创建动态且可滑动的折线图是一项常见的需求,特别是在展示数据变化趋势,如天气预报、股票走势等场景。本教程将详细讲解如何实现一个类似小米天气应用中24小时预报的折线图,并实现滑动功能。 ...

    Android自定义折线图,可左右滑动,可点击

    在Android开发中,有时我们需要创建具有特定功能的图表来展示数据,例如自定义的折线图。本知识点将深入探讨如何在Android应用中实现一个可左右滑动且可点击的自定义折线图。 首先,要创建这样一个自定义折线图,你...

Global site tag (gtag.js) - Google Analytics