BaseGlobalDialog
BaseGlobalDialog通过WindowManager添加View
public abstract class BaseGlobalDialog implements DefaultLifecycleObserver {
private static final String TAG = "BaseGlobalDialog";
protected Context mContext;
protected ViewGroup root;
protected TextView textView;
private WindowManager mWindowManager = null;
private boolean mIsShowing = false;
protected boolean isDismissByTouchOutside = true;
public BaseGlobalDialog(@NonNull Context context) {
this.mContext = context;
this.root = (ViewGroup) LayoutInflater.from(context).inflate(getLayoutId(), null);
this.textView = root.findViewById(getTextViewId());
}
public void showToast(String text) {
Log.d(TAG, "showDialog: ");
if (mIsShowing) {
Log.d(TAG, "showDialog: but is showing.");
return;
}
mIsShowing = true;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
textView.setText(text);
mWindowManager.addView(root, getLayoutParams());
setCancelTouchEvent();
if (mContext instanceof AppCompatActivity) {
((AppCompatActivity) mContext).getLifecycle().addObserver(this);
}
Log.d(TAG, "showDialog: end");
}
public void setDismissByTouchOutside(boolean dismissByTouchOutside) {
isDismissByTouchOutside = dismissByTouchOutside;
}
public abstract WindowManager.LayoutParams getLayoutParams();
public abstract int getLayoutId();
public abstract int getTextViewId();
public boolean isShowing() {
Log.d(TAG, "isShowing: mIsShowing = " + mIsShowing);
return mIsShowing;
}
public void hideToast() {
Log.d(TAG, "hideDialog: ");
if (mIsShowing && mWindowManager != null) {
mWindowManager.removeView(root);
mIsShowing = false;
if (mContext instanceof AppCompatActivity) {
((AppCompatActivity) mContext).getLifecycle().removeObserver(this);
}
}
Log.d(TAG, "hideDialog: end");
}
public void hideToastImmediately() {
Log.d(TAG, "hideToastImmediately: ");
if (mIsShowing && mWindowManager != null) {
mWindowManager.removeViewImmediate(root);
mIsShowing = false;
if (mContext instanceof AppCompatActivity) {
((AppCompatActivity) mContext).getLifecycle().removeObserver(this);
}
}
Log.d(TAG, "hideToastImmediately: end");
}
@SuppressLint("ClickableViewAccessibility")
private void setCancelTouchEvent() {
root.setOnTouchListener((View v, MotionEvent event) -> {
if (!isDismissByTouchOutside) {
return true;
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
Rect rect = new Rect();
textView.getGlobalVisibleRect(rect);
if (!rect.contains(x, y)) {
Log.d(TAG, "onTouch: outside");
hideToast();
}
}
return false;
});
root.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d(TAG, "onTouch: keycode = " + keyCode);
hideToast();
return true;
}
return false;
});
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
hideToast();
}
}
AnimGlobalToast
AnimGlobalToast在新增View时加上动画效果
class AnimGlobalToast extends BaseGlobalDialog {
private static final String TAG = "AnimGlobalToast";
private static final Handler handler = new Handler(Looper.getMainLooper());
private AnimatorSet mToastAnimatorSet;
private boolean mIsHiding;
public AnimGlobalToast(@NonNull Context mCtx) {
super(mCtx);
}
@Override
public WindowManager.LayoutParams getLayoutParams() {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.format = PixelFormat.RGBA_8888;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
return params;
}
@Override
public int getLayoutId() {
return R.layout.layout_global_toast_normal;
}
@Override
public int getTextViewId() {
return R.id.toast_text;
}
public void showDialogNoAutoHide(String text, long millisecond) {
showToast(text, millisecond, false);
}
public void showToast(String text, long millisecond) {
showToast(text, millisecond, true);
}
private void showToast(String text, long millisecond, boolean isNeedHide) {
startToastShowAnim(root, new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
AnimGlobalToast.super.showToast(text);
}
});
mIsHiding = false;
if (isNeedHide) {
handler.postDelayed(this::hideToast, millisecond);
}
}
private void startToastShowAnim(View view, AnimatorListenerAdapter listenerAdapter) {
Log.d(TAG, "startToastShowAnim: ");
int duation = 240;
ArrayList<Animator> animatorArrayList = new ArrayList<>();
animatorArrayList.add(ObjectAnimator.ofFloat(view, "translationY", 0, 30));
animatorArrayList.add(ObjectAnimator.ofFloat(view, "alpha", 0f, 1f));
if (mToastAnimatorSet != null && mToastAnimatorSet.isRunning()) {
mToastAnimatorSet.cancel();
}
mToastAnimatorSet = new AnimatorSet();
mToastAnimatorSet.setDuration(duation);
mToastAnimatorSet.playTogether(animatorArrayList);
mToastAnimatorSet.addListener(listenerAdapter);
mToastAnimatorSet.start();
}
@Override
public void hideToast() {
if (mIsHiding) { // 若动画已经启动,再调用hideToast()会闪一下
Log.d(TAG, "hideToast: mIsHiding");
return;
}
startToastHideAnim(textView, new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
mIsHiding = true;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
AnimGlobalToast.super.hideToast();
}
});
}
@Override
public void hideToastImmediately() {
AnimGlobalToast.super.hideToastImmediately();
}
private void startToastHideAnim(View view, AnimatorListenerAdapter listenerAdapter) {
Log.d(TAG, "startToastHideAnim: ");
int duation = 240;
ArrayList<Animator> animatorArrayList = new ArrayList<>();
animatorArrayList.add(ObjectAnimator.ofFloat(view, "translationY", -30, 0));
animatorArrayList.add(ObjectAnimator.ofFloat(view, "alpha", 1f, 0f));
if (mToastAnimatorSet != null && mToastAnimatorSet.isRunning()) {
mToastAnimatorSet.cancel();
}
mToastAnimatorSet = new AnimatorSet();
mToastAnimatorSet.setDuration(duation);
mToastAnimatorSet.playTogether(animatorArrayList);
mToastAnimatorSet.addListener(listenerAdapter);
mToastAnimatorSet.start();
}
}
GlobalToastManager
GlobalToastManager用单例控制AnimGlobalToast生命周期
public class GlobalToastManager {
private BaseGlobalDialog currentToast;
public static final long DEFAULT_TOAST_TIME = 2000;
private static class Holder {
private static final GlobalToastManager INSTANCE = new GlobalToastManager();
}
private GlobalToastManager() {
}
public static GlobalToastManager getInstance() {
return Holder.INSTANCE;
}
public void showToast(Context context, String msg) {
showToast(context, msg, true, DEFAULT_TOAST_TIME);
}
public void showToast(Context context, String msg, boolean dismissByTouchOutside) {
showToast(context, msg, dismissByTouchOutside, DEFAULT_TOAST_TIME);
}
public void showToast(Context context, String msg, boolean dismissByTouchOutside, long time) {
if (currentToast != null) {
currentToast.hideToastImmediately();
}
AnimGlobalToast nextToast = new AnimGlobalToast(context);
nextToast.setDismissByTouchOutside(dismissByTouchOutside);
nextToast.showToast(msg, time);
currentToast = nextToast;
}
public void showToastNoAutoHide(Context context, String msg) {
showToastNoAutoHide(context, msg, true, DEFAULT_TOAST_TIME);
}
public void showToastNoAutoHide(Context context, String msg, boolean dismissByTouchOutside) {
showToastNoAutoHide(context, msg, dismissByTouchOutside, DEFAULT_TOAST_TIME);
}
public void showToastNoAutoHide(Context context, String msg, boolean dismissByTouchOutside, long time) {
if (currentToast != null) {
currentToast.hideToastImmediately();
}
AnimGlobalToast nextToast = new AnimGlobalToast(context);
nextToast.setDismissByTouchOutside(dismissByTouchOutside);
nextToast.showDialogNoAutoHide(msg, time);
currentToast = nextToast;
}
public void hideToast() {
if (currentToast != null) {
BaseGlobalDialog hideToast = currentToast;
currentToast = null;
hideToast.hideToast();
}
}
}
使用方式
声明权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
使用时需要申请权限
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ImageView mIv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIv1 = findViewById(R.id.iv1);
mIv2 = findViewById(R.id.iv2);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(intent);
}
mIv1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick: mIv1");
GlobalToastManager.getInstance().showToast(MainActivity.this, "hellohellohellohellohellohellohello");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
GlobalToastManager.getInstance().hideToast();
}
}, 1000);
}
});
}
}
1228

被折叠的 条评论
为什么被折叠?



