美文网首页
android 漏斗图

android 漏斗图

作者: benz0516 | 来源:发表于2020-12-23 14:36 被阅读0次

    效果图

    漏斗图效果

    核心代码

    1. 自定义View:FunnelChart
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.RectF;
    import android.util.ArrayMap;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Created by benz on 2020/12/22.
     */
    
    public class FunnelChart extends View {
    
        private static final int SPACE = 3;
        private ArrayList<Path> mPaths = new ArrayList<>();
        private ArrayList<Paint> mPaints = new ArrayList<>();
        private List<FunnelData> mData;
        private OnValueTouchListener mTouchListener;
    
        public FunnelChart(Context context) {
            this(context, null);
        }
    
        public FunnelChart(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public FunnelChart(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public void setTouchListener(OnValueTouchListener touchListener) {
            mTouchListener = touchListener;
        }
    
        public void renderData(List<FunnelData> data) {
            if (data == null || data.isEmpty()) {
                return;
            }
            mData = data;
            mPaints.clear();
            for (int i = 0; i < mData.size(); i++) {
                Paint mPaint = new Paint();
                mPaint.setColor(mData.get(i).color);
                mPaint.setStyle(Paint.Style.FILL);
                mPaint.setDither(true);
                mPaint.setAntiAlias(true);
                mPaints.add(mPaint);
            }
            invalidate();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (mData == null || mData.isEmpty()) {
                Paint p = new Paint();
                p.setColor(Color.parseColor("#ffffff"));
                p.setStyle(Paint.Style.FILL);
                p.setDither(true);
                p.setAntiAlias(true);
                canvas.drawPaint(p);
                canvas.save();
                return;
            }
            mPaths.clear();
            float lastX = 0;
            float lastY = 0;
            float value1 = mData.get(0).value;
            for (int i = 0; i < mData.size(); i++) {
                Path mPath = new Path();
                mPath.moveTo(lastX, lastY);
                mPath.lineTo(lastX + mData.get(i).value * 1f / value1 * getWidth(), lastY);
                if (i < mData.size() - 1) {
                    float value2 = mData.get(i + 1).value;
                    mPath.lineTo(getWidth() / 2f + value2 / value1 * getWidth() / 2f, getHeight() * 1f / mData.size() * (i + 1) - SPACE);
                    mPath.lineTo(getWidth() / 2f - value2 / value1 * getWidth() / 2f, getHeight() * 1f / mData.size() * (i + 1) - SPACE);
                    lastX = getWidth() / 2f - value2 / value1 * getWidth() / 2f;
                } else {
                    mPath.lineTo(getWidth() / 2f, getHeight() * 1f / mData.size() * (i + 1) - SPACE);
                    mPath.lineTo(getWidth() / 2f, getHeight() * 1f / mData.size() * (i + 1) - SPACE);
                    lastX = getWidth() / 2f;
                }
                mPath.close();
                mPaths.add(mPath);
                lastY = getHeight() * 1f / mData.size() * (i + 1) + SPACE;
                canvas.drawPath(mPaths.get(i), mPaints.get(i));
            }
            canvas.save();
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);//默认实现,可以不写
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (mTouchListener != null) {
                float x = event.getX();
                float y = event.getY();
                for (int i = 0; i < mPaths.size(); i++) {
                    Path path = mPaths.get(i);
                    RectF rectF = new RectF();
                    path.computeBounds(rectF, true);
                    if (rectF.contains(x, y)) {
                        mTouchListener.onValueTouch(mData.get(i));
                        break;
                    }
                }
                return true;
            } else {
                return super.onTouchEvent(event);
            }
        }
    
        public interface OnValueTouchListener{
            void onValueTouch(FunnelData funnelData);
        }
    
    }
    
    1. 自定义数据结构:FunnelData
    /**
     * Created by benz on 2020/12/22.
     */
    
    public class FunnelData {
        public float value;
        public int color;
    }
    

    如何使用

    import android.graphics.Color;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    public class MainActivity extends AppCompatActivity {
        FunnelChart funnelView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            funnelView = (FunnelChart) findViewById(R.id.funnelview);
            funnelView.setTouchListener(new FunnelChart.OnValueTouchListener() {
                @Override
                public void onValueTouch(FunnelData funnelData) {
                    Toast.makeText(MainActivity.this, "点击了" + funnelData.value, Toast.LENGTH_SHORT).show();
                }
            });
            List<FunnelData> data = new ArrayList<>();
            int size = 3;
            for (int i = 0; i < size; i++) {
                FunnelData funnelData = new FunnelData();
                funnelData.color = Color.parseColor(getRandColorCode());
                funnelData.value = getRandomNumber(1000 / (i + 1), 800 / (i + 1));
                data.add(funnelData);
            }
            funnelView.renderData(data);
        }
    
        private int getRandomNumber(int max, int min) {
            Random random = new Random();
            return random.nextInt(max) % (max - min + 1) + min;
        }
    
        private String getRandColorCode() {
            String r, g, b;
            Random random = new Random();
            r = Integer.toHexString(random.nextInt(256)).toUpperCase();
            g = Integer.toHexString(random.nextInt(256)).toUpperCase();
            b = Integer.toHexString(random.nextInt(256)).toUpperCase();
            r = r.length() == 1 ? "0" + r : r;
            g = g.length() == 1 ? "0" + g : g;
            b = b.length() == 1 ? "0" + b : b;
            return "#" + r + g + b;
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#C0C1C2">
    
        <FunnelChart
            android:id="@+id/funnelview"
            android:layout_width="300dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"
            android:background="#ffffff" />
    </RelativeLayout>
    
    

    相关文章

      网友评论

          本文标题:android 漏斗图

          本文链接:https://www.haomeiwen.com/subject/amnynktx.html