Android实现一个带粘连效果的LoadingBar
作者:Greenda米 发布时间:2023-04-26 11:47:41
标签:android,loadingbar,粘连效果
前言
我们平时在开发的时候,发起网络请求前,会需要显示一个Loading,一般的做法都是在xml布局上添加好Loading,然后在Activity中,setVisibility来控制Loading的显示和隐藏,这样使用起来就很不方便,因为每一个xml都得引入一个Loading布局。
而LoadingBar就更好的解决了这个问题
最近设计师在外国的一个网站上挑了一个Loading的效果图,尝试实现之后,虽然和原图有点不太一样,但是效果还是不错的。难点就是粘连效果的实现,贝塞尔曲线的点点们简直要把我折磨死了。
先上效果图:
实例代码
然后是源码,就是一个简单VIew,可以直接放在xml中使用。
package top.greendami.greendami;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by GreendaMi on 2017/3/17.
*/
public class PPView extends View {
String TAG = "PPView";
//动画开关
boolean isLoading = true;
Context mContext;
private int mWidth = 100;
private int mheight = 100;
public int mColor;
public Paint mPaint = new Paint();
float time = 0;
//小球与中间打球的最远距离
float distance = 100;
public PPView(Context context) {
super(context);
mContext = context;
}
public PPView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
mColor = context.getResources().getColor(R.color.colorPrimary);
init();
}
private void init() {
mPaint.setAntiAlias(true);
mPaint.setColor(mColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
//宽度至少是高度的4倍
if (widthSpecSize < 4 * heightSpecSize) {
widthSpecSize = 4 * heightSpecSize;
}
mWidth = widthSpecSize;
mheight = heightSpecSize;
distance = 1.2f * mheight;
setMeasuredDimension(widthSpecSize, heightSpecSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isLoading) {
//大圆半径
float bigR = mheight * 0.32f + mheight * 0.03f * Math.abs((float) Math.sin(Math.toRadians(time)));
float smallR = mheight * 0.22f + mheight * 0.03f * Math.abs((float) Math.cos(Math.toRadians(time)));
float bigx = (getWidth()) / 2;
//画中间大圆
canvas.drawCircle(bigx, mheight / 2, bigR, mPaint);
float smalx = getSmallCenterX();
//画小圆
canvas.drawCircle(smalx, mheight / 2, smallR, mPaint);
//画链接
//小球在右侧
if (smalx > bigx) {
Path path = new Path();
//上面的贝塞尔曲线的第一个点,在大圆身上
float x1 = bigx + bigR * (float) Math.cos(Math.toRadians(time));
float y1 = mheight / 2 - bigR * (float) Math.sin(Math.toRadians(time));
if (y1 > mheight / 2 - smallR) {
y1 = mheight / 2 - smallR;
x1 = bigx + (float) (Math.sqrt(bigR * bigR - smallR * smallR));
}
//上面的贝塞尔曲线的第三个点,在小圆身上
float x2 = smalx - smallR * (float) Math.cos(Math.toRadians(time));
float y2 = mheight / 2 - smallR * (float) Math.sin(Math.toRadians(time));
if (y2 > mheight / 2 - smallR * 0.8) {
y2 = mheight / 2 - smallR * 0.8f;
x2 = smalx - smallR * (float) (Math.sqrt(1-0.64f));
}
//下面的贝塞尔曲线的第三个点,在小圆身上
float x3 = smalx - smallR * (float) Math.cos(Math.toRadians(time));
float y3 = mheight / 2 + smallR * (float) Math.sin(Math.toRadians(time));
if (y3 < mheight / 2 + smallR * 0.8) {
y3 = mheight / 2 + smallR * 0.8f;
x3 = smalx - smallR * (float) (Math.sqrt(1-0.64f));
}
//下面的贝塞尔曲线的第一个点,在大圆身上
float x4 = bigx + bigR * (float) Math.cos(Math.toRadians(time));
float y4 = mheight / 2 + bigR * (float) Math.sin(Math.toRadians(time));
if (y4 < mheight / 2 + smallR) {
y4 = mheight / 2 + smallR;
x4 = bigx + (float) (Math.sqrt(bigR * bigR - smallR * smallR));
}
path.moveTo(x1, y1);
path.quadTo((bigx + smalx) / 2, mheight / 2, x2, y2);
// 绘制贝赛尔曲线(Path)
path.lineTo(x3, y3);
path.quadTo((bigx + smalx) / 2, mheight / 2, x4, y4);
canvas.drawPath(path, mPaint);
}
//小球在左侧
if (smalx < bigx) {
Path path = new Path();
float x1 = bigx + bigR * (float) Math.cos(Math.toRadians(time));
float y1 = mheight / 2 - bigR * (float) Math.sin(Math.toRadians(time));
if (y1 > mheight / 2 - smallR) {
y1 = mheight / 2 - smallR;
x1 = bigx - (float) (Math.sqrt(bigR * bigR - smallR * smallR));
}
float x2 = smalx - smallR * (float) Math.cos(Math.toRadians(time));
float y2 = mheight / 2 - smallR * (float) Math.sin(Math.toRadians(time));
if (y2 > mheight / 2 - smallR * 0.8) {
y2 = mheight / 2 - smallR * 0.8f;
x2 = smalx + smallR * (float) (Math.sqrt(1-0.64f));
}
float x3 = smalx - smallR * (float) Math.cos(Math.toRadians(time));
float y3 = mheight / 2 + smallR * (float) Math.sin(Math.toRadians(time));
if (y3 < mheight / 2 + smallR * 0.8) {
y3 = mheight / 2 + smallR * 0.8f;
x3 = smalx + smallR * (float) (Math.sqrt(1-0.64f));
}
float x4 = bigx + bigR * (float) Math.cos(Math.toRadians(time));
float y4 = mheight / 2 + bigR * (float) Math.sin(Math.toRadians(time));
if (y4 < mheight / 2 + smallR) {
y4 = mheight / 2 + smallR;
x4 = bigx - (float) (Math.sqrt(bigR * bigR - smallR * smallR));
}
path.moveTo(x1, y1);
path.quadTo((bigx + smalx) / 2, mheight / 2, x2, y2);
// 绘制贝赛尔曲线(Path)
path.lineTo(x3, y3);
path.quadTo((bigx + smalx) / 2, mheight / 2, x4, y4);
canvas.drawPath(path, mPaint);
}
postInvalidate();
}
}
//计算小球的X坐标
private float getSmallCenterX() {
//此处控制速度
time = time + 2.5f;
return mWidth / 2 + distance * (float) Math.cos(Math.toRadians(time));
}
}
“精心”画了一张图,对代码做了说明。
在代码中使用
<?xml version="1.0" encoding="utf-8"?>
<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="@color/white" tools:context="top.greendami.greendami.MainActivity">
<top.greendami.greendami.PPView
android:layout_centerInParent="true"
android:layout_width="400dp"
android:layout_height="80dp" />
</RelativeLayout>
来源:http://www.jianshu.com/p/f7c164288aca


猜你喜欢
- 一、界面部分:首先,打开visual studio新建项目;然后使用“工具箱”添加控件:分别添加button,datagridview,te
- 今天给大家介绍一下如何用Java swing实现五子棋的开发即用Java开发图形界面程序五子棋,代码由于太多,只贴部分,最下面会附上下载地址
- android客户端生成本地验证码主要用来限制用户随意按请求按钮,其实该示例也是来对自定义view的练练手而已,先给出效果图吧其中可定制:*
- 一、settings.xml文件会在两个目录下存在:1、Maven安装目录(全局):%MAVEN_HOME%\conf\settings.x
- 本文实例分析了Android编程中activity的完整生命周期。分享给大家供大家参考,具体如下:android中 activity有自己的
- Spring Boot是什么众所周知 Spring 应用需要进行大量的配置,各种 XML 配置和注解配置让人眼花缭乱,且极容易出错,因此 S
- 依赖 <dependency> <gro
- 本文实例为大家分享了Java使用开源Rxtx实现串口通讯的具体代码,供大家参考,具体内容如下使用方法:windows平台:1、把rxtxPa
- 引言: 在现代的网络应用程序中,进行HTTP请求是一项常见的任务。Apache HttpClient是一个功能强大且广泛使用的Java库,它
- 我们主要介绍一下:java中如何通过最简单的方式实现链式创建json对象,解决创建json代码臃肿的问题。1、假设我们要创建一个json对象
- 一、简介BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。实例化Bean做前置处理、后置处理二、接口定义
- 先看一段代码: private DataSet GetDataSet(string strsql){ string s
- Android手机震动抖动效果的实现(1)布局文件如下<RelativeLayout xmlns:android="http
- 零、动态库 System.Math.dll引入动态库 using System.Math;Math 为通用数学函数、对数函数、三角函数等提供
- 摘要:手把手教你使用 Java AWT 创建一个简易计算器。一、关于AWTAWT (抽象窗口工具包)是一个有助于构建 GUI 的 API (
- 实例如下:#region 自定义变量 int currentCol = -1; bool sort; #
- 网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,
- 意义:由于每个应用进程都有自己的独立进程空间,在android平台上,一个进程通常不能访问另一个进程的内存空间,而我们经常需要夸进程传递对象
- Android 动画实现几种方案在 Android 的 FrameWork 中,为我们提供三种动画的实现方式:逐帧(Frame)动画、视图/
- 在远程调用中,需要把参数和返回值通过网络传输,这个使用