一、前言:由于无法忍受原来ProgressDialog的样子,决定去自定义一个样式,此并非真正意义地自定义新的ProgressDialog。
二、主要思路:
①创建ProgressDialog实例;
②通过Dialog的setContentView(View view)方法,该方法是设置屏幕内容到一个明确的View中,将自定义的布局设置到dialog中。
③通过WindowManager.LayoutParams设置dialog的相关布局参数,不然就会默认显示在中间。这里注意屏幕的适配。
④返回ProgressDialog对象,完成。
三、步骤:
①创建自定义布局(模仿QQ)
下面就是布局的代码(太简单,没什么好讲):
@drawable/loading.png:
②定义style,因为原始的dialog是不透明的,以下为代码:
<style name="myDialogStyle" parent="android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<!-- 是否有边框 -->
<item name="android:windowNoTitle">true</item>
<!-- 是否有标题 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 背景颜色设置为透明 -->
<item name="android:windowIsFloating">true</item>
<!-- 是否是浮动 -->
<item name="android:windowContentOverlay">@null</item>
</style>
在创建ProgressDialog时候,传入Theme即可:
ProgressDialog proDialog = new ProgressDialog(context,R.style.myDialogStyle);//设置主题
③定义进度图片的旋转动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<rotate
android:interpolator="@android:anim/linear_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:duration="1500"
android:pivotX="50%"
android:pivotY="50%"
/>
</set>
④创建类MyProgressDialogUtil,声明一个静态方法createProgressDialog(Context context,String tip)来提供外部创建,在其中加载布局,设置动画,创建ProgressDialog并设置属性,还有就是设置布局参数,需要注意屏幕的适配(用dp勿px)。
代码如下:
public class MyProgressDialogUtil {
private final static int proDialogWidth = 320;//自定义的宽度
private final static int proDialogHeight = 35;//自定义的长度
private final static int marginTop = 20;//自定义的距离父布局的上距离
public static ProgressDialog createProgressDialog(Context context,String tip){
//加载自定义的布局
View view = LayoutInflater.from(context).inflate(R.layout.mydialog_layout,null);
//获取控件实例,并设置
LinearLayout progressLayout = (LinearLayout)view.findViewById(R.id.progressView);
ImageView animImage = (ImageView)view.findViewById(R.id.animProgress);
//进度的360旋转动画
Animation animation = AnimationUtils.loadAnimation(context, R.anim.progress);
animImage.startAnimation(animation);
TextView tvTip = (TextView)view.findViewById(R.id.textTip);
tvTip.setText(tip);
//创建ProgressDialog,设置不可以通过back键或者点击界面来取消
ProgressDialog proDialog = new ProgressDialog(context,R.style.myDialogStyle);//设置主题
proDialog.setCancelable(false);
proDialog.setCanceledOnTouchOutside(false);
proDialog.show();
proDialog.setContentView(progressLayout);
//设置布局参数
WindowManager.LayoutParams params = proDialog.getWindow().getAttributes();
proDialog.getWindow().setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL);
params.width=getScreenWidth(context);
params.height=getScreenHeight(context);
params.y=getMarginTop(context);
proDialog.getWindow().setAttributes(params);
return proDialog;
}
//公式:density=densityDpi/160,px=dp*density
//根据自定义的高(dp)获取px单位的高
////在java中,强制转换符把float转换为int时,是直接丢掉小数部分的,加0.5f起到了四舍五入的作用,可以减小误差。
private static int getScreenHeight(Context context){
final float density=context.getResources().getDisplayMetrics().density;
return (int)(proDialogHeight*density+0.5f);
}
private static int getScreenWidth(Context context){
final float density=context.getResources().getDisplayMetrics().density;
return (int)(proDialogWidth*density+0.5f);
}
private static int getMarginTop(Context context){
final float density=context.getResources().getDisplayMetrics().density;
return (int)(marginTop*density+0.5f);
}
}
⑤获取density的方法可以是以下:
第一种:
WindowManager manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int width = (outMetrics.densityDpi/160)*proDialogWidth;
int height = outMetrics.density*proDialogHeight;
第二种:
float density=context.getResources().getDisplayMetrics().density;
int densityDpi=context.getResources().getDisplayMetrics().densityDpi;
四、遇到的问题:
假如你的show() 在setContentView后调用,就会出现如下问题:
根据字面意思,设置属性必须在加载界面添加之前。
查看源码得知(5.0.0的源码,变化不大应该没有问题):
一直调用下来,知道最后一个show(),所有的设置属性的操作都在其中进行,也就是相当于初始化,所以先调用setContentView()的话,由于还没初始化,所以不允许。个人这么认为,希望大神来指导交流。