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

android自定义柱状图表,Android自定义柱状图控件

搜索github会发现已经有很多相对成熟的图表框架,但与我们拿到的ui效果图总会有一些差别,然后就会陷入是把别人源码下载下来修改之后作为已用࿰

搜索github会发现已经有很多相对成熟的图表框架,但与我们拿到的ui效果图总会有一些差别,然后就会陷入是把别人源码下载下来修改之后作为已用,或是重新定义一个新控件的两难境地。初拿到效果图感觉还是比较复杂难以实现,但是仔细观察发现其实这就是一个列表,一个横向列表,一个可以用RecyclerView实现的列表。

private Paint paint;

private int measuredWidth;

private int measuredHeight;

private double ratio;

private GradientDrawable gradientDrawable;

public BarGraphItem(Context context) {

super(context);

initPaint();

}

public BarGraphItem(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

initPaint();

}

public BarGraphItem(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initPaint();

}

//设置柱子的高度

public void setRatio(double ratio) {

this.ratio = ratio;

invalidate();

}

private void initPaint() {

paint = new Paint();

paint.setStyle(Paint.Style.FILL);

paint.setColor(getResources().getColor(R.color.colorBarBack));

paint.setAntiAlias(true);

int colors[] = {getResources().getColor(R.color.colorBarColor), getResources().getColor(R.color.colorGradientGreen)};

gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP,colors);

//设置渐变色

gradientDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);

//设置顶部圆角

gradientDrawable.setCornerRadii(new float[]{15,15,15,15,0,0,0,0});

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

measuredWidth = getMeasuredWidth();

measuredHeight = getMeasuredHeight();

}

@Override

protected void onDraw(Canvas canvas) {

//画柱子的背景色

canvas.drawRect(0, 0, measuredWidth, measuredHeight, paint);

//计算柱子实际高度

if (ratio != 0){

int ratioHeight = (int) (measuredHeight * ratio + 0.5);

//默认坐标原点在左上角,这里我们把画布移到左上角

canvas.translate(0,measuredHeight - ratioHeight);

//x,y,w,h

gradientDrawable.setBounds(0,0,measuredWidth, ratioHeight);

gradientDrawable.draw(canvas);

}

}

}

代码并不复杂,可以看到最终效果有很多渐变色的运用,平时我们会用shape标签绘制一些简单的图形,其中有一个gradient属性可以帮我们实现渐变效果,那在代码中可以直接使用GradientDrawable来实现同样的效果。接下来在布局文件中使用

android:orientation="vertical"

xmlns:android="http://schemas.android.com/apk/res/android"

android:gravity="center_horizontal"

android:paddingTop="4dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content">

android:textSize="9dp"

android:text="--"

android:id="@+id/tv_amount_bar_graph"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

android:id="@+id/rl_bar_graph"

android:layout_marginTop="8dp"

android:background="@drawable/shape_bar_graph"

android:layout_width="43dp"

android:layout_height="wrap_content">

android:layout_centerHorizontal="true"

android:id="@+id/bgi_bar_graph"

android:layout_gravity="center_horizontal"

android:layout_width="8dp"

android:layout_height="110dp" />

android:textColor="#999999"

android:textSize="12dp"

android:gravity="center"

android:text="--"

android:background="#F9F9F9"

android:layout_marginTop="8dp"

android:id="@+id/tv_time_bar_graph"

android:layout_width="match_parent"

android:layout_height="40dp" />

android:id="@+id/iv_highest_bar_graph"

android:visibility="invisible"

android:src="@drawable/triangle_red_rose"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

因为柱状图整体的渐变背景并没到底部,只是中间柱子的部分,所以把这个背景的设置放到item的布局中,也是用shape 标签实现

android:shape="rectangle">

android:angle="90"

android:startColor="@color/colorLightBlue"

android:endColor="@color/colorGradientWhite"

>

标识最高点的红色三角可以用png或其它格式的图片,为了尽量缩减包体积也可以用layerlist标签来实现,

android:fromDegrees="45"

android:toDegrees="45"

android:pivotX="-40%"

android:pivotY="80%">

android:height="8dp"/>

准备工作已经完成,接下来就可以愉快地进行recyclerview三步曲了。在xml布局文件中使用recyclerview(比较简单代码就省略了),然后在MainActivity中初始化recyclerview,

private void initRecyclerView() {

//先造几条假数据

DecimalFormat df = new DecimalFormat("0.00");

int maxIndex = 0;

double max = 0;

for (int i &#61; 1;i <&#61; 10;i&#43;&#43;){

IncomeDetailsBean incomeDetailsBean &#61; new IncomeDetailsBean();

incomeDetailsBean.setDate(i &#43; "点");

double random &#61; Math.random();

//记录最大值

if (random > max) {

max &#61; random;

maxIndex &#61; i - 1;

}

incomeDetailsBean.setIncome(df.format(random * 10) &#43; "");

incomeDetailsBean.setRatio(random);

incomeDetails.add(incomeDetailsBean);

}

incomeDetails.get(maxIndex).setHighest(true);

//初始化recyclerview

layoutManager &#61; new LinearLayoutManager(this);

layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

recyclerView.setLayoutManager(layoutManager);

barGraphAdapter &#61; new BarGraphAdapter(this,incomeDetails);

recyclerView.setAdapter(barGraphAdapter);

}

最后一步adapter&#xff0c;只看绑定控件这一部分&#xff0c;

&#64;Override

public void onBindViewHolder(ViewHolder holder, int position) {

//如果没有数据会有几条占位图

if (incomeDetails &#61;&#61; null || incomeDetails.size() &#61;&#61; 0){

holder.barGraphItem.setRatio(0);

holder.tv_time.setText("--");

holder.tv_amount.setText("--");

if (View.VISIBLE &#61;&#61; holder.iv_highest.getVisibility()) {

holder.iv_highest.setVisibility(View.INVISIBLE);

holder.tv_time.setTextSize(12);

holder.tv_time.setTextColor(Color.parseColor("#999999"));

}

holder.tv_amount.setTextColor(Color.LTGRAY);

}else {

//绑定数据

IncomeDetailsBean incomeDetailsBean &#61; incomeDetails.get(position);

holder.barGraphItem.setRatio(incomeDetailsBean.getRatio());

holder.tv_time.setText(incomeDetailsBean.getDate());

holder.tv_amount.setText(incomeDetailsBean.getIncome());

holder.tv_amount.setTextColor(incomeDetailsBean.getRatio() &#61;&#61; 0 ? Color.LTGRAY : context.getResources().getColor(R.color.colorAccent));

holder.iv_highest.setVisibility(incomeDetailsBean.isHighest() ? View.VISIBLE : View.INVISIBLE);

holder.tv_time.setTextSize(incomeDetailsBean.isHighest() ? 16 : 12);

holder.tv_time.setTextColor(incomeDetailsBean.isHighest() ? context.getResources().getColor(R.color.colorAccent) : Color.parseColor("#999999"));

}

//缩放动画(x轴方向不变&#xff0c;y轴由0到1增长效果)

Animation animation &#61; AnimationUtils.loadAnimation(context, R.anim.scale_item);

holder.barGraphItem.startAnimation(animation);

}

纵向缩放动画

android:duration&#61;"700"

android:fromXScale&#61;"1.0"

android:fromYScale&#61;"0.0"

android:pivotY&#61;"100%"

android:toXScale&#61;"1.0"

android:toYScale&#61;"1.0">

最后是图中用到的配色资源

#3F51B5

#303F9F

&#64;android:color/holo_green_dark

#3399cc00

#ff669900

#5099cc00

#0599cc00

#40669900

整个过程没有很生僻的点&#xff0c;基本是对Android Drawable、动画及简单自定义控件这些基本技能的综合运用。

希望对你有所帮助&#xff0c;喜欢记得点赞喔。

作者简介&#xff1a;现就职于甜橙金融信息技术部&#xff0c;负责安卓客户端开发工作。



推荐阅读
  • 解决Spring Boot项目创建失败的问题
    在尝试创建新的Spring Boot项目时遇到了一些问题,具体表现为在项目创建过程中的两个关键步骤出现错误。本文将详细探讨这些问题及其解决方案。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Python自动化测试入门:Selenium环境搭建
    本文详细介绍如何在Python环境中安装和配置Selenium,包括开发工具PyCharm的安装、Python环境的设置以及Selenium包的安装方法。此外,还提供了编写和运行第一个自动化测试脚本的步骤。 ... [详细]
  • 本篇文章介绍如何将两个分别表示整数的链表进行相加,并生成一个新的链表。每个链表节点包含0到9的数值,如9-3-7和6-3相加得到1-0-0-0。通过反向处理链表、逐位相加并处理进位,最终再将结果链表反向,即可完成计算。 ... [详细]
  • Mongoose 5.12.10 发布:MongoDB 异步对象模型工具的新特性与修复
    Mongoose 是一款专为异步环境设计的 MongoDB 对象模型工具,支持 Promise 和回调函数。最新版本 Mongoose 5.12.10 带来了多项修复和改进,包括查询选项中的默认值设置、嵌入式判别器填充、以及 TypeScript 定义文件的优化。 ... [详细]
  • ListView简单使用
    先上效果:主要实现了Listview的绑定和点击事件。项目资源结构如下:先创建一个动物类,用来装载数据:Animal类如下:packagecom.example.simplelis ... [详细]
  • 本文详细介绍了如何在 Android 中使用值动画(ValueAnimator)来动态调整 ImageView 的高度,并探讨了相关的关键属性和方法,包括图片填充后的高度、原始图片高度、动画变化因子以及布局重置等。 ... [详细]
  • 深入剖析JVM垃圾回收机制
    本文详细探讨了Java虚拟机(JVM)中的垃圾回收机制,包括其意义、对象判定方法、引用类型、常见垃圾收集算法以及各种垃圾收集器的特点和工作原理。通过理解这些内容,开发人员可以更好地优化内存管理和程序性能。 ... [详细]
  • 本文详细介绍了 Android 开发中 layout_gravity 属性的使用方法及其在不同布局下的效果,旨在帮助开发者更好地理解和利用这一属性来精确控制视图的布局。 ... [详细]
  • 本文介绍了如何通过在数据库表中增加一个字段来记录文章的访问次数,并提供了一个示例方法用于更新该字段值。 ... [详细]
  • 在寻找轻量级Ruby Web框架的过程中,您可能会遇到Sinatra和Ramaze。两者都以简洁、轻便著称,但它们之间存在一些关键区别。本文将探讨这些差异,并提供详细的分析,帮助您做出最佳选择。 ... [详细]
  • 本文详细记录了一位具有五年半开发经验的候选人,在华为Android高级开发职位面试过程中的经历。从早晨9点到下午5点半,经过了群体面试、技术面试、综合面试及英语面试等多个环节,最终成功通过考核。文章不仅分享了面试心得,还提供了宝贵的面试题资源。 ... [详细]
  • 使用WinForms 实现 RabbitMQ RPC 示例
    本文通过两个WinForms应用程序演示了如何使用RabbitMQ实现远程过程调用(RPC)。一个应用作为客户端发送请求,另一个应用作为服务端处理请求并返回响应。 ... [详细]
  • iOS 开发技巧:TabBarController 自定义与本地通知设置
    本文介绍了如何在 iOS 中自定义 TabBarController 的背景颜色和选中项的颜色,以及如何使用本地通知设置应用程序图标上的提醒个数。通过这些技巧,可以提升应用的用户体验。 ... [详细]
  • 在许多地理位置选择类的应用程序中,侧边栏是常见的用户界面元素,用于通过选择特定的字母快速定位和选择地点。本文将详细介绍如何在Android应用中创建一个具有波浪效果的自定义侧边栏,以提升用户体验。 ... [详细]
author-avatar
蒋军利
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有