热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android仿水波纹流量球进度条控制器

这篇文章主要介绍了Android仿水波纹流量球进度条控制器的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

仿水波纹流球进度条控制器,Android实现高端大气的主流特效,供大家参考,具体内容如下

效果图:

CircleView

这里主要是实现中心圆以及水波特效

package com.lgl.circleview;

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.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;

/**
 * 水波圆
 * 
 * @author lgl
 * 
 */
public class CircleView extends View {

 private Context mContext;

 private int mScreenWidth;
 private int mScreenHeight;

 private Paint mRingPaint;
 private Paint mCirclePaint;
 private Paint mWavePaint;
 private Paint linePaint;
 private Paint flowPaint;
 private Paint leftPaint;

 private int mRingSTROKEWidth = 15;
 private int mCircleSTROKEWidth = 2;
 private int mLineSTROKEWidth = 1;

 private int mCircleColor = Color.WHITE;
 private int mRingColor = Color.WHITE;
 private int mWaveColor = Color.WHITE;

 private Handler mHandler;
 private long c = 0L;
 private boolean mStarted = false;
 private final float f = 0.033F;
 private int mAlpha = 50;// 透明度
 private float mAmplitude = 10.0F; // 振幅
 private float mWaterLevel = 0.5F;// 水高(0~1)
 private Path mPath;

 // 绘制文字显示在圆形中间,只是我没有设置,我觉得写在布局上也挺好的
 private String flowNum = "";
 private String flowLeft = "还剩余";

 /**
  * @param context
  */
 public CircleView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  mCOntext= context;
  init(mContext);
 }

 /**
  * @param context
  * @param attrs
  */
 public CircleView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
  mCOntext= context;
  init(mContext);
 }

 /**
  * @param context
  * @param attrs
  * @param defStyleAttr
  */
 public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  // TODO Auto-generated constructor stub
  mCOntext= context;
  init(mContext);
 }

 public void setmWaterLevel(float mWaterLevel) {
  this.mWaterLevel = mWaterLevel;
 }

 private void init(Context context) {
  mRingPaint = new Paint();
  mRingPaint.setColor(mRingColor);
  mRingPaint.setAlpha(50);
  mRingPaint.setStyle(Paint.Style.STROKE);
  mRingPaint.setAntiAlias(true);
  mRingPaint.setStrokeWidth(mRingSTROKEWidth);

  mCirclePaint = new Paint();
  mCirclePaint.setColor(mCircleColor);
  mCirclePaint.setStyle(Paint.Style.STROKE);
  mCirclePaint.setAntiAlias(true);
  mCirclePaint.setStrokeWidth(mCircleSTROKEWidth);

  linePaint = new Paint();
  linePaint.setColor(mCircleColor);
  linePaint.setStyle(Paint.Style.STROKE);
  linePaint.setAntiAlias(true);
  linePaint.setStrokeWidth(mLineSTROKEWidth);

  flowPaint = new Paint();
  flowPaint.setColor(mCircleColor);
  flowPaint.setStyle(Paint.Style.FILL);
  flowPaint.setAntiAlias(true);
  flowPaint.setTextSize(36);

  leftPaint = new Paint();
  leftPaint.setColor(mCircleColor);
  leftPaint.setStyle(Paint.Style.FILL);
  leftPaint.setAntiAlias(true);
  leftPaint.setTextSize(36);

  mWavePaint = new Paint();
  mWavePaint.setStrokeWidth(1.0F);
  mWavePaint.setColor(mWaveColor);
  mWavePaint.setAlpha(mAlpha);
  mPath = new Path();

  mHandler = new Handler() {
   @Override
   public void handleMessage(android.os.Message msg) {
    if (msg.what == 0) {
     invalidate();
     if (mStarted) {
      // 不断发消息给自己,使自己不断被重绘
      mHandler.sendEmptyMessageDelayed(0, 60L);
     }
    }
   }
  };
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int width = measure(widthMeasureSpec, true);
  int height = measure(heightMeasureSpec, false);
  if (width  0.5F) {
   startAngle = 360F - horiAngle;
   sweepAngle = 180F + 2 * horiAngle;
  } else {
   startAngle = horiAngle;
   sweepAngle = 180F - 2 * horiAngle;
  }

  canvas.drawLine(mScreenWidth * 3 / 8, mScreenHeight * 5 / 8,
    mScreenWidth * 5 / 8, mScreenHeight * 5 / 8, linePaint);

  float num = flowPaint.measureText(flowNum);
  canvas.drawText(flowNum, mScreenWidth * 4 / 8 - num / 2,
    mScreenHeight * 4 / 8, flowPaint);
  float left = leftPaint.measureText(flowLeft);
  canvas.drawText(flowLeft, mScreenWidth * 4 / 8 - left / 2,
    mScreenHeight * 3 / 8, leftPaint);

  // 如果未开始(未调用startWave方法),绘制一个扇形
  if ((!mStarted) || (mScreenWidth == 0) || (mScreenHeight == 0)) {
   // 绘制,即水面静止时的高度
   RectF oval = new RectF(mScreenWidth / 4, mScreenHeight / 4,
     mScreenWidth * 3 / 4, mScreenHeight * 3 / 4);
   canvas.drawArc(oval, startAngle, sweepAngle, false, mWavePaint);
   return;
  }
  // 绘制,即水面静止时的高度
  // 绘制,即水面静止时的高度
  RectF oval = new RectF(mScreenWidth / 4, mScreenHeight / 4,
    mScreenWidth * 3 / 4, mScreenHeight * 3 / 4);
  canvas.drawArc(oval, startAngle, sweepAngle, false, mWavePaint);

  if (this.c >= 8388607L) {
   this.c = 0L;
  }
  // 每次onDraw时c都会自增
  c = (1L + c);
  float f1 = mScreenHeight * (1.0F - (0.25F + mWaterLevel / 2))
    - mAmplitude;
  // 当前油量线的长度
  float waveWidth = (float) Math.sqrt(mScreenWidth * mScreenWidth / 16
    - centerOffset * centerOffset);
  // 与圆半径的偏移量
  float offsetWidth = mScreenWidth / 4 - waveWidth;

  int top = (int) (f1 + mAmplitude);
  mPath.reset();
  // 起始振动X坐标,结束振动X坐标
  int startX, endX;
  if (mWaterLevel > 0.50F) {
   startX = (int) (mScreenWidth / 4 + offsetWidth);
   endX = (int) (mScreenWidth / 2 + mScreenWidth / 4 - offsetWidth);
  } else {
   startX = (int) (mScreenWidth / 4 + offsetWidth - mAmplitude);
   endX = (int) (mScreenWidth / 2 + mScreenWidth / 4 - offsetWidth + mAmplitude);
  }
  // 波浪效果
  while (startX  CREATOR = new Parcelable.Creator() {
   public SavedState createFromParcel(Parcel in) {
    return new SavedState(in);
   }

   public SavedState[] newArray(int size) {
    return new SavedState[size];
   }
  };
 }

}

我们运行一下

其实他是十分的空旷的,所以也值得我们去定制,我们在中间加个流量显示,再加个进度条
activity_main.xml

<&#63;xml version="1.0" encoding="utf-8"&#63;>


 

 

 

 



我们要实现这个,就要调用它的初始化以及start方法

 mCircleView = (CircleView) findViewById(R.id.wave_view);
  // 设置多高,float,0.1-1F
  mCircleView.setmWaterLevel(0.1F);
  // 开始执行
  mCircleView.startWave();

别忘了activity销毁的时候把它回收哦
@Override
 protected void onDestroy() {
  // TODO Auto-generated method stub
  mCircleView.stopWave();
  mCircleView = null;
  super.onDestroy();
 }

我们再运行一遍

但是我们要怎么让水波纹随着进度条一起上升下降尼?,这里我们就要用到我们刚才写的SeekBar了,我们实现它的

setOnSeekBarChangeListener来监听,这样我们就要复写他的三个方法,这里我们只要用到一个
public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    //跟随进度条滚动
    mCircleView.setmWaterLevel((float) progress / 100);
    }

这里,我们要这样算的,我们设置高度的单位是float,也就是从0-1F,而我们的进度是int progress,从0-100,我们就要用(float) progress / 100)并且强转来得到单位,好了,我们现在水波纹的高度就是随着我们的进度条一起变化了,我们再来运行一下

好的,这样的话,我们就只剩下一个了,就是让大小随着我们的进度条变化了,这里我们因为更新UI不能再主线程中操作,所以我们需要用到我们的老伙计Handler了,但是用到handler还不够,我们的进度条数值也是在内部类里面,所以这里我们需要用到Handler来传值了,这里我们用的是Bundle,我们还是在onProgressChanged方法中操作了

 //创建一个消息
    Message message = new Message();
    Bundle bundle = new Bundle();
    //put一个int值
    bundle.putInt("progress", progress);
    //装载
    message.setData(bundle);
    //发送消息
    handler.sendMessage(message);
    //创建表示
    message.what = 1;

消息发送过去了,我们就在前面写个Handler去接收就是了

 private Handler handler = new Handler() {
  public void handleMessage(android.os.Message msg) {
   if (msg.what == 1) {
    int num = msg.getData().getInt("progress");
    Log.i("num", num + "");
    power.setText((float) num / 100 * max + "M/" + max + "M");
   }
  }
 };

这里的计算公式尼,是当前的数值/100得到百分比再去*最大值。我们现在可以完整的运行一下了,其实和最上面运行的图片是一样的

MainActivity

package com.lgl.circleview;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends Activity {

 private CircleView mCircleView;
 private SeekBar mSeekBar;
 private TextView power;
 private int max = 1024;
 private int min = 102;

 private Handler handler = new Handler() {
 public void handleMessage(android.os.Message msg) {
  if (msg.what == 1) {
  int num = msg.getData().getInt("progress");
  Log.i("num", num + "");
  power.setText((float) num / 100 * max + "M/" + max + "M");
  }
 }
 };

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

 power = (TextView) findViewById(R.id.power);
 power.setText(min + "M/" + max + "M");

 mCircleView = (CircleView) findViewById(R.id.wave_view);
 // 设置多高,float,0.1-1F
 mCircleView.setmWaterLevel(0.1F);
 // 开始执行
 mCircleView.startWave();

 mSeekBar = (SeekBar) findViewById(R.id.seekBar);
 mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
   boolean fromUser) {
  mCircleView.setmWaterLevel((float) progress / 100);
  // 创建一个消息
  Message message = new Message();
  Bundle bundle = new Bundle();
  // put一个int值
  bundle.putInt("progress", progress);
  // 装载
  message.setData(bundle);
  // 发送消息
  handler.sendMessage(message);
  // 创建表示
  message.what = 1;
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {

  }
 });
 }

 @Override
 protected void onDestroy() {
 // TODO Auto-generated method stub
 mCircleView.stopWave();
 mCircleView = null;
 super.onDestroy();
 }
}

代码下载:Android仿水波纹流量球进度条

以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文介绍了Python版Protobuf的安装和使用方法,包括版本选择、编译配置、示例代码等内容。通过学习本教程,您将了解如何在Python中使用Protobuf进行数据序列化和反序列化操作,以及相关的注意事项和技巧。 ... [详细]
  • MACElasticsearch安装步骤及验证方法
    本文介绍了MACElasticsearch的安装步骤,包括下载ZIP文件、解压到安装目录、启动服务,并提供了验证启动是否成功的方法。同时,还介绍了安装elasticsearch-head插件的方法,以便于进行查询操作。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
author-avatar
lingling2502852417
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有