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

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

先上效果图:

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


项目结构:

主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 {@Overrideprotected 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;
//    }@Overrideprotected 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);}}@Overrideprotected 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);}@Overrideprotected void onVisibilityChanged(View changedView, int visibility) {super.onVisibilityChanged(changedView, visibility);if (visibility == GONE || visibility == INVISIBLE) {stopAnimation();} else {startAnimation();}}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();startAnimation();}@Overrideprotected 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 访问密码 681c
有问题或者有业务QQ452270579交流,谢谢

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

  1. 水滴状的自己定义视图,让您摆脱单调的Dialog

    转载请注明出处:王亟亟的大牛之路 如今各种各样的进度条的呈现方式各种各样,我们老旧的条状条子和转圈圈的方式已经无法满足我们的业务需求,今天亟亟上的是一个水滴状循环滚动的一个自己定义视图.你能够把他用在 ...

  2. Android自定义视图四:定制onMeasure强制显示为方形

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...

  3. Xamarin XAML语言教程ContentView视图作为自定义视图的父类

    Xamarin XAML语言教程ContentView视图作为自定义视图的父类 自定义视图的父类:ContentView视图可以作为自定义视图的父类. [示例14-2]以下将自定义一个颜色视图.具体的 ...

  4. ​Xamarin iOS教程之自定义视图

    ​Xamarin iOS教程之自定义视图 Xamarin iOS自定义视图 工具栏中的视图在实际应用开发中用的很多,但是为了吸引用户的眼球,开发者可以做出一些自定义的视图. [示例2-33]以下将实现 ...

  5. Android Studio自定义视图无法预览

    Android Studio自定义视图没有办法预览 我想大家应该都和我一样,如果看到布局的编码的时候如果右边能够非常直观地显示出对应的视图,心里会非常舒心,像官方提供的tools命名空间就是为了这个目 ...

  6. MVC自定义视图规则

    自定义规则: using System.Web.Mvc; using System.Configuration;namespace Research {public class ViewConfig{ ...

  7. 【eoe教程】Android中自定义视图的绘制方法

    原文链接 :http://android.eoe.cn/topic/ui 自定义视图最重要的部分是它的外观.你可以根据应用的需求简单或复杂的实现它. 这个教程包含了最常见的操作. 重写onDraw() ...

  8. springmvc十七:自定义视图和自定义视图解析器

    自定义视图和视图解析器的步骤: 1).编写自定义的视图解析器,和视图实现类. 自定义的视图要实现View对象 public class MyView implements View{@Override ...

  9. (翻译)为你的MVC应用程序创建自定义视图引擎

    Creating your own MVC View Engine For MVC Application 原文链接:http://www.codeproject.com/Articles/29429 ...

  10. ListView自定义视图中对Button按钮实现仅允许一个按钮处于开启状态

    2019独角兽企业重金招聘Python工程师标准>>> Android项目迭代,之前使用下拉框Spinner被替换成ListView,相应的实现也比之前更加复杂了,根据美工给出的界面 ...

最新文章

  1. jquery 判断一个对象是否存在
  2. ThinkPHP微信实例——JSSDK图像接口多张图片上传下载并将图片流写入本地
  3. mysql的in查询参数限制,多少数据量会造成性能下降?什么时候创建临时表合适?
  4. 软件缘-网友个人精心打造的精品软件收集
  5. 每天一道LeetCode-----合并两个/多个有序链表为一个新链表
  6. 一名拿到阿里offer的Java程序员分享三轮面试经验
  7. python3(七)os模块
  8. 平衡二叉树(AVL树)-详解平衡调整
  9. Python 操作 Elasticsearch 实现 增 删 改 查
  10. 历经7年双11实战,阿里巴巴是如何定义云原生混部调度优先级及服务质量的?
  11. 6种快速统计代码执行时间的方法,真香!(史上最全)
  12. aix 添加lv 大小
  13. Nginx常用命令介绍
  14. Cartographer+LOAM+ LIO-SAM核心算法与源码剖析(室内+室外)
  15. SQL server 數據庫 從SQL2000搬移到SQL2016
  16. Win10 删除网络驱动器
  17. Java获取图片大小 及 尺寸 图片压缩 jpg压缩
  18. Spark推测执行spark.speculation
  19. matlab中啥叫字符串,在matlab中( )用于括住字符串.
  20. 科技部原副部长吴忠泽:尽早抢占元宇宙高地,掌握下一代互联网的话语权和主动权

热门文章

  1. 代码整洁之道读书笔记----第一章---综述--第一节-混乱代码和华丽的新系统
  2. sublime text3 错误解决
  3. 【ZOJ 3715 —— 13年浙江省赛K】Kindergarten Election 【枚举答案进行判断】 【夺宝奇兵 —— CCPC-Wannafly Winter Camp Day1】
  4. 微服务分布式基础项目(免费答疑):SpringBoot2.X+SpringCloud+SpringDataJPA+Consul+Feign+Swagger (还会持续更新,不懂的可以问博主)
  5. 2-15 复合类型概述
  6. 用户增删改查 django生命周期 数据库操作
  7. J2EE基础之EJB
  8. 大数据真实电商数据仓库全流程开发详解
  9. SQL Server用户权限详解
  10. MooTools 1.4 源码分析 - Fx