Android自定义等待对话框

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

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

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

<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

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

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

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

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(); } } }

对话框的布局:

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

对话框的样式:

<!-- 自定义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

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); } }

效果图;

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

时间: 2024-07-30 22:53:20

Android自定义等待对话框的相关文章

Android自定义等待对话框_Android

最近,看了好多的APP的等待对话框,发现自己的太lower,于是就研究了一番,最后经过苦心努力,实现一个. 自定义一个LoadingIndicatorView(extends View )类 编写values/attrs.xml,在其中编写styleable和item等标签元素 在布局文件中LoadingIndicatorView使用自定义的属性(注意namespace) 在LoadingIndicatorView的构造方法中通过TypedArray获取 描述就提供这些,一下是代码的展示,非常的

Android 自定义AlertDialog对话框样式

实际的项目开发当中,经常需要根据实际的需求来自定义AlertDialog.最近在开发一个WIFI连接的功能,点击WIFI需要弹出自定义密码输入框.在此权当记录 效果图 点击首页的Button即跳出对话框,显示WIFI信息(TextView),密码输入框(EditText),取消和连接按钮(Button) 实现 根据自己实际的需求,为AlertDialog创建一个布局,在此我需要定义一个如图所示的WIFI密码输入框,故在 res/layout 目录下建立一个 dialog_layout.xml 文

android自定义AlertDialog对话框

前面一篇文章http://www.jb51.net/article/103036.htm介绍了alertDialog的四种简单使用,但是有些时候为了让整个app的风格统一,或者说前面的四种形式不符合项目中的需求,这个时候就需要我们自定义alertDialog了.直接上代码 CustomAlertDialog: import android.app.Dialog; import android.content.Context; import android.os.Bundle; import an

Android如何自定义升级对话框示例详解

前言 本文主要给大家介绍了关于Android自定义升级对话框的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现的效果如下所示 其实这也只是一个DialogFragment 而已,重点只是在于界面的设计 想要使用做出这样一个DialogFragment ,需要自定义一个View,然后将该View传入到该Dialog中 先定义布局,一个TextView用于标题,一个TextView用于升级内容阐述,一个ImageView,一个确认升级的按钮 <?xml version

Android 自定义对话框 showSetPwdDialog_Android

样式如下所示: 布局: layout dialog_set_pwd.xml <?xml version="." encoding="utf-"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height=&

Android对话框自定义标题 对话框标题美化操作_Android

Android自带的对话框标题不好看,如果我们需要给弹出的对话框设置一个自己定义的标题,可以使用AlertDialog.Builder的setCustomTitle()方法.  定义一个对话框标题的title.xml文件:  <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andro

Android 自定义对话框 showSetPwdDialog

样式如下所示: 布局: layout dialog_set_pwd.xml <?xml version="." encoding="utf-"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height=&

Android 自定义弹出对话框界面详解

在安卓开发中,时常遇到要弹窗提醒的情况.而系统自带的弹出对话框由不是很美观,可以通过自己继承对话框类(Dialog),并设置自定义的布局文件,来达到美化弹出式对话框的目的. 首先是自定义一个对话框类,继承自Dialog,然后再构造函数中传入对话框显示内容.按钮响应函数等参数:  代码如下 复制代码 public UserDefinedDialog(Context context, String message,                          View.OnClickListe

Android 自定义Dialog 实例_Android

开发中经常需要请求网络获取数据,我们在请求网络到得到数据时当中需要等待一些时间,为了增加用户体验,我们一般会用一个Dialog来提示用户我们在加载网络数据. 今天我们来实现如下效果的加载中Dialog.   从图中我们可以看到要这个Dialog是图片还有文字组成的,(不过我这里使用代码实现的,没有用图片),以下是这个加载图形的代码: public class LVCircularRing extends View { private float mWidth = 0f; private floa