软件编程
位置:首页>> 软件编程>> Android编程>> Android实现一个带粘连效果的LoadingBar

Android实现一个带粘连效果的LoadingBar

作者:Greenda米  发布时间:2023-04-26 11:47:41 

标签:android,loadingbar,粘连效果

前言

我们平时在开发的时候,发起网络请求前,会需要显示一个Loading,一般的做法都是在xml布局上添加好Loading,然后在Activity中,setVisibility来控制Loading的显示和隐藏,这样使用起来就很不方便,因为每一个xml都得引入一个Loading布局。

而LoadingBar就更好的解决了这个问题

最近设计师在外国的一个网站上挑了一个Loading的效果图,尝试实现之后,虽然和原图有点不太一样,但是效果还是不错的。难点就是粘连效果的实现,贝塞尔曲线的点点们简直要把我折磨死了。

先上效果图:

Android实现一个带粘连效果的LoadingBar

实例代码

然后是源码,就是一个简单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));
}
}

“精心”画了一张图,对代码做了说明。

Android实现一个带粘连效果的LoadingBar

在代码中使用


<?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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com