打造全局Dialog,Toast,解决Toast多次弹出以及小米无法弹出悬浮窗问题

因为产品的一个小需求,就是防止Toast重复弹出,索性花了点时间将所有的Toast,Dialog弹窗,也就是小菊花全部更改了一下。

注意 为适配6.0 已用全新写法。
详情看:http://blog.csdn.net/a940659387/article/details/52473455
话不多说,上代码。

private static Toast mtoast;
    private static boolean isFirst;
    private static TextView tv_toast;
    public static void showToast(String str) {
        if(!isFirst){
         LayoutInflater inflate = (LayoutInflater)
                 CommonApplication.applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflate.inflate(R.layout.toast_layout, null);
         tv_toast = (TextView) view.findViewById(R.id.message);
         mtoast = new Toast(CommonApplication.applicationContext);
         mtoast.setView(view);
         isFirst = true;
        }
        tv_toast.setText(str);
        mtoast.setDuration(Toast.LENGTH_SHORT);
         mtoast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
         mtoast.show();
        }

    public static void showLongToast(String str) {
        if(!isFirst){
             LayoutInflater inflate = (LayoutInflater)
                     CommonApplication.applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             View view = inflate.inflate(R.layout.toast_layout, null);
             tv_toast = (TextView) view.findViewById(R.id.message);
             mtoast = new Toast(CommonApplication.applicationContext);
             mtoast.setView(view);
             isFirst = true;
            }
            tv_toast.setText(str);
            mtoast.setDuration(Toast.LENGTH_LONG);
             mtoast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
             mtoast.show();
            }
CommonApplication.applicationContext 其实就是自己的Application 在oncreate 方法里赋值下就可以。 不懂如何自己写Application的童鞋请自行google,百度。

以上就是Toast的全局方法,顺便展示下拉个布局,很简单的一个小布局,
上代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content"  
    android:orientation="vertical"  
    android:background="#80000000">  

    <TextView  
        android:id="@+id/message"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:paddingLeft="30dip"
        android:paddingRight="30dip"
        android:paddingTop="8dip"
        android:paddingBottom="8dip"
        android:layout_gravity="center_horizontal"  
        android:textColor="@color/white_low"  
        />  

</LinearLayout>  

背景色感觉透明度80刚刚好,可自行调节。

接下来就是蛋疼的Dialog了,本来想仿照toast直接用个ApplicationContext,发现蛋疼的崩溃,原因居然是Dialog要依赖于一个上下文,ApplicationContext找不到依赖的上下文,大致就是这么个意思,有错误请联系我,谢谢。

根据一些大牛们的想法,发现只能写在service里 ,没办法 ,写吧 。 参考环信的异地登录的方式 在service实现一个接口,在工具类中调用接口的方法从而达到全局Dialog(菊花)的效果;

上service代码

public class CommonDialogService extends Service implements CommonDialogListener{

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    /**this is TV*/
    private static TextView tv;
    private static Dialog dialog;
    /**判断是否已经new Dialog*/
    private static boolean isFirst;
    private void showDialog(int iscancle){
        if(!isFirst){
        dialog = new Dialog(this, R.style.MyDialogStyle);
        View view = LayoutInflater.from(this).inflate(R.layout.progressbar_item,
                null);
        dialog.setContentView(view);
        tv = (TextView) view.findViewById(R.id.mylaodint_text_id);
        ImageView progressImageView = (ImageView) view
                .findViewById(R.id.myloading_image_id);
        AnimationDrawable animationDrawable = (AnimationDrawable) progressImageView
                .getDrawable();
        animationDrawable.start();
        android.view.WindowManager.LayoutParams lp = dialog.getWindow()
                .getAttributes();
        lp.width = ConstantsYiBaiSong.WinWidth/ 3;
        lp.height = LayoutParams.WRAP_CONTENT;
        dialog.getWindow().setAttributes(lp);
        dialog.getWindow()
            .setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        }
        if(iscancle==1){
            dialog.setCanceledOnTouchOutside(true);
        }else{
            dialog.setCanceledOnTouchOutside(false);
        }
        if(!dialog.isShowing()){
            dialog.show();
        }
    }

    public void onCreate() {
        /**this将此service与工具类绑定*/
        ToastUtils.getInstanse().setListener(this);
    }


    /**showDialog*/
    @Override
    public void show() {
        showDialog(1);
        dialog.setCancelable(true);
    }

    /**cancleDialog*/
    @Override
    public void cancle() {
        if(dialog.isShowing()){
            dialog.cancel();
            dialog.setCancelable(true);
        }
    }

    /**show have custom Text dialog*/
    @Override
    public void showstr(String str) {
        showDialog(1);
        dialog.setCancelable(true);
        tv.setText(str);
    }

    /**show uncancle's dialog */
    @Override
    public void showunCancle() {
        showDialog(2);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setCancelable(false);
    }

    @Override
    public void setStr(String str) {
        if(dialog.isShowing()){
            tv.setText(str+"");
        }
    };

}

不要忘了注册service 在manifest里

<service android:name="*.*.*.CommonDialogService"></service>

请忽略上面的*。
对了要在service里弹出dialog 必须要在show之前加上一句话
dialog.getWindow()
.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

小米这个默认是禁止的 可以将 TYPR_SYSTE_ALERT改为TYPE_TOAST 即可。

不过个人认为做这个操作的时候最好加个判断机型是否为小米。个人预感这个方法很快将被禁用。搞不好会跟最初的home监听,加上就会崩溃。

要不就会报错。
还要在manifest里加这么一个权限。

大致的意思能就是让弹框在系统层。
这样做的缺陷就是如果你网络不好,你按下home键那个小菊花(Dialog)还会在那里转啊转,转啊转。有问题就会有解决的办法,接着往下看,。

接下来是接口
public interface CommonDialogListener {

    void show();
    void cancle();
    void showstr(String str);
    void showunCancle();
    void setStr(String str);

}

最后是工具类。为了省事直接上全部代码。

public class ToastUtils {
    private static final String TAG = "ToastUtils";
    private static CommonDialogListener mListener;
    private static ToastUtils toast = null;
    private ToastUtils(){

    }

    public void setListener( CommonDialogListener listener){
        this.mListener =listener;
    }

    public synchronized static ToastUtils getInstanse(){
        if(toast ==null){
            toast = new ToastUtils();
        }
        return toast;
    }


    public static void showstrToastAlong(String str){
        mListener.showstr(str);
    };

    public static void showToastAlong(){
        mListener.show();
    }





    public static void cancel() {
        mListener.cancle();

    }

//  public void showToastAlong() {
//      // final ProgressDialog progressDialog = mProgress.get();
//      // if (progressDialog == null)
//      // return;
//      // progressDialog.show();
//      if (progress != null) {
//          if ("".equals(str)) {
//              progress.show();
//          } else {
//              progress.showstr(str);
//          }
//      } else {
//          return;
//      }
//  }


    /***
     * 
     * 方法说明:进度显示
     *
     * @param str
     */
    public static void setStr(String str){
        mListener.setStr(str);
    }

    /***
     * 
     * 方法说明:不可点击的Show
     *
     */
    public static void showunclickToastAlong() {
        // final ProgressDialog progressDialog = mProgress.get();
        // if (progressDialog == null)
        // return;
        // progressDialog.show();
        mListener.showunCancle();
    }

//  public void showToastAlong(long delay) {
//      showToastAlong();
//      Timer timer = new Timer();
//      TimerTask task = new TimerTask() {
//          @Override
//          public void run() {
//ToastUtils.cancel();
//          }
//      };
//      timer.schedule(task, delay);
//  }

    private static String prestr;
    private static Context  preContext;
    private static Toast mtoast;
    private static boolean isFirst;
    private static TextView tv_toast;
    public static void showToast(String str) {
        if(!isFirst){
         LayoutInflater inflate = (LayoutInflater)
                 CommonApplication.applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflate.inflate(R.layout.toast_layout, null);
         tv_toast = (TextView) view.findViewById(R.id.message);
         mtoast = new Toast(CommonApplication.applicationContext);
         mtoast.setView(view);
         isFirst = true;
        }
        tv_toast.setText(str);
        mtoast.setDuration(Toast.LENGTH_SHORT);
         mtoast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
         mtoast.show();
        }

    public static void showLongToast(String str) {
        if(!isFirst){
             LayoutInflater inflate = (LayoutInflater)
                     CommonApplication.applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             View view = inflate.inflate(R.layout.toast_layout, null);
             tv_toast = (TextView) view.findViewById(R.id.message);
             mtoast = new Toast(CommonApplication.applicationContext);
             mtoast.setView(view);
             isFirst = true;
            }
            tv_toast.setText(str);
            mtoast.setDuration(Toast.LENGTH_LONG);
             mtoast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
             mtoast.show();
            }

//  public void cancelDiaog(boolean cancel){
//      if(progress!=null){
//      progress.cancelKey(cancel);
//      }
//      progress=null;
//      str="";
//      
//  }
}

现在来解决那个小菊花在系统层转啊转,转啊转的问题。最好不要监听单个Activity的返回事件。原因自然是因为你是全局的么,每个都写,累不死你。
解决办法就是广播。当然也是从别的大牛辣边借鉴过来的。
上代码

public class HomeWatcherReceiver extends BroadcastReceiver {
    private static final String LOG_TAG = "HomeReceiver";
    private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
    private static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    private static final String SYSTEM_DIALOG_REASON_LOCK = "lock";
    private static final String SYSTEM_DIALOG_REASON_ASSIST = "assist";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
//      Log.i(LOG_TAG, "onReceive: action: " + action);
        if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
            // android.intent.action.CLOSE_SYSTEM_DIALOGS
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
//          Log.i(LOG_TAG, "reason: " + reason);

            if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
                ToastUtils.cancel();

            } else if (SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) {
                // 长按Home键 或者 activity切换键
                ToastUtils.cancel();

            } else if (SYSTEM_DIALOG_REASON_LOCK.equals(reason)) {
                // 锁屏
                ToastUtils.cancel();
            } else if (SYSTEM_DIALOG_REASON_ASSIST.equals(reason)) {
                // samsung 长按Home键
                ToastUtils.cancel();
            }

        }
    }
}

然后就是广播的注册了。这里推荐用动态注册,为啥子,因为我静态测试不起作用,我也不知道为啥子。谁知道了可以告诉我一下下。

记得最后销毁的时候将service和广播销毁和解绑。算了 顺便把绑定,解绑代码粘贴下吧。

//绑定
IntentFilter filter  = new        IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        this.registerReceiver(mHomeWatchReceiver, filter);
        //Service
        dialogservice= new Intent(this, CommonDialogService.class);
        startService(dialogservice);


@Override
    protected void onDestroy() {
        super.onDestroy();
        this.stopService(dialogservice);
        unregisterReceiver(mHomeWatchReceiver);
    }


上几张图片。
这里写图片描述
小菊花转啊转。

大功告成,转载请标明出处。谢谢。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫的于

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值