IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Android饼状图 -> 正文阅读

[游戏开发]Android饼状图

项目需要做一个android饼状图的效果 因为元素比较多 并且有些元素的百分比为0也需要显示出来,一开始考虑使用MPAndroidCharthttps://github.com/PhilJay/MPAndroidChart,毕竟点赞数量多 但是看了下效果 跟要求差别还是有点大,所以又找了个其他的项目参考PieChartViewhttps://github.com/luweibin3118/PieChartView, 这个项目 发现只能设置int类型的百分比 而且当条目过多的时候 会导致显示的文本覆盖重合之类的 所以改了两个地方

1.将int 类型改为float类型 百分比

2.将百分比显示由标注线下面移动到 content后面

下面贴下代码和效果

?源代码可以去项目里面找? 我只放下修改后的代码

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class MyPieChartView extends View{

    private Paint mPaint;

    private Path mPath, drawLinePath = new Path();

    private PathMeasure mPathMeasure = new PathMeasure();

    private Canvas mCanvas;

    private int width, height;

    private RectF pieRectF, tempRectF;

    private int radius;

    private List<MyPieChartView.ItemType> itemTypeList, leftTypeList, rightTypeList;

    private List<Point> itemPoints;

    private int cell = 0;

    private float innerRadius = 0.0f;

    private float offRadius = 0, offLine;

    private int textAlpha;

    private Point firstPoint;

    private int backGroundColor = 0xffffffff;

    private int itemTextSize = 30, textPadding = 8;

    private int defaultStartAngle = -90;

    private float pieCell;

    private ValueAnimator animator;

    private long animDuration = 1000;

    private Point startPoint = new Point();

    private Point centerPoint = new Point();

    private Point endPoint = new Point();

    private Point tempPoint = new Point();

    public MyPieChartView(Context context) {
        super(context);
        init();
    }

    public MyPieChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
        mPath = new Path();

        pieRectF = new RectF();
        tempRectF = new RectF();

        itemTypeList = new ArrayList<>();
        leftTypeList = new ArrayList<>();
        rightTypeList = new ArrayList<>();
        itemPoints = new ArrayList<>();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startAnim();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (animator != null) {
            animator.cancel();
        }
    }

    private void startAnim() {
        animator = ValueAnimator.ofFloat(0, 360f * 2);
        animator.setDuration(animDuration);
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                if (value < 360f) {
                    offRadius = value;
                    offLine = 0;
                    textAlpha = 0;
                } else if (value >= 360f) {
                    offRadius = 360f;
                    offLine = (value - 360f) / 360f;
                    if (offLine > 0.5f) {
                        textAlpha = (int) (255 * ((offLine - 0.5f) / 0.5f));
                        if (textAlpha > 255) textAlpha = 255;
                    } else {
                        textAlpha = 0;
                    }
                } else if (value == 360f * 2) {
                    offRadius = 360f;
                    offLine = 1.0f;
                    textAlpha = 255;
                }
                postInvalidate();
            }
        });
        animator.start();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.width = w;
        this.height = h;
        radius = Math.min(width, height) / 4;
        pieRectF.set(width / 2 - radius, height / 2 - radius, width / 2 + radius, height / 2 + radius);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        try {
            mCanvas = canvas;
            drawPie();
            if (offRadius == 360f) {
                drawTitle();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void drawTitle() {
        resetPaint();
        float startRadius = defaultStartAngle;
        int count = rightTypeList.size();
        int h;
        if (count > 1) {
            h = (radius * 2) / (count - 1);
        } else {
            h = radius;
        }
        for (int i = 0; i < count; i++) {
            mPath.reset();
            MyPieChartView.ItemType itemType = rightTypeList.get(i);
            double angle = 2 * Math.PI * ((startRadius + itemType.radius / 2) / 360d);
            int x = (int) (width / 2 + radius * Math.cos(angle));
            int y = (int) (height / 2 + radius * Math.sin(angle));
            startPoint.set(x, y);
            centerPoint.set((int) (width / 2 + radius * 1.2f), height / 2 - radius + h * (i));
            endPoint.set((int) (width * 0.98f), centerPoint.y);
            mPath.moveTo(startPoint.x, startPoint.y);
            mPath.lineTo(centerPoint.x, centerPoint.y);
            mPath.lineTo(endPoint.x, endPoint.y);
            resetPaint();
            mPaint.setStrokeWidth(2);
            mPaint.setColor(itemType.color);
            mPaint.setStyle(Paint.Style.STROKE);
            mPathMeasure.setPath(mPath, false);
            drawLinePath.reset();
            mPathMeasure.getSegment(0, mPathMeasure.getLength() * offLine, drawLinePath, true);
            mCanvas.drawPath(drawLinePath, mPaint);
            startRadius += itemType.radius;

            if (textAlpha > 0) {
                mPaint.setTextSize(itemTextSize);
                mPaint.setStyle(Paint.Style.FILL);
                mPaint.setTextAlign(Paint.Align.CENTER);
                mPaint.setAlpha(textAlpha);
                mCanvas.drawText(itemType.type+itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,
                        centerPoint.y - textPadding, mPaint);
                mPaint.setTextSize(itemTextSize * 4 / 5);
//                mCanvas.drawText(itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,
//                        centerPoint.y + (itemTextSize + textPadding) * 4 / 5, mPaint);  //itemType.getPercent()移动到itemType.type后面了
            }
        }

        count = leftTypeList.size();
        if (count > 1) {
            h = (radius * 2) / (count - 1);
        } else {
            h = radius;
        }

        for (int i = 0; i < count; i++) {
            mPath.reset();
            MyPieChartView.ItemType itemType = leftTypeList.get(i);
            double angle = 2 * Math.PI * ((startRadius + itemType.radius / 2) / 360d);
            int x = (int) (width / 2 + radius * Math.cos(angle));
            int y = (int) (height / 2 + radius * Math.sin(angle));
            startPoint.set(x, y);
            centerPoint.set((int) (width / 2 - radius * 1.2f), height / 2 - radius + h * (count - 1 - i));
            endPoint.set((int) (width * 0.02f), centerPoint.y);
            mPath.moveTo(startPoint.x, startPoint.y);
            mPath.lineTo(centerPoint.x, centerPoint.y);
            mPath.lineTo(endPoint.x, endPoint.y);
            resetPaint();
            mPaint.setStrokeWidth(2);
            mPaint.setColor(itemType.color);
            mPaint.setAntiAlias(true);
            mPaint.setDither(true);
            mPaint.setStyle(Paint.Style.STROKE);
            mPathMeasure.setPath(mPath, false);
            drawLinePath.reset();
            mPathMeasure.getSegment(0, mPathMeasure.getLength() * offLine, drawLinePath, true);
            mCanvas.drawPath(drawLinePath, mPaint);
            startRadius += itemType.radius;

            if (textAlpha > 0) {
                mPaint.setTextSize(itemTextSize);
                mPaint.setStyle(Paint.Style.FILL);
                mPaint.setTextAlign(Paint.Align.CENTER);
                mPaint.setAlpha(textAlpha);
                mCanvas.drawText(itemType.type+itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,
                        centerPoint.y - textPadding, mPaint);
                mPaint.setTextSize(itemTextSize * 4 / 5);
//                mCanvas.drawText(itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,
//                        centerPoint.y + (itemTextSize + textPadding) * 4 / 5, mPaint);
            }
        }

        if (textAlpha == 1f) {
            itemTypeList.clear();
            leftTypeList.clear();
            rightTypeList.clear();
            itemPoints.clear();
        }
    }

    private void drawPie() {
        if (mCanvas == null) {
            return;
        }
        mCanvas.drawColor(backGroundColor);
        mPaint.setStyle(Paint.Style.FILL);
        float sum = 0;
        for (MyPieChartView.ItemType itemType : itemTypeList) {
            sum += itemType.widget;
        }
        float a = 360f / sum;
        float startRadius = defaultStartAngle;
        float sumRadius = 0;
        leftTypeList.clear();
        rightTypeList.clear();
        itemPoints.clear();
        for (MyPieChartView.ItemType itemType : itemTypeList) {
            itemType.radius = itemType.widget * a;
            double al = 2 * Math.PI * ((startRadius + 90) / 360d);
            tempPoint.set((int) (width / 2 + radius * Math.sin(al)),
                    (int) (height / 2 - radius * Math.cos(al)));
            if (cell > 0) {
                if (startRadius == defaultStartAngle) {
                    firstPoint = tempPoint;
                }
            }

            double angle = 2 * Math.PI * ((startRadius + itemType.radius / 2) / 360d);
            double sin = -Math.sin(angle);
            double cos = -Math.cos(angle);
            if (cos > 0) {
                leftTypeList.add(itemType);
            } else {
                rightTypeList.add(itemType);
            }
            sumRadius += Math.abs(itemType.radius);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(itemType.color);
            if (pieCell > 0) {
                if (sumRadius <= offRadius) {
                    tempRectF.set(pieRectF.left - (float) (pieCell * cos), pieRectF.top - (float) (pieCell * sin),
                            pieRectF.right - (float) (pieCell * cos), pieRectF.bottom - (float) (pieCell * sin));
                    mCanvas.drawArc(tempRectF, startRadius, itemType.radius, true, mPaint);
                } else {
                    mCanvas.drawArc(tempRectF, startRadius, itemType.radius - (Math.abs(offRadius - sumRadius)), true, mPaint);
                    break;
                }
            } else {
                if (sumRadius <= offRadius) {
                    mCanvas.drawArc(pieRectF, startRadius, itemType.radius, true, mPaint);
                } else {
                    mCanvas.drawArc(pieRectF, startRadius, itemType.radius - (Math.abs(offRadius - sumRadius)), true, mPaint);
                    break;
                }

            }
            startRadius += itemType.radius;
            if (cell > 0 && pieCell == 0) {
                mPaint.setColor(backGroundColor);
                mPaint.setStrokeWidth(cell);
                mCanvas.drawLine(getWidth() / 2, getHeight() / 2, tempPoint.x, tempPoint.y, mPaint);
            }
        }
        if (cell > 0 && firstPoint != null && pieCell == 0) {
            mPaint.setColor(backGroundColor);
            mPaint.setStrokeWidth(cell);
            mCanvas.drawLine(getWidth() / 2, getHeight() / 2, firstPoint.x, firstPoint.y, mPaint);
        }
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(backGroundColor);
        if (innerRadius > 0 && pieCell == 0) {
            mCanvas.drawCircle(width / 2, height / 2, radius * innerRadius, mPaint);
        }
    }

    public void resetPaint() {
        mPaint.reset();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setAlpha(255);
    }

    /**
     * 添加一条分类数据
     *
     * @param itemType
     */
    public void addItemType(MyPieChartView.ItemType itemType) {
        if (itemTypeList != null) {
            itemTypeList.add(itemType);
        }
    }

    /**
     * 设置每条图之间的间歇大小
     *
     * @param cell
     */
    public void setCell(int cell) {
        this.cell = cell;
    }

    /**
     * 设置内部圆的半径比例,eg:0.5f
     *
     * @param innerRadius
     */
    public void setInnerRadius(float innerRadius) {
        if (innerRadius > 1.0f) {
            innerRadius = 1.0f;
        } else if (innerRadius < 0) {
            innerRadius = 0;
        }
        this.innerRadius = innerRadius;
    }

    /**
     * 设置背景颜色
     *
     * @param backGroundColor
     */
    public void setBackGroundColor(int backGroundColor) {
        this.backGroundColor = backGroundColor;
    }

    /**
     * 设置每条字体大小
     *
     * @param itemTextSize
     */
    public void setItemTextSize(int itemTextSize) {
        this.itemTextSize = itemTextSize;
    }

    /**
     * 设置字体距离横线的padding值
     *
     * @param textPadding
     */
    public void setTextPadding(int textPadding) {
        this.textPadding = textPadding;
    }

    /**
     * 设置动画时间
     *
     * @param animDuration
     */
    public void setAnimDuration(long animDuration) {
        this.animDuration = animDuration;
    }

    /**
     * 代替方法{@link #setCell(int)}
     *
     * @param pieCell
     */
    @Deprecated
    public void setPieCell(int pieCell) {
        this.cell = pieCell;
    }

    public static class ItemType {
        private static final DecimalFormat df = new DecimalFormat("0.0%");
        String type;
        float widget;
        int color;
        float radius;

        public ItemType(String type, float widget, int color) {
            this.type = type;
            this.widget = widget;
            this.color = color;
        }

        public String getPercent() {
            return df.format(radius / 360f);
        }
    }
}

布局文件:

   <com.runjiang.cityplatform.widget.MyPieChartView
        android:id="@+id/piechart"
        android:layout_width="match_parent"
        android:layout_height="300dp"/>

使用方法很简单:

pieChartView.addItemType(new PieChartView.ItemType("小米", 13, 0xff8B5A00));

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:35:02  更:2022-04-15 00:36:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:06:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码