热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android自定义View实现芝麻分曲线图效果

这篇文章主要介绍了Android自定义View实现芝麻分曲线图效果的相关资料,非常不错具有参考借鉴价值,需要的朋友可以参考下

1.简介

其实这个效果几天之前就写了,但是一直没有更新博客,本来想着把芝麻分雷达图也做好再发博客的,然后今天看到鸿洋的微信公众号有朋友发了芝麻分的雷达图,所以就算了,算是一个互补吧。平时文章也写的比较少,所以可能有点杂乱,有什么需要改进的地方欢迎给出建议,不胜感激。

效果图:

这里写图片描述

2.步骤:

初始化View的属性
初始化画笔
绘制代表最高分和最低分的两根虚线
绘制文字
绘制代表月份的属性
绘制芝麻分折线
绘制代表芝麻分的圆点
绘制选中分数的悬浮文字以及背景
处理点击事件

3.编码:

初始化View属性

/**
* 初始化布局配置
*
* @param context
* @param attrs
*/
private void initConfig(Context context, AttributeSet attrs)
{
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ScoreTrend);
maxScore=a.getInt(R.styleable.ScoreTrend_max_score,700);
minScore=a.getInt(R.styleable.ScoreTrend_min_score,650);
brokenLineColor=a.getColor(R.styleable.ScoreTrend_broken_line_color,brokenLineColor);
a.recycle();
}

初始化画笔:

private void init()
{
brokenPath = new Path();
brokenPaint = new Paint();
brokenPaint.setAntiAlias(true);
brokenPaint.setStyle(Paint.Style.STROKE);
brokenPaint.setStrokeWidth(dipToPx(brokenLineWith));
brokenPaint.setStrokeCap(Paint.Cap.ROUND);
straightPaint = new Paint();
straightPaint.setAntiAlias(true);
straightPaint.setStyle(Paint.Style.STROKE);
straightPaint.setStrokeWidth(brokenLineWith);
straightPaint.setColor((straightLineColor));
straightPaint.setStrokeCap(Paint.Cap.ROUND);
dottedPaint = new Paint();
dottedPaint.setAntiAlias(true);
dottedPaint.setStyle(Paint.Style.STROKE);
dottedPaint.setStrokeWidth(brokenLineWith);
dottedPaint.setColor((straightLineColor));
dottedPaint.setStrokeCap(Paint.Cap.ROUND);
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor((textNormalColor));
textPaint.setTextSize(dipToPx(15));
}

绘制代表最高分和最低分虚线

//绘制虚线
private void drawDottedLine(Canvas canvas, float startX, float startY, float stopX, float stopY)
{
dottedPaint.setPathEffect(new DashPathEffect(new float[]{20, 10}, 4));
dottedPaint.setStrokeWidth(1);
// 实例化路径
Path mPath = new Path();
mPath.reset();
// 定义路径的起点
mPath.moveTo(startX, startY);
mPath.lineTo(stopX, stopY);
canvas.drawPath(mPath, dottedPaint);
}

绘制文本

//绘制文本
private void drawText(Canvas canvas)
{
textPaint.setTextSize(dipToPx(12));
textPaint.setColor(textNormalColor);
canvas.drawText(String.valueOf(maxScore), viewWith * 0.1f - dipToPx(10), viewHeight * 0.15f + textSize * 0.25f, textPaint);
canvas.drawText(String.valueOf(minScore), viewWith * 0.1f - dipToPx(10), viewHeight * 0.4f + textSize * 0.25f, textPaint);
textPaint.setColor(0xff7c7c7c);
float newWith = viewWith - (viewWith * 0.15f) * 2;//分隔线距离最左边和最右边的距离是0.15倍的viewWith
float coordinateX;//分隔线X坐标
textPaint.setTextSize(dipToPx(12));
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(textNormalColor);
textSize = (int) textPaint.getTextSize();
for(int i = 0; i 

绘制代表月份的属性

//绘制月份的直线(包括刻度)
private void drawMonthLine(Canvas canvas)
{
straightPaint.setStrokeWidth(dipToPx(1));
canvas.drawLine(0, viewHeight * 0.7f, viewWith, viewHeight * 0.7f, straightPaint);
float newWith = viewWith - (viewWith * 0.15f) * 2;//分隔线距离最左边和最右边的距离是0.15倍的viewWith
float coordinateX;//分隔线X坐标
for(int i = 0; i 

绘制芝麻分折线

//绘制折线
private void drawBrokenLine(Canvas canvas)
{
brokenPath.reset();
brokenPaint.setColor(brokenLineColor);
brokenPaint.setStyle(Paint.Style.STROKE);
if(score.length == 0)
{
return;
}
Log.v("ScoreTrend", "drawBrokenLine: " + scorePoints.get(0));
brokenPath.moveTo(scorePoints.get(0).x, scorePoints.get(0).y);
for(int i = 0; i 

绘制代表芝麻分的圆点

//绘制折线穿过的点
private void drawPoint(Canvas canvas)
{
if(scorePoints == null)
{
return;
}
brokenPaint.setStrokeWidth(dipToPx(1));
for(int i = 0; i 

绘制选中分数的悬浮文字以及背景

//绘制显示浮动文字的背景
private void drawFloatTextBackground(Canvas canvas, int x, int y)
{
brokenPath.reset();
brokenPaint.setColor(brokenLineColor);
brokenPaint.setStyle(Paint.Style.FILL);
//P1
Point point = new Point(x, y);
brokenPath.moveTo(point.x, point.y);
//P2
point.x = point.x + dipToPx(5);
point.y = point.y - dipToPx(5);
brokenPath.lineTo(point.x, point.y);
//P3
point.x = point.x + dipToPx(12);
brokenPath.lineTo(point.x, point.y);
//P4
point.y = point.y - dipToPx(17);
brokenPath.lineTo(point.x, point.y);
//P5
point.x = point.x - dipToPx(34);
brokenPath.lineTo(point.x, point.y);
//P6
point.y = point.y + dipToPx(17);
brokenPath.lineTo(point.x, point.y);
//P7
point.x = point.x + dipToPx(12);
brokenPath.lineTo(point.x, point.y);
//最后一个点连接到第一个点
brokenPath.lineTo(x, y);
canvas.drawPath(brokenPath, brokenPaint);
}

处理点击事件

@Override
public boolean onTouchEvent(MotionEvent event)
{
this.getParent().requestDisallowInterceptTouchEvent(true);//一旦底层View收到touch的action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
onActionUpEvent(event);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_CANCEL:
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return true;
}
private void onActionUpEvent(MotionEvent event)
{
boolean isValidTouch = validateTouch(event.getX(), event.getY());
if(isValidTouch)
{
invalidate();
}
}
//是否是有效的触摸范围
private boolean validateTouch(float x, float y)
{
//曲线触摸区域
for(int i = 0; i  (scorePoints.get(i).x - dipToPx(8) * 2) && x <(scorePoints.get(i).x + dipToPx(8) * 2))
{
if(y > (scorePoints.get(i).y - dipToPx(8) * 2) && y <(scorePoints.get(i).y + dipToPx(8) * 2))
{
selectMOnth= i + 1;
return true;
}
}
}
//月份触摸区域
//计算每个月份X坐标的中心点
float mOnthTouchY= viewHeight * 0.7f - dipToPx(3);//减去dipToPx(3)增大触摸面积
float newWith = viewWith - (viewWith * 0.15f) * 2;//分隔线距离最左边和最右边的距离是0.15倍的viewWith
float validTouchX[] = new float[monthText.length];
for(int i = 0; i  monthTouchY)
{
for(int i = 0; i  validTouchX[i] - dipToPx(8))
{
Log.v("ScoreTrend", "validateTouch: " + (i + 1));
selectMOnth= i + 1;
return true;
}
}
}
return false;
}

获取控件的宽高

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
viewWith = w;
viewHeight = h;
initData();
}

4.总结

还有一些比较不够完善的地方需要处理,比如说可以通过XML调节的属性太少了。平时写的东西还是太少了,希望以后多总结完善写作功底吧。需要的属性后面需要再完善吧

GitHub地址:https://github.com/FelixLee0527/ZhiMaScoreCurve

以上所述是小编给大家介绍的Android 自定义View实现芝麻分曲线图效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 本文基于对相关论文和开源代码的研究,详细介绍了LOAM(激光雷达里程计与建图)的工作原理,并对其关键技术进行了分析。 ... [详细]
  • 本文介绍如何使用 Sortable.js 库实现元素的拖拽和位置交换功能。Sortable.js 是一个轻量级、无依赖的 JavaScript 库,支持拖拽排序、动画效果和多种插件扩展。通过简单的配置和事件处理,可以轻松实现复杂的功能。 ... [详细]
  • 深入解析:手把手教你构建决策树算法
    本文详细介绍了机器学习中广泛应用的决策树算法,通过天气数据集的实例演示了ID3和CART算法的手动推导过程。文章长度约2000字,建议阅读时间5分钟。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 本报告涵盖了个人博客账号和码云账号的注册过程,以及对网络工程专业学习的反思与展望。通过回顾初入大学时的专业选择,分析当前的专业知识和技能水平,并对未来的职业规划进行了详细讨论。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
author-avatar
赵小锅2502889451
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有