100行Android代码轻松实现带动画柱状图

为何要用带动画的柱状图呢?

最近,项目中遇到一个地方,要用到柱状图。所以这篇文章主要讲怎么搞一个柱子。100行代码,搞定柱状图!

圆角,头顶带数字。恩,这样用drawable也可以搞定。但是,这个柱子是有一个动画的,就是进入到界面的时候柱子不断的长高。这样的话,综合考虑还是用自定义View来做比较简便。效果如下图了:

完整Demo地址请到我的github下载地址:
https://github.com/lixiaodaoaaa/ColumnAnimViewProject

关于尺寸

控件尺寸直接来自xml中的设置,无需进行onMeasure测量。所以使用getWidth和getHeight获取高度。

关于数据范围

数据如果是一个柱子单独显示,则数据的范围不是很重要,但是柱状图通常是由很多柱子并列显示的,而这些柱子的单位高度都应该是一样的,所以提供设置最大值的范围,最小值就是0.

关于数字的文字大小

由于柱子的宽度就是整个View的宽度,所以数字的宽度不能超过柱子的宽度。因为这个原因,文字的size需要动态计算。意思就是 0和100000这两个数字显示的时候,文字的大小是不一样的。

关于边界值

0,是一个边界值(最小值),当显示0的时候,并不是柱子不显示的,而是显示一个最小高度的。

关于动画

不停的设置值,就会形成动画。意思是先设置数据1,然后紧接着设数据2.3.4.5……一直到最终的显示值,就会有动画效果。但是如果最终数值很大,1,1,1的增加就会很慢,动画时间很长。

完整代码如下:

package com.lixiaodaoaaa.view.pieview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.gcssloop.graphics.R;
import com.lixiaodaoaaa.uitls.DensityUtils;

/**************************************
 * *** http://weibo.com/lixiaodaoaaa **
 * *** create at 2017/5/18  23:45 ****
 * ******* by:lixiaodaoaaa **********
 **************************************/

public class PColumn extends View {
  int MAX = 100;//最大
  int corner = 40;
  int data = 0;//显示的数
  int tempData = 0;
  int textPadding = 20;
  Paint mPaint;
  int mColor;

  Context mContext;

  public PColumn(Context context) {
    super(context);
    mContext = context;
  }

  public PColumn(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    mContext = context;
    initPaint();
  }

  public PColumn(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;
    initPaint();
  }

  private void initPaint() {
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mColor = mContext.getResources().getColor(R.color.colorPrimary);
    mPaint.setColor(mColor);
  }

  @Override
  public void draw(Canvas canvas) {
    super.draw(canvas);

    if (data == 0) {
      mPaint.setTextSize(getWidth() / 2);
      RectF oval3 = new RectF(0, getHeight() - DensityUtils.pxTodip(mContext, 20), getWidth(), getHeight());// 设置个新的长方形
      canvas.drawRoundRect(oval3, DensityUtils.pxTodip(mContext, corner), DensityUtils.pxTodip(mContext, corner), mPaint);

      canvas.drawText("0",
          getWidth() * 0.5f - mPaint.measureText("0") * 0.5f,
          getHeight() - DensityUtils.pxTodip(mContext, 20) - 2 * DensityUtils.pxTodip(mContext, textPadding),
          mPaint);
      return;
    }

    //防止数值很大的的时候,动画时间过长
    int step = data / 100 + 1;

    if (tempData < data - step) {
      tempData = tempData + step;
    } else {
      tempData = data;
    }
    //画圆角矩形
    String S = tempData + "";
    //一个字和两,三个字的字号相同
    if (S.length() < 4) {
      mPaint.setTextSize(getWidth() / 2);
    } else {
      mPaint.setTextSize(getWidth() / (S.length() - 1));
    }

    float textH = mPaint.ascent() + mPaint.descent();
    float MaxH = getHeight() - textH - 2 * DensityUtils.pxTodip(mContext, textPadding);
    //圆角矩形的实际高度
    float realH = MaxH / MAX * tempData;
    RectF oval3 = new RectF(0, getHeight() - realH, getWidth(), getHeight());// 设置个新的长方形
    canvas.drawRoundRect(oval3, DensityUtils.pxTodip(mContext, corner), DensityUtils.pxTodip(mContext, corner), mPaint);
    //写数字
    canvas.drawText(S,
        getWidth() * 0.5f - mPaint.measureText(S) * 0.5f,
        getHeight() - realH - 2 * DensityUtils.pxTodip(mContext, textPadding),
        mPaint);
    if (tempData != data) {
      postInvalidate();
    }
  }

  public void setData(int data, int MAX) {
    this.data = data;
    tempData = 0;
    this.MAX = MAX;
    postInvalidate();
  }

}
/*
 * Copyright 2016 GcsSloop
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Last modified 2016-10-02 00:22:33
 *
 */

package com.lixiaodaoaaa.graphics;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.gcssloop.graphics.R;
import com.lixiaodaoaaa.view.pieview.PColumn;

public class MainActivity extends AppCompatActivity {

  private PColumn column_one;
  private PColumn column_two;
  private PColumn column_three;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initAllViews();
  }

  private void initAllViews() {
    column_one = (PColumn) findViewById(R.id.column_one);
    column_two = (PColumn) findViewById(R.id.column_two);
    column_three = (PColumn) findViewById(R.id.column_three);

    column_one.setData(0, 100);
    column_two.setData(30, 100);
    column_three.setData(40, 100);

  }

}

xml配置如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="1"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.lixiaodaoaaa.graphics.MainActivity"
>
  <View
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="0.2"/>
  <com.lixiaodaoaaa.view.pieview.PColumn
    android:id="@+id/column_one"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

  <View
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2.4"/>

  <com.lixiaodaoaaa.view.pieview.PColumn
    android:id="@+id/column_two"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

  <View
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2.4"/>

  <com.lixiaodaoaaa.view.pieview.PColumn
    android:id="@+id/column_three"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"/>
  <View
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="0.2"/>
</LinearLayout>

完整Demo地址请到我的github下载地址:
https://github.com/lixiaodaoaaa/ColumnAnimViewProject

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义view实现动态柱状图

    先看一下动态柱状图效果. 主要功能是可以自定义指定的字体,柱状图颜色,动态效果. 在自定义view public class Histogram extends View { int MAX = 100;//矩形显示的最大值 int corner = 0; //矩形的角度. 设置为0 则没有角度. double data = 0.0;//显示的数 double tempData = 0; //初始数据 int textPadding = 50; //字体与矩形图的距离 Paint mPaint;

  • Android自定义带增长动画和点击弹窗提示效果的柱状图DEMO

    项目中最近用到各种图表,本来打算用第三方的,例如MPAndroid,这是一个十分强大的图表库,应用起来十分方便,但是最终发现和设计不太一样,没办法,只能自己写了.今天将写好的柱状图的demo贴在这,该柱状图可根据数据的功能有一下几点: 1. 根据数据的多少,动态的绘制柱状图柱子的条数: 2. 柱状图每条柱子的绘制都有动态的动画效果: 3. 每条柱子有点击事件,点击时弹出提示框,显示相关信息,规定时间后,弹窗自动消失. 好了,先上演示图: 下边贴出相关代码: 自定义柱状图类: package co

  • MPAndroidChart开源图表库的使用介绍之饼状图、折线图和柱状图

    MPAndroidChart开源图表库之饼状图 为大家介绍一款图标开源库MPAndroidChart,它不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,用起来非常灵活.MPAndroidChart同样拥有常用的图表类型:线型图.饼图.柱状图和散点图. mpandroidchartlibrary.jar包下载地址: https://github.com/PhilJay/MPAndroidChart/releases 下面主要实现以下饼状图: 1.从上面的地址中下载

  • 详解Android自定义View--自定义柱状图

    绪论 转眼间,2016伴随着互联网寒冬和帝都的雾霾马上就过去了,不知道大家今年一整年过得怎么样?最近票圈被各个城市的雾霾刷屏,内心难免会动荡,庆幸自己早出来一年,也担忧着自己的未来的职业规划.无所谓了,既然选择了这个行业,我觉得大家就应该坚持下去,路是自己走的,及时再寒冬,只要你足够优秀,足够努力,相信你最后还是会找到自己满意的工作的.最后还要感谢今年博客之星大家对我的投票支持,非常感谢.不多说了,今天的主题是它–对,自定义View柱状图. 先来说说我最近在做什么吧?好久没有写博客了,最近手里有

  • 100行Android代码轻松实现带动画柱状图

    为何要用带动画的柱状图呢? 最近,项目中遇到一个地方,要用到柱状图.所以这篇文章主要讲怎么搞一个柱子.100行代码,搞定柱状图! 圆角,头顶带数字.恩,这样用drawable也可以搞定.但是,这个柱子是有一个动画的,就是进入到界面的时候柱子不断的长高.这样的话,综合考虑还是用自定义View来做比较简便.效果如下图了: 完整Demo地址请到我的github下载地址: https://github.com/lixiaodaoaaa/ColumnAnimViewProject 关于尺寸 控件尺寸直接来

  • 100行python代码实现跳一跳辅助程序

    写在前面 分享一下今天下午用python写的"跳一跳"小游戏的辅助程序.之前是准备用树莓派操控一个"机械手指"来代替人的触摸操作,但该方案还在酝酿中,实现了再分享.接下来要分享的是用"纯软件"的方法来玩"跳一跳". 原理 原理其实很简单,按如下步骤操作即可: 每次跳跃之前,截取一下手机屏幕,并将截图保存到本地电脑中: 计算截图中人偶的位置与将要跳至的台面中心的距离dd: 将以上距离dd换算成相应的触摸时间ss: 发送模拟触摸的

  • 100行Python代码实现每天不同时间段定时给女友发消息

    每天不同时间段通过微信发消息提醒女友 简介 有时候,你很想关心她,但是你太忙了,以至于她一直抱怨,觉得你不够关心她.你暗自下决心,下次一定要准时发消息给她,哪怕是几句话,可是你又忘记了.你觉得自己很委屈

  • 只需要100行Python代码就可以实现的贪吃蛇小游戏

    图示 基本准备 首先,我们需要安装pygame库,小编通过pip install pygame,很快就安装好了.在完成贪吃蛇小游戏的时候,我们需要知道整个游戏分为四部分: 1.游戏显示:游戏界面.结束界面 2.贪吃蛇:头部.身体.食物判断.死亡判断 3.树莓:随机生成 4.按键控制:上.下.左.右 游戏显示 首先,我们来初始化pygame,定义颜色.游戏界面的窗口大小.标题和图标等. 游戏结束界面,我们会显示"Game Over!"和该局游戏所得分数,相关代码如下: 贪吃蛇和树莓 我们

  • 100行PHP代码实现socks5代理服务器

    前两天在B站上看到一个小伙纸100元组装个电脑打LOL画质流畅,突发奇想100行代码能(简单)实现个啥好玩的.我主要是做php开发的,于是就有了本文. 当然,由于php(不算swoole扩展)本身不擅长做网络服务端编程,所以这个代理,只是个玩具,离日常使用有点距离.如果想使用稳定可靠的加密(所以能禾斗学上网)代理,可以用这个:https://github.com/momaer/asocks-go也是100来行代码使用go实现. 写的过程中发现php多线程还是难的.比如我开始想每个连接新建一个线程

  • 20行Android代码写一个CircleImageView

    一提到弄一个圆形的头像,很多人马上会想到用CircleIamgeView,但其实自己写一个也并不难自己写的部分也就20行代码,主要是用到PoterDuffXfermode来设置两个图层交集区域的显示方式 首先写一个继承自ImageView的控件 public class CircleImageView extends ImageView 然后创建构造方法 public CircleImageView(Context context, AttributeSet attrs) { super(con

  • 100行Python代码实现自动抢火车票(附源码)

    前言 又要过年了,今年你不妨自己写一段代码来抢回家的火车票,是不是很Cool.下面话不多说了,来一起看看详细的介绍吧. 先准备好: 12306网站用户名和密码 chrome浏览器及下载chromedriver 下载Python代码,来自网络整理 [点击下载 |  本地下载 ] 代码用的Python+Splinter开发,Splinter是一个使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互. Splinter官网:http://splinter.readth

  • 15行Python代码带你轻松理解令牌桶算法

    在网络中传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送,令牌桶算法就实现了这个功能, 可控制发送到网络上数据的数目,并允许突发数据的发送. 什么是令牌 从名字上看令牌桶,大概就是一个装有令牌的桶吧,那么什么是令牌呢? 紫薇格格拿的令箭,可以发号施令,令行禁止.在计算机的世界中,令牌也有令行禁止的意思,有令牌,则相当于得到了进行操作的授权,没有令牌,就什么都不能做. 用令牌实现限速器 我们用1块令牌来代表发送1字节数据的资格,假设我们源源不断的发放令牌给程序,程

  • Android实现带动画效果的可点击展开TextView

    本文为大家分享了Android实现带动画效果的可点击展开TextView 制作代码,效果图: 收起(默认)效果: 点击展开后的效果: 源码: 布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/activity_main" xmlns:android="http://schemas.android.com/apk/res/a

  • Android自定义PopWindow带动画向下弹出效果

    本文实例为大家分享了PopWindow实现带动画向下弹出效果的具体代码,供大家参考,具体内容如下 首先建一个popwin的实体类 package dmpte.mytest; import android.content.Context; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.PopupWindow; i

随机推荐