diff --git a/Toastlib/src/main/java/com/android/toastlib/ToastUtils.java b/Toastlib/src/main/java/com/android/toastlib/ToastUtils.java index 868f2b1..f5b291f 100644 --- a/Toastlib/src/main/java/com/android/toastlib/ToastUtils.java +++ b/Toastlib/src/main/java/com/android/toastlib/ToastUtils.java @@ -4,27 +4,39 @@ import android.os.Build; import android.util.Log; +import com.android.toastlib.toast.ActivityCustomizeToast; import com.android.toastlib.toast.ActivityToast; import com.android.toastlib.toast.IToast; import com.android.toastlib.toast.SystemToast; +import com.android.toastlib.toast.TopCustomizeToast; import com.android.toastlib.toast.TopToast; import com.android.toastlib.util.ToastHandler; public class ToastUtils { - public final static int TOP_STYLE = 0x1023; - public final static int SYSTEM_STYLE = 0x1024; + /** + * 顶部下拉回弹样式 + */ + public final static int TOP_TOAST_STYLE = 0x1023; + /** + *系统透明度样式 + */ + public final static int SYSTEM_TOAST_STYLE = 0x1024; public final static String TAG = "ToastUtils"; private static IToast topToast = null; private static IToast systemToast = null; private static ToastHandler topToastHandler = null; private static ToastHandler systemToastHandler = null; + /** + * Should init in Application.java + * @param application + */ public static void init(Application application){ //init TopToast 大于7.1.1 使用ActivityToast,否则使用TopToast if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1){ - topToast = new ActivityToast(application); + topToast = new ActivityCustomizeToast(application); }else{ - topToast = new TopToast(application); + topToast = new TopCustomizeToast(application); } //init SystemToast @@ -33,22 +45,48 @@ public static void init(Application application){ systemToastHandler = new ToastHandler(systemToast); } + /** + * Show Toast use the default TOP_TOAST_STYLE + * @param id + */ + public static void show(int id){ + show(id,TOP_TOAST_STYLE); + } + + /** + * Show Toast use the default TOP_TOAST_STYLE + * @param message + */ + public static void show(CharSequence message){ + show(message,TOP_TOAST_STYLE); + } + + /** + * Show Toast with the Toast style you choosed + * @param id + * @param toastStyle + */ public static void show(int id,int toastStyle){ checkToastUtils(); IToast toast = null; try { - toast = toastStyle == TOP_STYLE ? topToast :systemToast; + toast = toastStyle == TOP_TOAST_STYLE ? topToast :systemToast; show(toast.getView().getContext().getResources().getText(id),toastStyle); } catch (Exception e) { Log.e(TAG,e.toString()); } } + /** + * Show Toast with the Toast style you choosed + * @param message + * @param toastStyle + */ public static void show(CharSequence message,int toastStyle) { checkToastUtils(); ToastHandler toastHandler = null; try { - toastHandler = toastStyle == TOP_STYLE ? topToastHandler : systemToastHandler; + toastHandler = toastStyle == TOP_TOAST_STYLE ? topToastHandler : systemToastHandler; toastHandler.add(message); toastHandler.show(); } catch (Exception e) { diff --git a/Toastlib/src/main/java/com/android/toastlib/toast/ActivityCustomizeToast.java b/Toastlib/src/main/java/com/android/toastlib/toast/ActivityCustomizeToast.java new file mode 100644 index 0000000..13e7723 --- /dev/null +++ b/Toastlib/src/main/java/com/android/toastlib/toast/ActivityCustomizeToast.java @@ -0,0 +1,35 @@ +package com.android.toastlib.toast; + +import android.app.Application; +import android.view.View; + +import com.android.toastlib.util.ActivityCustomizeToastHandler; + +public class ActivityCustomizeToast implements IToast{ + // 吐司弹窗显示辅助类 + private final ActivityCustomizeToastHandler mToastHelper; + + public ActivityCustomizeToast(Application application) { + mToastHelper = new ActivityCustomizeToastHandler(application); + } + + @Override + public void cancel() { + // 取消显示 + mToastHelper.removeView(); + } + + @Override + public View getView() { + return mToastHelper.getView(); + } + + @Override + public void showToast(CharSequence s) { + mToastHelper.setMessage(s); + if(mToastHelper.isToastShowing()) + mToastHelper.sendHideToastMessage(s); + else + mToastHelper.sendShowToastMessage(s); + } +} diff --git a/Toastlib/src/main/java/com/android/toastlib/toast/ActivityToast.java b/Toastlib/src/main/java/com/android/toastlib/toast/ActivityToast.java index 026e2e8..f6ee880 100644 --- a/Toastlib/src/main/java/com/android/toastlib/toast/ActivityToast.java +++ b/Toastlib/src/main/java/com/android/toastlib/toast/ActivityToast.java @@ -20,7 +20,10 @@ public void cancel() { } @Override - public void showToast() { + public void showToast(CharSequence s) { + if(messageView != null){ + messageView.setText(s); + } mToastHelper.show(); } } diff --git a/Toastlib/src/main/java/com/android/toastlib/toast/IToast.java b/Toastlib/src/main/java/com/android/toastlib/toast/IToast.java index 95a17b0..acd0ca9 100644 --- a/Toastlib/src/main/java/com/android/toastlib/toast/IToast.java +++ b/Toastlib/src/main/java/com/android/toastlib/toast/IToast.java @@ -3,9 +3,8 @@ import android.view.View; public interface IToast{ - void setMessageText(CharSequence s); - void showToast(); + void showToast(CharSequence s); void cancel(); diff --git a/Toastlib/src/main/java/com/android/toastlib/toast/SystemToast.java b/Toastlib/src/main/java/com/android/toastlib/toast/SystemToast.java index a9b0f58..4d220f5 100644 --- a/Toastlib/src/main/java/com/android/toastlib/toast/SystemToast.java +++ b/Toastlib/src/main/java/com/android/toastlib/toast/SystemToast.java @@ -1,8 +1,6 @@ package com.android.toastlib.toast; import android.content.Context; -import android.os.Build; -import android.os.Handler; import android.util.Log; import android.view.View; import android.widget.Toast; @@ -20,13 +18,8 @@ public SystemToast(Context context) { } @Override - public void setMessageText(CharSequence s) { + public void showToast(CharSequence s) { toast.setText(s); - Log.i("haozi","setMessageText =="+s); - } - - @Override - public void showToast() { toast.show(); } diff --git a/Toastlib/src/main/java/com/android/toastlib/toast/TopCustomizeToast.java b/Toastlib/src/main/java/com/android/toastlib/toast/TopCustomizeToast.java new file mode 100644 index 0000000..4d452b4 --- /dev/null +++ b/Toastlib/src/main/java/com/android/toastlib/toast/TopCustomizeToast.java @@ -0,0 +1,33 @@ +package com.android.toastlib.toast; + +import android.app.Application; +import android.view.View; + +import com.android.toastlib.util.TopCustomizeToastHandler; + +public class TopCustomizeToast implements IToast{ + private TopCustomizeToastHandler topToastHandler; + public TopCustomizeToast(Application application){ + topToastHandler = new TopCustomizeToastHandler(application); + } + + @Override + public void showToast(CharSequence s) { + topToastHandler.setMessage(s); + if(topToastHandler.isToastShowing()){ + topToastHandler.sendHideToastMessage(s); + }else { + topToastHandler.sendShowToastMessage(s); + } + } + + @Override + public void cancel() { + topToastHandler.removeView(); + } + + @Override + public View getView() { + return topToastHandler.getView(); + } +} diff --git a/Toastlib/src/main/java/com/android/toastlib/toast/TopToast.java b/Toastlib/src/main/java/com/android/toastlib/toast/TopToast.java index 02c0dc1..8c7e29b 100644 --- a/Toastlib/src/main/java/com/android/toastlib/toast/TopToast.java +++ b/Toastlib/src/main/java/com/android/toastlib/toast/TopToast.java @@ -10,13 +10,14 @@ import android.widget.Toast; import com.android.toastlib.R; +import com.android.toastlib.ToastUtils; import com.android.toastlib.util.ScreenUtils; import java.lang.reflect.Field; -public class TopToast implements IToast{ +public class TopToast implements IToast { private final static String TAG = "TopToast"; - private static TextView messageView = null; + public static TextView messageView = null; public Toast toast = null; public TopToast(Context context) { @@ -24,14 +25,11 @@ public TopToast(Context context) { } @Override - public void setMessageText(CharSequence s) { + public void showToast(CharSequence s) { if(messageView != null){ messageView.setText(s); } - } - - @Override - public void showToast() { + toast.setDuration(Toast.LENGTH_SHORT); toast.show(); } @@ -48,7 +46,7 @@ public View getView() { private void initToast(Context context) { View toastView = LayoutInflater.from(context).inflate(R.layout.common_toast_layout,null); messageView = toastView.findViewById(R.id.common_toast_text); - toastView.setMinimumHeight(ScreenUtils.getActionBarHeight(context)+ScreenUtils.getStatusHeight(context)); + toastView.setMinimumHeight(ScreenUtils.getActionBarHeight(context)+ ScreenUtils.getStatusHeight(context)); toastView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); toast = new Toast(context); toast.setView(toastView); @@ -75,10 +73,10 @@ private void makeToastSelfViewAnim(){ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; } catch (NoSuchFieldException e) { e.printStackTrace(); - Log.e("haozi","e.to=="+e.toString()); + Log.e(TAG,e.toString()); } catch (IllegalAccessException e) { e.printStackTrace(); - Log.e("haozi","e.to=="+e.toString()); + Log.e(TAG,e.toString()); } } } diff --git a/Toastlib/src/main/java/com/android/toastlib/util/ActivityCustomizeToastHandler.java b/Toastlib/src/main/java/com/android/toastlib/util/ActivityCustomizeToastHandler.java new file mode 100644 index 0000000..017313e --- /dev/null +++ b/Toastlib/src/main/java/com/android/toastlib/util/ActivityCustomizeToastHandler.java @@ -0,0 +1,47 @@ +package com.android.toastlib.util; + +import android.app.Application; +import android.graphics.PixelFormat; +import android.view.Gravity; +import android.view.WindowManager; + +public class ActivityCustomizeToastHandler extends BaseCustomToastHandler { + private ActivityLifecycleCallback mWindowHelper; + private String mPackageName; + + public ActivityCustomizeToastHandler(Application context) { + super(context); + init(context); + } + + private void init(Application application) { + mPackageName = application.getPackageName(); + mWindowHelper = new ActivityLifecycleCallback(this, application); + } + + @Override + public WindowManager getWindowManager() { + return mWindowHelper.getWindowManager(); + } + + @Override + public WindowManager.LayoutParams getWindowManagerLayoutParams() { + WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.format = PixelFormat.TRANSLUCENT; +// params.windowAnimations = R.style.top_toast_style; + params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_FULLSCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + params.packageName = mPackageName; + // 重新初始化位置 + params.gravity = Gravity.TOP; + params.x = 0; + params.y = 0; + + return params; + } +} diff --git a/Toastlib/src/main/java/com/android/toastlib/util/ActivityLifecycleCallback.java b/Toastlib/src/main/java/com/android/toastlib/util/ActivityLifecycleCallback.java index 7527852..cc949f3 100755 --- a/Toastlib/src/main/java/com/android/toastlib/util/ActivityLifecycleCallback.java +++ b/Toastlib/src/main/java/com/android/toastlib/util/ActivityLifecycleCallback.java @@ -23,7 +23,8 @@ final class ActivityLifecycleCallback implements Application.ActivityLifecycleCa private final ArrayMap mActivitySet = new ArrayMap<>(); // 用于 Activity 暂停时移除 WindowManager - private final ActivityToastHelper mToastHelper; + private ActivityToastHelper mToastHelper; + private ActivityCustomizeToastHandler mToastHandler; // 当前 Activity 对象标记 private String mCurrentTag; @@ -33,6 +34,11 @@ final class ActivityLifecycleCallback implements Application.ActivityLifecycleCa application.registerActivityLifecycleCallbacks(this); } + ActivityLifecycleCallback(ActivityCustomizeToastHandler helper, Application application) { + mToastHandler = helper; + application.registerActivityLifecycleCallbacks(this); + } + /** * 获取一个WindowManager对象 * @@ -42,8 +48,6 @@ WindowManager getWindowManager() throws NullPointerException { if (mCurrentTag != null) { // 如果使用的 WindowManager 对象不是当前 Activity 创建的,则会抛出异常 // android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application - Log.i("shihao","getWindowManager mCurrentTag =="+mCurrentTag); - Log.i("shihao","getWindowManager mActivityset .size =="+mActivitySet.size()); Activity activity = mActivitySet.get(mCurrentTag); if (activity != null) { return getWindowManagerObject(activity); @@ -59,9 +63,7 @@ WindowManager getWindowManager() throws NullPointerException { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { mCurrentTag = getObjectTag(activity); - Log.i("shihao","onActivityCreated mCurrentTag =="+mCurrentTag); mActivitySet.put(mCurrentTag, activity); - Log.i("shihao","onActivityCreated mActivityset .size =="+mActivitySet.size()); } @Override @@ -72,8 +74,6 @@ public void onActivityStarted(Activity activity) { @Override public void onActivityResumed(Activity activity) { mCurrentTag = getObjectTag(activity); - Log.i("shihao","onActivityResumed mCurrentTag =="+mCurrentTag); - Log.i("shihao","onActivityResumed mActivityset .size =="+mActivitySet.size()); } // A跳转B页面的生命周期方法执行顺序: @@ -82,7 +82,10 @@ public void onActivityResumed(Activity activity) { @Override public void onActivityPaused(Activity activity) { // 取消这个吐司的显示 - mToastHelper.cancel(); + if(mToastHandler != null) + mToastHandler.removeView(); + if(mToastHelper != null) + mToastHelper.cancel(); // 不能放在 onStop 或者 onDestroyed 方法中,因为此时新的 Activity 已经创建完成,必须在这个新的 Activity 未创建之前关闭这个 WindowManager // 调用取消显示会直接导致新的 Activity 的 onCreate 调用显示吐司可能显示不出来的问题(立马显示然后立马消失的效果) } @@ -96,10 +99,7 @@ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} @Override public void onActivityDestroyed(Activity activity) { // 移除对这个 Activity 的引用 - Log.i("shihao","onActivityDestroyed mCurrentTag =="+mCurrentTag); - Log.i("shihao","onActivityDestroyed mActivityset .size =="+mActivitySet.size()); mActivitySet.remove(getObjectTag(activity)); - Log.e("shihao","onActivityDestroyed mActivityset .size11111 =="+mActivitySet.size()); // 如果当前的 Activity 是最后一个的话 if (getObjectTag(activity).equals(mCurrentTag)) { // 清除当前标记 diff --git a/Toastlib/src/main/java/com/android/toastlib/util/AnimationUtils.java b/Toastlib/src/main/java/com/android/toastlib/util/AnimationUtils.java new file mode 100755 index 0000000..b8bfa5f --- /dev/null +++ b/Toastlib/src/main/java/com/android/toastlib/util/AnimationUtils.java @@ -0,0 +1,42 @@ +package com.android.toastlib.util; + +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.view.View; + +/** + * This class is used for storing some types of Animation. + * + * @author Chen Yu + * @version 1.0 + * @date 2016-08-19 + */ +public class AnimationUtils { + public static final int ANIMATION_PULL = 0X003; + public static final int ANIMATION_HIDE = 0X004; + public static final String TRANSLATIONY = "translationY"; + + public static AnimatorSet getShowAnimation(View view, int animationType, int height){ + switch (animationType){ + case ANIMATION_PULL: + AnimatorSet pullSet = new AnimatorSet(); + pullSet.playTogether( + ObjectAnimator.ofFloat(view, TRANSLATIONY, + -height-BaseCustomToastHandler.OTHER_HEIGHT, 0,-BaseCustomToastHandler.OTHER_HEIGHT) + ); + pullSet.setDuration(600); + return pullSet; + + case ANIMATION_HIDE: + AnimatorSet hideSet = new AnimatorSet(); + hideSet.playTogether( + ObjectAnimator.ofFloat(view, TRANSLATIONY, -BaseCustomToastHandler.OTHER_HEIGHT,-height) + ); + hideSet.setDuration(300); + return hideSet; + + default: + return new AnimatorSet(); + } + } +} diff --git a/Toastlib/src/main/java/com/android/toastlib/util/BaseCustomToastHandler.java b/Toastlib/src/main/java/com/android/toastlib/util/BaseCustomToastHandler.java new file mode 100644 index 0000000..b194546 --- /dev/null +++ b/Toastlib/src/main/java/com/android/toastlib/util/BaseCustomToastHandler.java @@ -0,0 +1,202 @@ +package com.android.toastlib.util; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.TextView; + +import com.android.toastlib.R; + + +public abstract class BaseCustomToastHandler extends Handler { + public static final int SHORT_DURATION_TIMEOUT = 2000; // 短吐司显示的时长 + public static final int LONG_DURATION_TIMEOUT = 3000; // 长吐司显示的时长 + private final static int SHOW_TOAST = 0x123; + private final static int HIDE_TOAST = 0x456; + public final static int MAX_CANCEL_TIEM = 1000; + public final static int OTHER_HEIGHT = 40; + private static final String TAG = "BaseCustomToastHandler"; + private static int viewHeight = -1; + private boolean isCancelToast = false; + private int cancelToastTime = 0; + private TextView messageView; + View toastView; + private boolean isShowing = false; + + public BaseCustomToastHandler(Context context) { + super(Looper.getMainLooper()); + init(context); + } + + private void init(Context context) { + initToast(context); + } + + private void initToast(Context context) { + toastView = LayoutInflater.from(context).inflate(R.layout.common_toast_layout,null); + messageView = toastView.findViewById(R.id.common_toast_text); + viewHeight = ScreenUtils.getActionBarHeight(context)+ ScreenUtils.getStatusHeight(context)+OTHER_HEIGHT; + toastView.setMinimumHeight(viewHeight); + toastView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } + + @Override + public void handleMessage(Message msg) { + CharSequence message = (CharSequence) msg.obj; + switch (msg.what) { + case SHOW_TOAST: + showToast(message); + break; + case HIDE_TOAST: + hideToast(message); + break; + default: + break; + } + } + + public void sendShowToastMessage(CharSequence msg) { + if (!isShowing) { + Message message = Message.obtain(); + message.what = SHOW_TOAST; + message.obj = msg; + sendMessage(message); + } + } + + public void sendHideToastMessage(CharSequence messageText) { + try { + removeMessages(HIDE_TOAST); + Message message = Message.obtain(); + message.what = HIDE_TOAST; + message.obj = messageText; + sendMessageDelayed(message, getToastDuration(messageText)); + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } + + private void showToast(CharSequence message) { + try { + isShowing = true; + toastView.setVisibility(View.VISIBLE); + getWindowManager().addView(toastView, getWindowManagerLayoutParams()); + AnimatorSet set = AnimationUtils.getShowAnimation(toastView, AnimationUtils.ANIMATION_PULL, viewHeight); + set.addListener(new ToastAnimatorListener(true,message)); + set.start(); + } catch (Exception e) { + Log.i(TAG, e.toString()); + removeOtherToast(message); + } + } + + private void removeOtherToast(final CharSequence message) { + if (!isCancelToast) { +// ToastUtils.cancle(); + isCancelToast = true; + } + isShowing = false; + if (cancelToastTime < MAX_CANCEL_TIEM) { + postDelayed(new Runnable() { + @Override + public void run() { + isShowing = false; + showToast(message); + } + }, cancelToastTime += 100); + } + } + + public void hideToast(CharSequence message) { + AnimatorSet set = AnimationUtils.getShowAnimation(toastView, AnimationUtils.ANIMATION_HIDE, viewHeight); + set.addListener(new ToastAnimatorListener(false, message)); + set.start(); + } + + public void removeView() { + try { + removeMessages(HIDE_TOAST); + removeToast(); + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } + + private void removeToast() { + try { + isShowing = false; + toastView.setVisibility(View.INVISIBLE); + getWindowManager().removeView(toastView); + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } + + public View getView() { + return toastView; + } + + public void setMessage(CharSequence s) { + messageView.setText(s); + } + + public class ToastAnimatorListener implements Animator.AnimatorListener{ + private boolean isShowToast = false; + private CharSequence message; + + public ToastAnimatorListener(boolean isShowToast, CharSequence message){ + this.isShowToast = isShowToast; + this.message = message; + } + + @Override + public void onAnimationStart(Animator animation) { + //Do nothing + } + + @Override + public void onAnimationEnd(Animator animation) { + try { + if(isShowToast){ + isCancelToast = false; + cancelToastTime = 0; + sendHideToastMessage(message); + }else { + removeToast(); + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + //Do nothing + } + + @Override + public void onAnimationRepeat(Animator animation) { + //Do nothing + } + } + + private int getToastDuration (CharSequence text) { + // 如果显示的文字超过了10个就显示长吐司,否则显示短吐司 + int durationTime = text.length() > 40 ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; + return durationTime; + } + + public boolean isToastShowing(){ + return isShowing; + } + + public abstract WindowManager getWindowManager(); + public abstract WindowManager.LayoutParams getWindowManagerLayoutParams(); +} diff --git a/Toastlib/src/main/java/com/android/toastlib/util/ToastHandler.java b/Toastlib/src/main/java/com/android/toastlib/util/ToastHandler.java index d2e0d3b..88d8840 100755 --- a/Toastlib/src/main/java/com/android/toastlib/util/ToastHandler.java +++ b/Toastlib/src/main/java/com/android/toastlib/util/ToastHandler.java @@ -4,7 +4,6 @@ import android.os.Looper; import android.os.Message; import android.util.Log; -import android.widget.Toast; import com.android.toastlib.toast.IToast; @@ -18,18 +17,16 @@ * desc : Toast 显示处理类 */ public class ToastHandler extends Handler { - public static final int SHORT_DURATION_TIMEOUT = 2000; // 短吐司显示的时长 - public static final int LONG_DURATION_TIMEOUT = 3500; // 长吐司显示的时长 - public static final int CONTINUE_SHORT_DURATION_TIMEOUT = 600; // 短吐司显示的时长 public static final int CONTINUE_LONG_DURATION_TIMEOUT = 1000; // 长吐司显示的时长 + private static final long MAX_CONTROL_INTERVAL = 500; private static final int TYPE_SHOW = 1; // 显示吐司 private static final int TYPE_CONTINUE = 2; // 继续显示 private static final int TYPE_CANCEL = 3; // 取消显示 // 队列最大容量 - private static final int MAX_TOAST_CAPACITY = 5; + private static final int MAX_TOAST_CAPACITY = 10; // 吐司队列 private volatile Queue mQueue; @@ -39,6 +36,8 @@ public class ToastHandler extends Handler { // 吐司对象 private final IToast mToast; + private long lastAddMsgTime = 0; + private CharSequence currentToastString = null; public ToastHandler(IToast toast) { super(Looper.getMainLooper()); @@ -47,17 +46,33 @@ public ToastHandler(IToast toast) { } public void add(CharSequence s) { -// if (mQueue.isEmpty() || !mQueue.contains(s)) { -// // 添加一个元素并返回true,如果队列已满,则返回false -// if (!mQueue.offer(s)) { +// if (mQueue.isEmpty() || !mQueue.contains(s)){ +// || isNeedAddMessage()) { +// lastAddMsgTime = System.currentTimeMillis(); + +// if(mQueue.offer(s)){// 成功添加一个元素并返回true,如果队列已满,则返回false + +// }else{ // // 移除队列头部元素并添加一个新的元素 // mQueue.poll(); // mQueue.offer(s); // } // } - if (mQueue.isEmpty() || !mQueue.contains(s)) { - mQueue.offer(s); + + if(!mQueue.contains(s) || isNeedAddMessage(s)){ + if(mQueue.offer(s)) + lastAddMsgTime = System.currentTimeMillis(); + } + } + + private boolean isNeedAddMessage(CharSequence addString) { + if((System.currentTimeMillis() - lastAddMsgTime > MAX_CONTROL_INTERVAL) + && currentToastString != null + && addString.toString().equalsIgnoreCase(currentToastString.toString())){ + return true; } + + return false; } public void show() { @@ -79,31 +94,27 @@ public void handleMessage(Message msg) { switch (msg.what) { case TYPE_SHOW: // 返回队列头部的元素,如果队列为空,则返回null - Log.i("haozi","show mQueue.size 1111=="+mQueue.size()); - CharSequence text = mQueue.poll(); + CharSequence text = mQueue.peek(); if (text != null) { - mToast.setMessageText(text); - mToast.showToast(); + currentToastString = text.toString(); + mToast.showToast(text); // 等这个 Toast 显示完后再继续显示,要加上一些延迟,不然在某些手机上 Toast 可能会来不及消失 sendEmptyMessageDelayed(TYPE_CONTINUE, getToastDuration(text)); - Log.i("haozi","show mQueue.size =="+mQueue.size()); }else { isShow = false; } break; case TYPE_CONTINUE: // 移除并返问队列头部的元素,如果队列为空,则返回null - Log.i("haozi","TYPE_CONTINUE mQueue.size2222 =="+mQueue.size()); -// mQueue.poll(); - Log.i("haozi","TYPE_CONTINUE mQueue.size1111 =="+mQueue.size()); + mQueue.poll(); if (!mQueue.isEmpty()) { sendEmptyMessage(TYPE_SHOW); }else { isShow = false; + currentToastString = null; } break; case TYPE_CANCEL: - Log.i("haozi","TYPE_CANCEL mQueue.size =="+mQueue.size()); isShow = false; mQueue.clear(); mToast.cancel(); @@ -117,13 +128,6 @@ public void handleMessage(Message msg) { * 根据文本来获取吐司的显示时间 */ private int getToastDuration (CharSequence text) { - // 如果显示的文字超过了10个就显示长吐司,否则显示短吐司 - int durationTime = 0; - if(mQueue.size() > 0){ - durationTime = text.length() > 20 ? CONTINUE_LONG_DURATION_TIMEOUT : CONTINUE_SHORT_DURATION_TIMEOUT; - }else{ - durationTime = text.length() > 20 ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; - } - return durationTime; + return text.length() > 40 ? CONTINUE_LONG_DURATION_TIMEOUT : CONTINUE_SHORT_DURATION_TIMEOUT; } } \ No newline at end of file diff --git a/Toastlib/src/main/java/com/android/toastlib/util/TopCustomizeToastHandler.java b/Toastlib/src/main/java/com/android/toastlib/util/TopCustomizeToastHandler.java new file mode 100755 index 0000000..fca773f --- /dev/null +++ b/Toastlib/src/main/java/com/android/toastlib/util/TopCustomizeToastHandler.java @@ -0,0 +1,52 @@ +package com.android.toastlib.util; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.os.Build; +import android.view.Gravity; +import android.view.WindowManager; + +public class TopCustomizeToastHandler extends BaseCustomToastHandler { + private static WindowManager mWindowManager = null; + private static WindowManager.LayoutParams mParams = null; + + public TopCustomizeToastHandler(Context context) { + super(context); + initWindowManager(context); + } + + private void initWindowManager(Context context) { + mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + + mParams = new WindowManager.LayoutParams(); + mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + mParams.width = WindowManager.LayoutParams.MATCH_PARENT; + mParams.format = PixelFormat.TRANSLUCENT; + //7.0 以下用TYPE_TOAST + //7.1.1 需用TYPE_PHONE + //8.0以上过时,用TYPE_APPLICATION_OVERLAY + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + } else + mParams.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 ? WindowManager.LayoutParams.TYPE_PHONE : WindowManager.LayoutParams.TYPE_TOAST; + + mParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_FULLSCREEN + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + + mParams.gravity = Gravity.TOP; + mParams.y = 0; + mParams.x = 0; + } + + @Override + public WindowManager getWindowManager() { + return mWindowManager; + } + + @Override + public WindowManager.LayoutParams getWindowManagerLayoutParams() { + return mParams; + } +} diff --git a/Toastlib/src/main/res/mipmap-hdpi/item_toast_icon.png b/Toastlib/src/main/res/mipmap-hdpi/item_toast_icon.png new file mode 100644 index 0000000..d02d896 Binary files /dev/null and b/Toastlib/src/main/res/mipmap-hdpi/item_toast_icon.png differ diff --git a/Toastlib/src/main/res/mipmap-xhdpi/item_toast_icon.png b/Toastlib/src/main/res/mipmap-xhdpi/item_toast_icon.png new file mode 100644 index 0000000..94421ff Binary files /dev/null and b/Toastlib/src/main/res/mipmap-xhdpi/item_toast_icon.png differ diff --git a/Toastlib/src/main/res/mipmap-xxhdpi/item_toast_icon.png b/Toastlib/src/main/res/mipmap-xxhdpi/item_toast_icon.png index 94421ff..775d899 100644 Binary files a/Toastlib/src/main/res/mipmap-xxhdpi/item_toast_icon.png and b/Toastlib/src/main/res/mipmap-xxhdpi/item_toast_icon.png differ diff --git a/app/build.gradle b/app/build.gradle index 0e00f93..ab4ca37 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,5 +27,5 @@ dependencies { androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation project(':Toastlib') -// implementation 'com.github.haozi5460:Toastlib:1.0.0' +// implementation 'com.github.haozi5460:Toastlib:1.0.1' } diff --git a/app/src/main/java/com/android/toasttest/MainActivity.java b/app/src/main/java/com/android/toasttest/MainActivity.java index 17dcf0a..52ec7f6 100644 --- a/app/src/main/java/com/android/toasttest/MainActivity.java +++ b/app/src/main/java/com/android/toasttest/MainActivity.java @@ -26,7 +26,7 @@ protected void onCreate(Bundle savedInstanceState) { public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); - ToastUtils.show("Replace with your own action",ToastUtils.TOP_STYLE); + ToastUtils.show("Replace with your own action"); } }); } @@ -47,12 +47,12 @@ public boolean onOptionsItemSelected(MenuItem item) { //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { - ToastUtils.show("Replace with your own actionsdfadfadfasdfasdfasdfasdf",ToastUtils.TOP_STYLE); - ToastUtils.show("Replace with your own action",ToastUtils.SYSTEM_STYLE); - ToastUtils.show("Replace with your own actionf1111111111111",ToastUtils.TOP_STYLE); - ToastUtils.show("Replace with your own action1111112223232143413",ToastUtils.SYSTEM_STYLE); - ToastUtils.show("Replace with your own action222222222222",ToastUtils.TOP_STYLE); - ToastUtils.show("Replace with your own actionDDDDDDDDDDDDDD",ToastUtils.SYSTEM_STYLE); + ToastUtils.show("Replace with your own actionsdfadfadfasdfasdfasdfasdf"); + ToastUtils.show("Replace with your own action",ToastUtils.SYSTEM_TOAST_STYLE); + ToastUtils.show("Replace with your own actionf1111111111111"); + ToastUtils.show("Replace with your own action1111112223232143413",ToastUtils.SYSTEM_TOAST_STYLE); + ToastUtils.show("Replace with your own action222222222222"); + ToastUtils.show("Replace with your own actionDDDDDDDDDDDDDD",ToastUtils.SYSTEM_TOAST_STYLE); return true; } if (id == R.id.action_settings1) {