转载请注明出处:王亟亟的大牛之路

如今各种各样的进度条的呈现方式各种各样,我们老旧的条状条子和转圈圈的方式已经无法满足我们的业务需求,今天亟亟上的是一个水滴状循环滚动的一个自己定义视图。你能够把他用在各种不同的场景下。

先上效果图:

然后又加入了真空,隐藏和显示的效果,如图。



项目结构:

主Activity

public class MainActivity extends AppCompatActivity {private MetaballView metaballView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);metaballView = (MetaballView) this.findViewById(R.id.metaball);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.menu_main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();//noinspection SimplifiableIfStatementif (id == R.id.action_fill) {metaballView.setPaintMode(1);return true;} else if (id == R.id.action_strock) {metaballView.setPaintMode(0);return true;}else if(id==R.id.action_disappear){metaballView.setVisibility(View.GONE);return  true;}else if(id==R.id.action_appear){metaballView.setVisibility(View.VISIBLE);return  true;}return super.onOptionsItemSelected(item);}
}

CustomView

public class MetaballView extends View {private Paint paint = new Paint();private float handle_len_rate = 2f;private float radius = 30;private final int ITEM_COUNT = 6;private final int ITEM_DIVIDER = 60;private final float SCALE_RATE = 0.3f;private float maxLength;private ArrayList<Circle> circlePaths = new ArrayList<>();private float mInterpolatedTime;private MoveAnimation wa;private Circle circle;public MetaballView(Context context) {super(context);init();}public MetaballView(Context context, AttributeSet attrs) {super(context, attrs);init();}public MetaballView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private class Circle {float[] center;float radius;}public void setPaintMode(int mode) {paint.setStyle(mode == 0 ?

Paint.Style.STROKE : Paint.Style.FILL); } private void init() { paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.FILL); paint.setAntiAlias(true); Circle circlePath = new Circle(); circlePath.center = new float[]{(radius + ITEM_DIVIDER), radius * 1.4f}; circlePath.radius = radius / 4 * 3; circlePaths.add(circlePath); for (int i = 1; i < ITEM_COUNT; i++) { circlePath = new Circle(); circlePath.center = new float[]{(radius * 2 + ITEM_DIVIDER) * i, radius * 1.4f}; circlePath.radius = radius; circlePaths.add(circlePath); } maxLength = (radius * 2 + ITEM_DIVIDER) * ITEM_COUNT; } private float[] getVector(float radians, float length) { float x = (float) (Math.cos(radians) * length); float y = (float) (Math.sin(radians) * length); return new float[]{ x, y }; } private class MoveAnimation extends Animation { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); mInterpolatedTime = interpolatedTime; invalidate(); } } /** * @param canvas 画布 * @param j * @param i * @param v 控制两个圆连接时候长度,间接控制连接线的粗细。该值为1的时候连接线为直线 * @param handle_len_rate * @param maxDistance */ private void metaball(Canvas canvas, int j, int i, float v, float handle_len_rate, float maxDistance) { final Circle circle1 = circlePaths.get(i); final Circle circle2 = circlePaths.get(j); RectF ball1 = new RectF(); ball1.left = circle1.center[0] - circle1.radius; ball1.top = circle1.center[1] - circle1.radius; ball1.right = ball1.left + circle1.radius * 2; ball1.bottom = ball1.top + circle1.radius * 2; RectF ball2 = new RectF(); ball2.left = circle2.center[0] - circle2.radius; ball2.top = circle2.center[1] - circle2.radius; ball2.right = ball2.left + circle2.radius * 2; ball2.bottom = ball2.top + circle2.radius * 2; float[] center1 = new float[]{ ball1.centerX(), ball1.centerY() }; float[] center2 = new float[]{ ball2.centerX(), ball2.centerY() }; float d = getDistance(center1, center2); float radius1 = ball1.width() / 2; float radius2 = ball2.width() / 2; float pi2 = (float) (Math.PI / 2); float u1, u2; if (d > maxDistance) { canvas.drawCircle(ball1.centerX(), ball1.centerY(), circle1.radius, paint); canvas.drawCircle(ball2.centerX(), ball2.centerY(), circle2.radius, paint); } else { float scale2 = 1 + SCALE_RATE * (1 - d / maxDistance); float scale1 = 1 - SCALE_RATE * (1 - d / maxDistance); radius2 *= scale2; // radius1 *= scale1; canvas.drawCircle(ball1.centerX(), ball1.centerY(), radius1, paint); canvas.drawCircle(ball2.centerX(), ball2.centerY(), radius2, paint); } Log.d("Metaball_radius", "radius1:" + radius1 + ",radius2:" + radius2); if (radius1 == 0 || radius2 == 0) { return; } if (d > maxDistance || d <= Math.abs(radius1 - radius2)) { return; } else if (d < radius1 + radius2) { u1 = (float) Math.acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d)); u2 = (float) Math.acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d)); } else { u1 = 0; u2 = 0; } Log.d("Metaball", "center2:" + Arrays.toString(center2) + ",center1:" + Arrays.toString(center1)); float[] centermin = new float[]{center2[0] - center1[0], center2[1] - center1[1]}; float angle1 = (float) Math.atan2(centermin[1], centermin[0]); float angle2 = (float) Math.acos((radius1 - radius2) / d); float angle1a = angle1 + u1 + (angle2 - u1) * v; float angle1b = angle1 - u1 - (angle2 - u1) * v; float angle2a = (float) (angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v); float angle2b = (float) (angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v); Log.d("Metaball", "angle1:" + angle1 + ",angle2:" + angle2 + ",angle1a:" + angle1a + ",angle1b:" + angle1b + ",angle2a:" + angle2a + ",angle2b:" + angle2b); float[] p1a1 = getVector(angle1a, radius1); float[] p1b1 = getVector(angle1b, radius1); float[] p2a1 = getVector(angle2a, radius2); float[] p2b1 = getVector(angle2b, radius2); float[] p1a = new float[]{p1a1[0] + center1[0], p1a1[1] + center1[1]}; float[] p1b = new float[]{p1b1[0] + center1[0], p1b1[1] + center1[1]}; float[] p2a = new float[]{p2a1[0] + center2[0], p2a1[1] + center2[1]}; float[] p2b = new float[]{p2b1[0] + center2[0], p2b1[1] + center2[1]}; Log.d("Metaball", "p1a:" + Arrays.toString(p1a) + ",p1b:" + Arrays.toString(p1b) + ",p2a:" + Arrays.toString(p2a) + ",p2b:" + Arrays.toString(p2b)); float[] p1_p2 = new float[]{p1a[0] - p2a[0], p1a[1] - p2a[1]}; float totalRadius = (radius1 + radius2); float d2 = Math.min(v * handle_len_rate, getLength(p1_p2) / totalRadius); d2 *= Math.min(1, d * 2 / (radius1 + radius2)); Log.d("Metaball", "d2:" + d2); radius1 *= d2; radius2 *= d2; float[] sp1 = getVector(angle1a - pi2, radius1); float[] sp2 = getVector(angle2a + pi2, radius2); float[] sp3 = getVector(angle2b - pi2, radius2); float[] sp4 = getVector(angle1b + pi2, radius1); Log.d("Metaball", "sp1:" + Arrays.toString(sp1) + ",sp2:" + Arrays.toString(sp2) + ",sp3:" + Arrays.toString(sp3) + ",sp4:" + Arrays.toString(sp4)); Path path1 = new Path(); path1.moveTo(p1a[0], p1a[1]); path1.cubicTo(p1a[0] + sp1[0], p1a[1] + sp1[1], p2a[0] + sp2[0], p2a[1] + sp2[1], p2a[0], p2a[1]); path1.lineTo(p2b[0], p2b[1]); path1.cubicTo(p2b[0] + sp3[0], p2b[1] + sp3[1], p1b[0] + sp4[0], p1b[1] + sp4[1], p1b[0], p1b[1]); path1.lineTo(p1a[0], p1a[1]); path1.close(); canvas.drawPath(path1, paint); } private float getLength(float[] b) { return (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]); } private float getDistance(float[] b1, float[] b2) { float x = b1[0] - b2[0]; float y = b1[1] - b2[1]; float d = x * x + y * y; return (float) Math.sqrt(d); } //測试用 // @Override // public boolean onTouchEvent(MotionEvent event) { // switch (event.getAction()) { // case MotionEvent.ACTION_DOWN: // break; // case MotionEvent.ACTION_MOVE: // Circle circle = circlePaths.get(0); // circle.center[0] = event.getX(); // circle.center[1] = event.getY(); // invalidate(); // break; // case MotionEvent.ACTION_UP: // break; // } // // return true; // } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); circle = circlePaths.get(0); circle.center[0] = maxLength * mInterpolatedTime; for (int i = 1, l = circlePaths.size(); i < l; i++) { metaball(canvas, i, 0, 0.6f, handle_len_rate, radius * 4f); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (ITEM_COUNT * (radius * 2 + ITEM_DIVIDER)), MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (2 * radius * 1.4f), MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } private void stopAnimation() { this.clearAnimation(); postInvalidate(); } private void startAnimation() { wa = new MoveAnimation(); wa.setDuration(2500); wa.setInterpolator(new AccelerateDecelerateInterpolator()); wa.setRepeatCount(Animation.INFINITE); wa.setRepeatMode(Animation.REVERSE); startAnimation(wa); } @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); if (visibility == GONE || visibility == INVISIBLE) { stopAnimation(); } else { startAnimation(); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); startAnimation(); } @Override protected void onDetachedFromWindow() { stopAnimation(); super.onDetachedFromWindow(); } }

想改变呈现的方式能够改动Style文件以及setColor这里更改自己想要的颜色。也能够改构造函数用外部传入的方式来活用该类

布局文件

<RelativeLayout 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:background="#001d30"android:clipChildren="false"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=".MainActivity"><com.dodola.animview.MetaballViewandroid:id="@+id/metaball"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true" />
</RelativeLayout>

源代码已上传,地址:http://yunpan.cn/cddIXXQbqTf2m 訪问password 681c
有问题或者有业务QQ452270579交流,谢谢

水滴状的自己定义视图,让您摆脱单调的Dialog相关推荐

  1. Django站点管理、视图和URL(管理界面本地化、创建管理员、注册模型类、发布内容到数据库、定义视图、配置URLconf)

    1.Django站点管理 站点: 分为内容发布和公共访问两部分 内容发布的部分由网站的管理员负责查看.添加.修改.删除数据 Django能够根据定义的模型类自动地生成管理模块 使用Django的管理模 ...

  2. MySql数据库之视图(定义视图、查询视图、更新视图、视图的作用)

    目录 一.定义视图 1.建立视图 2.删除视图 二.查询视图 三.更新视图 四.视图的作用 一.定义视图 1.建立视图 语法:CREATE VIEW 视图名 [列名]... AS 子查询 [WITH ...

  3. 视图的定义,修改,删除,更新,以及定义视图的好处。

    视图 视图是从一个或几个基本表(或视图)导出的表.它与基本表不同,是一个虚表.视图一经定义,就可以和基本表一样被查询,被删除.也可以在视图之上再定义新的视图,但对视图的更新(增,删,改)操作则有一定的 ...

  4. android 重置画布,android-自定义视图:重按视图画布

    多亏了pskink,我才能够创建完整的解决方案. 如果要创建自定义视图,其中必须是针对不同触摸状态(按下,选定,聚焦等)的自定义工程图,并且您不知道此视图是否将放置在其他可以拦截触摸事件的视图中,或者 ...

  5. Android 基础:Materia Design 定义视图阴影elevation和创建卡片CardView

    新的  translationZ  属性使得你可以设计临时变更 elevation 的动画.elevation 变化在做触摸反馈时很有用. 创建列表和卡片 ======= RecyclerView 是 ...

  6. android-canvas-自定义视图-点击切换圆位置

    1.画圆类 import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; ...

  7. 合肥工业大学—SQL Server数据库实验九:视图的定义与使用

    视图的定义与使用 1. 定义视图 2. 使用视图 1. 定义视图 在EDUC数据库中,已Student.Course 和SC表为基础完成一下视图定义: 1) 定义视图V_SC_G:该视图包含Stude ...

  8. oracle数据库视图:定义、查询与更新 实践学习报告

    本篇博客分享SQL语言视图操作--详细实践学习报告(以截图方式展示) 软件:Oracle SQL Developer 目录 1.学生-课程数据库 2.视图 ①定义视图 ②查询视图 ③更新视图 ④视图的 ...

  9. oracle 隐藏视图定义,Oracle中视图(views)的含义

    很多时候在书本上也好在其他的一些学习博客里也好,有关数据库知识时经常看到视图,那么视图(views)到底是什么呢,有什么作用呢? 1.视图的定义 视图是存储在数据字典里的一条select语句. 通过创 ...

最新文章

  1. c语言修改elf文件crc32,hash/crc32
  2. LeetCode-26: 删除排序数组中的重复项
  3. 藏的太深!原来支付宝还有另一个“集福”活动
  4. tableau两个不同的图合并_【书稿摘要】Tableau地图函数(下)
  5. 使用WireShark抓包对方QQ的ip地址(通过QQ电话)
  6. 怎么不带卡、刷手机进出图书馆---手机NFC
  7. 上帝的归上帝 凯撒的归凯撒
  8. python处理excel数值为文本_使用Python中的xlrd将数字Excel数据读取为文本
  9. linux 微信安装
  10. 测试属性4 –准确性
  11. 用python实现相声、评书自动下载(四)
  12. 【实习日记】Linux-VM15-Ubuntu18.04 + 运行selenium实现文件下载
  13. PostMan发送请求参数带有路径特殊字符会返回400错误(与URL字符及URL编码值有关)
  14. 什么是GO+和GO哪里不一样
  15. 【产业互联网周报】阿里将暂停阿里云美国扩张计划;协同办公领域硝烟又起,华为推WeLink,企业微信与微信打通;申通全面迁至阿里云...
  16. powershell操作excel
  17. 百度IFE2018任务--20-21天
  18. 百度地图多个坐标连成轨迹
  19. 中毒后360安全卫士打不开的终极解决办法
  20. 泛融云计算机研究院,深圳泛融云计算研究院正式成立

热门文章

  1. C++ 虚函数表解析(转)
  2. python基础知识5——赋值与深浅拷贝——整数和字符串,列表元组字典
  3. 因讨要介绍费引发纠纷 浙江龙湾一男子砍死房产中介
  4. React-Router4按需加载
  5. 经验之谈—让你看明确block
  6. WCF学习之旅----基础篇之EnterpriseServices
  7. PHP核心技术与最佳实践 读书笔记 第二章 面向对象的设计原则
  8. Struts2中Action各种转发类型
  9. 第 6 章 存储 - 039 - Data Volume 之 bind mount
  10. GIT 添加多个git账号