这个属于页面打开时的延迟加载效果,总的来说比较好用,网络太卡的时候也不至于没办法进行操作,当然也存在没有加载完成而产生的误操作可能性,具体还是要看项目的需要。
公共类:
public class CustomProgressDialog extends Dialog {
private Context context = null;
private static CustomProgressDialog customProgressDialog = null;
public CustomProgressDialog(Context context){
super(context);
this.context = context;
}
public CustomProgressDialog(Context context, int theme) {
super(context, theme);
}
public static CustomProgressDialog createDialog(Context context){
customProgressDialog = new CustomProgressDialog(context, R.style.CustomProgressDialog);
customProgressDialog.setContentView(R.layout.customprogressdialog);
customProgressDialog.getWindow().getAttributes().gravity = Gravity.CENTER;
return customProgressDialog;
}
public void onWindowFocusChanged(boolean hasFocus){
if (customProgressDialog == null){
return;
}
// ImageView imageView = (ImageView) customProgressDialog.findViewById(R.id.loadingImageView);
// AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getBackground();
// animationDrawable.start();
}
/**
*
* [Summary]
* setTitile 标题
* @param strTitle
* @return
*
*/
public CustomProgressDialog setTitile(String strTitle){
return customProgressDialog;
}
/**
*
* [Summary]
* setMessage 提示内容
* @param strMessage
* @return
*
*/
public CustomProgressDialog setMessage(String strMessage){
TextView tvMsg = (TextView)customProgressDialog.findViewById(R.id.id_tv_loadingmsg);
if (tvMsg != null){
tvMsg.setText(strMessage);
}
return customProgressDialog;
}
}
布局文件xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.meikuang.landongjiguang.renyuandingwei.PublicClass.WindowsLoad
android:id="@+id/windows_load"
android:layout_width="80dp"
android:layout_height="80dp" />
<ImageView
android:id="@+id/loadingImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
<TextView
android:id="@+id/id_tv_loadingmsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="20sp"/>
</LinearLayout>
加载动画文件:
public class WindowsLoad extends View {
private float pi = (float) Math.PI;
private String TAG = "WindowsLoad";
private Paint paint;
private int R;
private float circleR;
private ValueAnimator circleAnimator1;
private ValueAnimator circleAnimator2;
private ValueAnimator circleAnimator3;
private boolean init = true;
float x1, x2, x3, y1, y2, y3;
public WindowsLoad(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.parseColor("#ffffff"));
R = 10;
}
float[] circleCentre;
float[] start1;
float[] start2;
float[] start3;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//初始化
if (init) {
circleCentre = new float[]{getWidth() / 2, getHeight() / 2};
start1 = new float[]{getWidth() / 2, R};
start2 = onCiecleCoordinate(-0.5f, start1, circleCentre);
start3 = onCiecleCoordinate(-0.5f, start2, circleCentre);
init = false;
loading();
}
// canvas.drawCircle(start1[0], start1[1], R, paint);
// Log.d(TAG, "onDraw() returned: "+ start1[0]+" "+start1[1] +" "+ start2[0]+" "+start2[1]);
//第一个点初始位置
if (!circleAnimator1.isRunning()) {
canvas.drawCircle(start1[0], start1[1], R, paint);
}
//第二个点初始位置
if (!circleAnimator2.isRunning()) {
canvas.drawCircle(start2[0], start2[1], R, paint);
}
//第三个点初始位置
if (!circleAnimator3.isRunning()) {
canvas.drawCircle(start3[0], start3[1], R, paint);
}
if (circleAnimator1.isRunning()) {
x1 = (float) (circleCentre[0] + circleR * Math.cos((float) circleAnimator1.getAnimatedValue()));
y1 = (float) (circleCentre[1] + circleR * Math.sin((float) circleAnimator1.getAnimatedValue()));
canvas.drawCircle(x1, y1, R, paint);
}
if (circleAnimator2.isRunning()) {
x2 = (float) (circleCentre[0] + circleR * Math.cos((float) circleAnimator2.getAnimatedValue()));
y2 = (float) (circleCentre[1] + circleR * Math.sin((float) circleAnimator2.getAnimatedValue()));
canvas.drawCircle(x2, y2, R, paint);
}
if (circleAnimator3.isRunning()) {
x3 = (float) (circleCentre[0] + circleR * Math.cos((float) circleAnimator3.getAnimatedValue()));
y3 = (float) (circleCentre[1] + circleR * Math.sin((float) circleAnimator3.getAnimatedValue()));
canvas.drawCircle(x3, y3, R, paint);
}
if (circleAnimator1.isRunning() || circleAnimator2.isRunning() || circleAnimator3.isRunning()) {
invalidate();
}
}
private void loading() {
circleAnimator1 = getCircleData(start1, circleCentre, 0);
circleAnimator1.start();
circleAnimator2 = getCircleData(start2, circleCentre, 300);
circleAnimator2.start();
circleAnimator3 = getCircleData(start3, circleCentre, 600);
circleAnimator3.start();
postDelayed(new Runnable() {
@Override
public void run() {
loading();
invalidate();
}
}, circleAnimator3.getDuration() + 600);
}
private SlowToQuick slowToQuick = new SlowToQuick();
private ValueAnimator getCircleData(float[] startCoordinate, float[] RCoordinate, int delay) {
float x1 = startCoordinate[0];
float y1 = startCoordinate[1];
float x0 = RCoordinate[0];
float y0 = RCoordinate[1];
// Log.i(TAG, "getCircleData x y: " + x1+" ,"+y1+" x0 "+x0+ " y0 "+y0);
circleR = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
float param = (float) (Math.abs(y1 - y0) / circleR);
if (param < -1.0) {
param = -1.0f;
} else if (param > 1.0) {
param = 1.0f;
}
float a = (float) Math.asin(param);
if (x1 >= x0 && y1 >= y0) {
a = a;
} else if (x1 < x0 && y1 >= y0) {
a = pi - a;
} else if (x1 < x0 && y1 < y0) {
a = a + pi;
} else {
a = 2 * pi - a;
}
ValueAnimator circleAnimator = ValueAnimator.ofFloat(a, a + 2 * pi);
circleAnimator.setDuration(1500);
circleAnimator.setInterpolator(slowToQuick);
circleAnimator.setStartDelay(delay);
return circleAnimator;
}
//获取同一个圆上,间隔固定角度的点座标
private float[] onCiecleCoordinate(float angle, float[] start, float[] center) {
float x1 = start[0];
float y1 = start[1];
float x0 = center[0];
float y0 = center[1];
float R = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
float param = (float) (Math.abs(y1 - y0) / R);
if (param < -1.0) {
param = -1.0f;
} else if (param > 1.0) {
param = 1.0f;
}
float a = (float) Math.asin(param);
if (x1 >= x0 && y1 >= y0) {
a = a;
} else if (x1 < x0 && y1 >= y0) {
a = pi - a;
} else if (x1 < x0 && y1 < y0) {
a = a + pi;
} else {
a = 2 * pi - a;
}
float x = (float) (center[0] + R * Math.cos(a + angle));
float y = (float) (center[1] + R * Math.sin(a + angle));
return new float[]{x, y};
}
class SlowToQuick implements Interpolator {
@Override
public float getInterpolation(float input) {
return input * input;
}
}
}
然后再在styles.xml文件中添加以下代码:
<style name="CustomDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>
<style name="CustomProgressDialog" parent="@style/CustomDialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
</style>
作为对Dialog的配置。
用法:
首先定义:
private CustomProgressDialog progressDialog = null;//加载页
然后在开始加载页面的地方写入代码:
//加载页添加
if (progressDialog == null){
progressDialog = CustomProgressDialog.createDialog(getActivity());
}
progressDialog.show();
最后在结束加载地方写入代码:
//关闭加载页
if (progressDialog != null){
progressDialog.dismiss();
progressDialog = null;
}
这样就可以实现加载页面效果。
P.S:动画可以进行各种替换,但是如果对加载页面没有特别的特殊要求最好尽量使用代码生成的动画,不要使用图片帧动画式,一来手机可能会卡顿(毕竟在加载状态下,原本各个进程就被占用了),二来不容易适配(毕竟手机的分辨率不一样,就不再需要美工挨个画)。