Skip to content

Commit e075f6b

Browse files
committed
Update
1 parent ba78292 commit e075f6b

2 files changed

Lines changed: 45 additions & 7 deletions

File tree

app/src/main/java/com/omarea/common/ui/BannerNotificationManager.kt

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ package com.omarea.common.ui
33
import android.animation.Animator
44
import android.animation.AnimatorListenerAdapter
55
import android.app.Activity
6+
import android.graphics.PixelFormat
67
import android.graphics.drawable.GradientDrawable
78
import android.os.Handler
89
import android.os.Looper
10+
import android.view.Gravity
911
import android.view.LayoutInflater
1012
import android.view.View
1113
import android.view.ViewGroup
14+
import android.view.WindowManager
1215
import android.widget.ImageView
1316
import android.widget.TextView
1417
import androidx.core.view.ViewCompat
@@ -20,7 +23,13 @@ enum class BannerType { INFO, SUCCESS, WARNING, ERROR }
2023
/**
2124
* Hiện 1 banner thông báo đè lên trên cùng của Activity đang foreground.
2225
* Khác với Toast: hiển thị trong nội dung ứng dụng, có thể tùy biến màu/icon/tiêu đề,
23-
* và chỉ hoạt động khi app đang mở (cần 1 Activity foreground để addView vào).
26+
* và chỉ hoạt động khi app đang mở (cần 1 Activity foreground để add vào).
27+
*
28+
* Banner được thêm vào dưới dạng 1 Window độc lập (WindowManager.addView), KHÔNG phải
29+
* child view của content Activity. Lý do: nếu chỉ addView vào content, banner sẽ bị các
30+
* Dialog/AlertDialog (vốn là 1 Window riêng nổi trên Window của Activity) che mất, vì
31+
* Dialog luôn ở lớp trên bất kể elevation. Thêm dưới dạng Window riêng, add sau cùng,
32+
* đảm bảo banner luôn nổi trên mọi Dialog đang mở tại thời điểm gọi.
2433
*
2534
* Gọi từ shell: am broadcast -a <applicationId>.broadcast.BANNER --es text "..." --es type "success"
2635
*/
@@ -71,12 +80,23 @@ object BannerNotificationManager {
7180
return
7281
}
7382
isShowing = true
74-
showOn(activity, req)
83+
try {
84+
showOn(activity, req)
85+
} catch (e: Exception) {
86+
// Activity có thể vừa bị hủy đúng lúc addView (BadTokenException...) -> bỏ qua, sang cái tiếp theo
87+
showNext()
88+
}
7589
}
7690

7791
private fun showOn(activity: Activity, req: BannerRequest) {
78-
val root = activity.findViewById<ViewGroup>(android.R.id.content)
79-
val view = LayoutInflater.from(activity).inflate(R.layout.banner_notification, root, false)
92+
val decorView = activity.window?.decorView
93+
if (decorView == null || !decorView.isAttachedToWindow) {
94+
showNext()
95+
return
96+
}
97+
val windowManager = activity.windowManager
98+
99+
val view = LayoutInflater.from(activity).inflate(R.layout.banner_notification, null, false)
80100

81101
val bannerRoot = view.findViewById<View>(R.id.banner_root)
82102
val icon = view.findViewById<ImageView>(R.id.banner_icon)
@@ -110,7 +130,21 @@ object BannerNotificationManager {
110130
insets
111131
}
112132

113-
root.addView(view)
133+
val params = WindowManager.LayoutParams(
134+
ViewGroup.LayoutParams.MATCH_PARENT,
135+
ViewGroup.LayoutParams.WRAP_CONTENT,
136+
WindowManager.LayoutParams.TYPE_APPLICATION,
137+
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
138+
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
139+
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
140+
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
141+
PixelFormat.TRANSLUCENT
142+
).apply {
143+
gravity = Gravity.TOP
144+
token = decorView.windowToken
145+
}
146+
147+
windowManager.addView(view, params)
114148
ViewCompat.requestApplyInsets(view)
115149

116150
var dismissed = false
@@ -124,7 +158,11 @@ object BannerNotificationManager {
124158
.setDuration(200)
125159
.setListener(object : AnimatorListenerAdapter() {
126160
override fun onAnimationEnd(animation: Animator) {
127-
root.removeView(view)
161+
try {
162+
windowManager.removeViewImmediate(view)
163+
} catch (e: Exception) {
164+
// Window có thể đã bị hệ thống dọn (activity destroyed) -> bỏ qua
165+
}
128166
showNext()
129167
}
130168
})

app/src/main/res/layout/banner_notification.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
android:layout_height="wrap_content"
66
android:layout_marginStart="12dp"
77
android:layout_marginEnd="12dp"
8-
android:layout_marginTop="12dp"
8+
android:layout_marginTop="?android:actionBarSize"
99
android:orientation="horizontal"
1010
android:gravity="center_vertical"
1111
android:background="@drawable/banner_bg"

0 commit comments

Comments
 (0)