自定义ProgressDialog的姿势(模仿QQ登录加载dialog)

一、前言:由于无法忍受原来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()的话,由于还没初始化,所以不允许。个人这么认为,希望大神来指导交流。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值