因为产品的一个小需求,就是防止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);
}
上几张图片。
小菊花转啊转。
大功告成,转载请标明出处。谢谢。