效果图

漏斗图效果

核心代码

自定义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 mPaths = new ArrayList<>();

private ArrayList mPaints = new ArrayList<>();

private List 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 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);

}

}

自定义数据结构: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 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;

}

}

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#C0C1C2">

android:id="@+id/funnelview"

android:layout_width="300dp"

android:layout_height="200dp"

android:layout_centerInParent="true"

android:background="#ffffff" />

android 漏斗 动画,android 漏斗图相关推荐

  1. Android Animation 动画——translate解析图

    今天来学习一下Animation文件里面translate的fromXDelta/fromYDelta与toXDelta/toYDelta值使用. 现在看一下动画吧: 很简单,就是一个从左向右的动画, ...

  2. android菊花动画,Android仿ios加载时菊花图

    第一步: /** * 显示正在加载动画 * @param context */ public static Dialog showLoadingDialog(Context context){ //创 ...

  3. android 4 动画,[Android]开发App,你得知道这些4——动画

    0.前言 上一篇文章中,我们讲解了Android的触摸事件 有兴趣的可以去看一看 准备工作 在读本文前,你最好有以下准备: (1)安装Android Stuido(以下简称AS) (2)有一定的Jav ...

  4. android 逐字动画,Android实现文本逐字显示View(类似rpg游戏人物对话,文本逐字显示)...

    前面好多篇文章都是Android Studio.源码编译.ndk等相关教程,今天敲一敲代码,不然都生锈了哈_. 来个古装动画美图,缓解大家疲劳的眼睛...(话说有木有人知道这是谁???) Paste_ ...

  5. android 飞机动画,Android实现纸飞机的简单操作

    在项目中,我们要求做一个纸飞机的功能:就是当打开这个界面时,会有4架纸飞机从屏幕左侧飞入,然后到达自己的位置坐上下浮动,同时云彩也不断地从屏幕右侧飘到屏幕左侧.当你点击其中一个纸飞机时,这个纸飞机先向 ...

  6. android rotate 动画,Android 动画使用 scale、alpha、translate、rotate、set

    scale:尺寸伸缩动画 alpha:渐变透明动画 translate:位移动画 rotate:旋转动画 调用动画文件 给View执行动画 动画文件可以存放在res下的anim目录 Android S ...

  7. android菊花动画,Android实现仿iOS菊花加载圈动画效果

    常见的实现方式 切图,做旋转动画 自定义View,绘制效果 gif图 1.切图会增加体积,但相对简单,不过在换肤的场景下,会使用不同颜色,需要准备多张图,不够灵活. 2.由于自定义的好处,不同颜色只需 ...

  8. android jason动画,Android 动画之Lottie动画使用

    Android 动画之Lottie动画使用 一:简介 Lottie是Airbnb开源的一套跨平台的完整解决方案,设计师只需要使用After Effects(简称AE)设计动画之后,使用Lottic提供 ...

  9. android 光晕动画,Android去掉SrollView、GrdiView、RecycleView、ViewPager等可滑动控件滑动到边缘的光晕效果...

    下面以RecycleView为例,其他可滑动控件也是一样的 在XML中设置: android:id="@+id/rv_recycle_view" android:layout_wi ...

最新文章

  1. 【PAT】1009. Product of Polynomials (25)
  2. Linux环境下安装PHP的memced扩展
  3. 如何判断当前UI component是运行在IC还是non-IC环境下
  4. Quartz Scheduler失火指令说明
  5. 【渝粤教育】国家开放大学2018年秋季 0233-21T学前儿童语言教育 参考试题
  6. String、int、Integer互转的常用方法
  7. [PHP] 日期与时间
  8. centos7修改mysql数据存储,Centos7 修改mysql8数据文件存储路径方案
  9. python基础学习笔记第二天 内建方法(s t r)
  10. 写不出满分作文怎么办,GPT-3 来帮你
  11. centos 文件夹网络连接_CentOS的网络配置的命令详解
  12. Windows 8 Directx 开发学习笔记(九)材质定义及混合光照效果实现
  13. 软件设计师考试历年试题汇总
  14. 个人博客或网站快速被搜索引擎收录
  15. github配置SSH keys
  16. uniapp 在线升级(热更新)及java后台
  17. 五种方法输出大写字母A(c语言)
  18. MySQL 中的boolean/bool/tinyint(1)表示布尔类型
  19. 魔兽世界怀旧服务器无限刷怪点,魔兽世界怀旧服50级刷怪地点汇总
  20. 二维隐式查分方程的计算机程序,地下水流动问题数值方法

热门文章

  1. Python-Django毕业设计口袋校园外卖网站论文(程序+LW)
  2. 如何部署LAMP架构
  3. html首页我的待办,需要帮助使HTML 5中的待办事项列表[解决]
  4. Django实战——待办事项清单
  5. ASP.net 生成验证码
  6. Solidworks显示和隐藏工具栏
  7. android iphone 多核,太震撼!苹果A11性能深度揭秘:只身吊打安卓全系无悬念?
  8. word论文常用格式设定技巧【公式对齐、制表符公式编号等】
  9. python中水平制表符_打印格式化与字符串之水平间隔—制表符,,
  10. 微型计算机最早出现于第三代计算机中,计算机应用基础统考试题库