服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android自定义等待对话框

Android自定义等待对话框

2021-06-22 15:18Android开发网 Android

这篇文章主要为大家详细介绍了Android自定义等待对话框的实现方法,感兴趣的小伙伴们可以参考一下

最近,看了好多的app的等待对话框,发现自己的太lower,于是就研究了一番,最后经过苦心努力,实现一个。

  • 自定义一个loadingindicatorview(extends view )类
  • 编写values/attrs.xml,在其中编写styleable和item等标签元素
  • 在布局文件中loadingindicatorview使用自定义的属性(注意namespace)
  • 在loadingindicatorview的构造方法中通过typedarray获取

描述就提供这些,一下是代码的展示,非常的详细。
1、自定义属性的声明文件

?
1
2
3
4
5
6
7
8
9
<declare-styleable name="avloadingindicatorview">
    <attr name="indicator">
      <flag name="ballspinfadeloader" value="22"/>
    </attr>
    <attr name="indicator_color" format="color"/>
  </declare-styleable>
 
 
<pre name="code" class="html">

loadingindicatorview.java 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import android.annotation.targetapi;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.os.build;
import android.support.annotation.intdef;
import android.util.attributeset;
import android.view.view;
 
import com.chni.lidong.androidtestdemo.r;
 
 
/**
 * created by lidongon 2016/1/31
 *
 .ballspinfadeloader,
 *
 */
public class loadingindicatorview extends view {
 
 
  //indicators 指示器
  public static final int ballspinfadeloader=22;
 
  @intdef(flag = true,
      value = {
          ballspinfadeloader,
      })
  public @interface indicator{}
 
  //sizes (with defaults in dp)
  public static final int default_size=45;
 
  //attrs
  int mindicatorid;
  int mindicatorcolor;
 
  paint mpaint;
 
  baseindicatorcontroller mindicatorcontroller;
 
  private boolean mhasanimation;
 
 
  public loadingindicatorview(context context) {
    super(context);
    init(null, 0);
  }
 
  public loadingindicatorview(context context, attributeset attrs) {
    super(context, attrs);
    init(attrs, 0);
  }
 
  public loadingindicatorview(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
    init(attrs, defstyleattr);
  }
 
 
  @targetapi(build.version_codes.lollipop)
  public loadingindicatorview(context context, attributeset attrs, int defstyleattr, int defstyleres) {
    super(context, attrs, defstyleattr, defstyleres);
    init(attrs, defstyleattr);
  }
 
  private void init(attributeset attrs, int defstyle) {
    /**
     *获取typedarray(属性的集合)
     */
    typedarray a = getcontext().obtainstyledattributes(attrs, r.styleable.avloadingindicatorview);
    mindicatorid=a.getint(r.styleable.avloadingindicatorview_indicator, ballspinfadeloader);//获取编号属性
    mindicatorcolor=a.getcolor(r.styleable.avloadingindicatorview_indicator_color, color.white);//获取颜色属性
    a.recycle();//回收属性的集合
    mpaint=new paint();
    mpaint.setcolor(mindicatorcolor);//设置画笔的颜色
    mpaint.setstyle(paint.style.fill);//设置画笔的样式为填充
    mpaint.setantialias(true);//去锯齿
    applyindicator();//
  }
 
  private void applyindicator(){
    switch (mindicatorid){
      case ballspinfadeloader:
        mindicatorcontroller=new ballspinfadeloaderindicator();
        break;
    }
    mindicatorcontroller.settarget(this);//将控件设置到当前view
  }
 
  @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    int width = measuredimension(dp2px(default_size), widthmeasurespec);//获取view的宽度
    int height = measuredimension(dp2px(default_size), heightmeasurespec);//获取view的高度
    setmeasureddimension(width, height);//
  }
 
  /**
   *测量的 维度
   * @param defaultsize 默认大小
   * @param measurespec {@see widthmeasurespec,heightmeasurespec}
   * @return 返回测量的结果
   */
  private int measuredimension(int defaultsize,int measurespec){
    int result = defaultsize;
    int specmode = measurespec.getmode(measurespec);//测量规范
    int specsize = measurespec.getsize(measurespec);//测量大小
    if (specmode == measurespec.exactly) {//父控件已经为子控件设置确定的大小,子控件会考虑父控件给他的大小,自己需要多大设置多大
      result = specsize;
    } else if (specmode == measurespec.at_most) {//子控件可以设置自己希望的指定大小
      result = math.min(defaultsize, specsize);//取最小值
    } else {
      result = defaultsize;
    }
    return result;
  }
 
  @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    drawindicator(canvas);
  }
 
  @override
  protected void onlayout(boolean changed, int left, int top, int right, int bottom) {
    super.onlayout(changed, left, top, right, bottom);
    if (!mhasanimation){
      mhasanimation=true;
      applyanimation();
    }
  }
 
  void drawindicator(canvas canvas){
    mindicatorcontroller.draw(canvas,mpaint);
  }
 
  void applyanimation(){
    mindicatorcontroller.createanimation();
  }
 
  private int dp2px(int dpvalue) {
    return (int) getcontext().getresources().getdisplaymetrics().density * dpvalue;
  }

baseindicatorcontroller.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.chni.lidong.androidtestdemo.loading;
 
import android.graphics.canvas;
import android.graphics.paint;
import android.view.view;
 
/**
 * created by lidongon 2016/1/31
 */
public abstract class baseindicatorcontroller {
 
  private view mtarget;
 
 
  public void settarget(view target){
    this.mtarget=target;
  }
 
  public view gettarget(){
    return mtarget;
  }
 
  /**
   * 得到view的宽度
   * @return
   */
  public int getwidth(){
    return mtarget.getwidth();
  }
 
  /**
   * 得到view的高度
   * @return
   */
  public int getheight(){
    return mtarget.getheight();
  }
 
  /**
   * 刷新view
   */
  public void postinvalidate(){
    mtarget.postinvalidate();
  }
 
  /**
   * draw indicator what ever
   * you want to draw
   * 绘制indicate
   * @param canvas
   * @param paint
   */
  public abstract void draw(canvas canvas,paint paint);
 
  /**
   * create animation or animations
   * ,and add to your indicator.
   * 创建动画或者动画集合,添加到indcator
   */
  public abstract void createanimation();
 
 
}

 ballspinfadeloaderindicator.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.chni.lidong.androidtestdemo.loading;
 
import android.graphics.canvas;
import android.graphics.paint;
 
import com.nineoldandroids.animation.valueanimator;
 
/**
 * created by lidongon 2016/1/31
 */
public class ballspinfadeloaderindicator extends baseindicatorcontroller {
 
  public static final float scale=1.0f;
 
  public static final int alpha=255;
  /**
   * 圆点的比例
   */
  float[] scalefloats=new float[]{scale,
      scale,
      scale,
      scale,
      scale,
      scale,
      scale,
      scale};
  /**
   * 圆点的透明度集合
   */
  int[] alphas=new int[]{alpha,
      alpha,
      alpha,
      alpha,
      alpha,
      alpha,
      alpha,
      alpha};
 
 
  @override
  public void draw(canvas canvas, paint paint) {
    float radius=getwidth()/10;
    for (int i = 0; i < 8; i++) {
      canvas.save();
      point point=circleat(getwidth(),getheight(),getwidth()/2-radius,i*(math.pi/4));
      canvas.translate(point.x,point.y);
      canvas.scale(scalefloats[i],scalefloats[i]);
      paint.setalpha(alphas[i]);
      canvas.drawcircle(0,0,radius,paint);
      canvas.restore();
    }
  }
 
  /**
   * 圆o的圆心为(a,b),半径为r,点a与到x轴的为角α.
   *则点a的坐标为(a+r*cosα,b+r*sinα)
   * @param width
   * @param height
   * @param radius
   * @param angle
   * @return
   */
  point circleat(int width,int height,float radius,double angle){
    float x= (float) (width/2+radius*(math.cos(angle)));
    float y= (float) (height/2+radius*(math.sin(angle)));
    return new point(x,y);
  }
 
  @override
  public void createanimation() {
    int[] delays= {0, 120, 240, 360, 480, 600, 720, 780, 840};
    for (int i = 0; i < 8; i++) {
      final int index=i;
      valueanimator scaleanim=valueanimator.offloat(1,0.4f,1);//创建valueanimator对象
      scaleanim.setduration(1000);//设置动画的持续时间
      scaleanim.setrepeatcount(-1);//设置动画是否重复
      scaleanim.setstartdelay(delays[i]);//延迟启动动画
      scaleanim.addupdatelistener(new valueanimator.animatorupdatelistener() {//valueanimator只负责第一次的内容,因此必须通过监听来实现对象的相关属性的更新
        @override
        public void onanimationupdate(valueanimator animation) {
          scalefloats[index] = (float) animation.getanimatedvalue();//获取当前帧的值
          postinvalidate();
        }
      });
      scaleanim.start();//启动属性动画
 
      valueanimator alphaanim=valueanimator.ofint(255, 77, 255);//透明度动画
      alphaanim.setduration(1000);//
      alphaanim.setrepeatcount(-1);
      alphaanim.setstartdelay(delays[i]);
      alphaanim.addupdatelistener(new valueanimator.animatorupdatelistener() {
        @override
        public void onanimationupdate(valueanimator animation) {
          alphas[index] = (int) animation.getanimatedvalue();
          postinvalidate();
        }
      });
      alphaanim.start();
    }
  }
 
  final class point{
    public float x;
    public float y;
 
    public point(float x, float y){
      this.x=x;
      this.y=y;
    }
  }
 
 
}

uihelp.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.chni.lidong.androidtestdemo.utils;
 
import android.app.activity;
import android.app.dialog;
import android.view.layoutinflater;
import android.view.view;
import android.widget.linearlayout;
import android.widget.textview;
 
import com.chni.lidong.androidtestdemo.r;
 
/**
 * 对话框的实现
 * @author 李东
 * @date 2014-11-23
 */
public class uihelper {
   
  /** 加载数据对话框 */
  private static dialog mloadingdialog;
   
   
  /**
   * 显示加载对话框
   * @param context 上下文
   * @param msg 对话框显示内容
   * @param cancelable 对话框是否可以取消
   */
  public static void showdialogforloading(activity context, string msg, boolean cancelable) {
    view view = layoutinflater.from(context).inflate(r.layout.layout_loading_dialog, null);
    textview loadingtext = (textview)view.findviewbyid(r.id.id_tv_loading_dialog_text);
    loadingtext.settext(msg);
     
    mloadingdialog = new dialog(context, r.style.loading_dialog_style);
    mloadingdialog.setcancelable(cancelable);
    mloadingdialog.setcontentview(view, new linearlayout.layoutparams(linearlayout.layoutparams.match_parent, linearlayout.layoutparams.match_parent));
    mloadingdialog.show();   
  }
   
  /**
   * 关闭加载对话框
   */
  public static void hidedialogforloading() {
    if(mloadingdialog != null && mloadingdialog.isshowing()) {
      mloadingdialog.cancel();
    }
  }
 
}

对话框的布局:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:background="@drawable/bg_loading_dialog_shape"
  android:gravity="center"
  android:minheight="60dp"
  android:minwidth="180dp"
  android:orientation="vertical"
  android:padding="@dimen/padding_10" >
 
  <linearlayout
    android:layout_width="wrap_content"
    android:layout_weight="1"
    android:gravity="center"
    android:layout_height="wrap_content">
 
    <com.chni.lidong.androidtestdemo.loading.avloadingindicatorview
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:indicator="ballspinfadeloader"
      app:indicator_color="@color/green"
      />
 
  </linearlayout>
 
  <textview
    android:id="@+id/id_tv_loading_dialog_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margintop="@dimen/padding_5"
    android:text="正在登录…"
    android:textcolor="@color/content"
    android:textsize="14sp" />
 
</linearlayout>

对话框的样式:

?
1
2
3
4
5
6
7
8
<!-- 自定义loading dialog -->
<style name="loading_dialog_style" parent="@android:style/theme.dialog">
  <item name="android:windowframe">@null</item>
  <item name="android:windownotitle">true</item>
  <item name="android:windowbackground">@color/transparent</item>
  <item name="android:windowisfloating">true</item>
  <item name="android:windowcontentoverlay">@null</item>
</style>

mainactivity.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class main7activity extends appcompatactivity {
 
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main7);
    toolbar toolbar = (toolbar) findviewbyid(r.id.toolbar);
    setsupportactionbar(toolbar);
 
    floatingactionbutton fab = (floatingactionbutton) findviewbyid(r.id.fab);
    fab.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view view) {
        snackbar.make(view, "replace with your own action", snackbar.length_long)
            .setaction("action", null).show();
      }
    });
    uihelper.showdialogforloading(this, "正在加载...", true);
    handler handler = new handler();
    handler.postdelayed(new runnable() {
      @override
      public void run() {
        uihelper.hidedialogforloading();
      }
    },10000);
  }
 
}

效果图;

Android自定义等待对话框

以上就是本文的全部内容,希望对大家的学习有所帮助。

延伸 · 阅读

精彩推荐
  • AndroidAndroid CardView+ViewPager实现ViewPager翻页动画的方法

    Android CardView+ViewPager实现ViewPager翻页动画的方法

    本篇文章主要介绍了Android CardView+ViewPager实现ViewPager翻页动画的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Abby代黎明9602022-03-02
  • AndroidAndroid中AsyncTask详细介绍

    Android中AsyncTask详细介绍

    这篇文章主要介绍了Android中AsyncTask详细介绍,AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合,需要的朋友可以参考下...

    Android开发网7452021-03-11
  • AndroidAndroid程序设计之AIDL实例详解

    Android程序设计之AIDL实例详解

    这篇文章主要介绍了Android程序设计的AIDL,以一个完整实例的形式较为详细的讲述了AIDL的原理及实现方法,需要的朋友可以参考下...

    Android开发网4642021-03-09
  • AndroidAndroid实现Service获取当前位置(GPS+基站)的方法

    Android实现Service获取当前位置(GPS+基站)的方法

    这篇文章主要介绍了Android实现Service获取当前位置(GPS+基站)的方法,较为详细的分析了Service基于GPS位置的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    Ruthless8342021-03-31
  • AndroidAndroid界面效果UI开发资料汇总(附资料包)

    Android界面效果UI开发资料汇总(附资料包)

    android ui界面设计,友好的界面会提高用户体验度;同时也增强了android ui界面设计的难度,本文提供了一些常用开发资料(有下载哦)感兴趣的朋友可以了解下...

    Android开发网4672021-01-03
  • AndroidAndroid编程解析XML方法详解(SAX,DOM与PULL)

    Android编程解析XML方法详解(SAX,DOM与PULL)

    这篇文章主要介绍了Android编程解析XML方法,结合实例形式详细分析了Android解析XML文件的常用方法与相关实现技巧,需要的朋友可以参考下...

    liuhe68810052021-05-03
  • AndroidAndroid实现固定屏幕显示的方法

    Android实现固定屏幕显示的方法

    这篇文章主要介绍了Android实现固定屏幕显示的方法,实例分析了Android屏幕固定显示所涉及的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    鉴客6192021-03-27
  • Android汇总Android视频录制中常见问题

    汇总Android视频录制中常见问题

    这篇文章主要汇总了Android视频录制中常见问题,帮助大家更好地解决Android视频录制中常见的问题,需要的朋友可以参考下...

    yh_thu5192021-04-28