將浮動視窗以單例模式生成

This commit is contained in:
Raymond Yang 2023-07-03 15:02:09 +08:00
parent 49fbe33f8d
commit ea629e45a7
6 changed files with 157 additions and 66 deletions

View File

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.TYPE_APPLICATION_OVERLAY" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
@ -17,6 +18,7 @@
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:screenOrientation="landscape"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -0,0 +1,69 @@
package com.ray650128.easywindowtest
import android.view.Gravity
import android.view.MotionEvent
import android.view.WindowManager
import com.hjq.window.EasyWindow
object FloatingWindowHelper {
private var _isShowing: Boolean = false
val isShowing: Boolean
get() = _isShowing
private val window by lazy {
EasyWindow<EasyWindow<*>>(MyApp.instance).apply {
setContentView(R.layout.window_hint)
setGravity(Gravity.START or Gravity.TOP)
setYOffset(100)
setImageDrawable(android.R.id.icon, R.drawable.ic_chicken)
setOnTouchListener { window, view, event ->
var touch = false
when (event.action) {
MotionEvent.ACTION_DOWN -> {
window.setWindowFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
)
window.update()
touch = true
}
MotionEvent.ACTION_OUTSIDE -> {
window.setWindowFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
)
window.update()
touch = false
}
else -> {}
}
touch
}
}
}
fun show() {
_isShowing = true
window.show()
}
fun hide() {
_isShowing = false
window.cancel()
}
fun setXOffset(value: Int) {
window.setXOffset(value)
window.update()
}
fun setYOffset(value: Int) {
window.setYOffset(value)
window.update()
}
}

View File

@ -1,6 +1,7 @@
package com.ray650128.easywindowtest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
@ -20,92 +21,63 @@ class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val mContext: Context by lazy { this }
private val floatingWindowPermission = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_CANCELED) {
if (!Settings.canDrawOverlays(this)) {
binding.btnStep1.isEnabled = !Settings.canDrawOverlays(this)
binding.btnStep2.isEnabled = Settings.canDrawOverlays(this)
binding.btnStep3.isEnabled = isFloatWindowShowing
if (!Settings.canDrawOverlays(mContext)) {
binding.btnStep1.isEnabled = !Settings.canDrawOverlays(mContext)
binding.btnStep2.isEnabled = Settings.canDrawOverlays(mContext)
binding.btnStep3.isEnabled = FloatingWindowHelper.isShowing
return@registerForActivityResult
}
showOverlayWindow()
}
}
private var isFloatWindowShowing = false
private val window by lazy {
EasyWindow<EasyWindow<*>>(application).apply {
setContentView(R.layout.window_hint)
setGravity(Gravity.START or Gravity.TOP)
setYOffset(100)
setImageDrawable(android.R.id.icon, R.drawable.ic_chicken)
setOnTouchListener { window, view, event ->
var touch = false
when (event.action) {
MotionEvent.ACTION_DOWN -> {
window.setWindowFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
)
window.update()
touch = true
}
MotionEvent.ACTION_OUTSIDE -> {
window.setWindowFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
)
window.update()
touch = false
}
else -> {}
}
touch
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnStep1.isEnabled = !Settings.canDrawOverlays(this)
binding.btnStep1.setOnClickListener {
binding.apply {
btnStep1.setOnClickListener {
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
intent.data = Uri.parse("package:$packageName")
floatingWindowPermission.launch(intent)
}
binding.btnStep2.isEnabled = Settings.canDrawOverlays(this)
binding.btnStep2.setOnClickListener {
btnStep2.setOnClickListener {
showOverlayWindow()
}
binding.btnStep3.isEnabled = isFloatWindowShowing
binding.btnStep3.setOnClickListener {
btnStep3.setOnClickListener {
hideOverlayWindow()
}
}
}
override fun onResume() {
super.onResume()
binding.apply {
btnStep1.isEnabled = !Settings.canDrawOverlays(mContext)
btnStep2.isEnabled = Settings.canDrawOverlays(mContext) && !FloatingWindowHelper.isShowing
btnStep3.isEnabled = FloatingWindowHelper.isShowing
}
}
private fun showOverlayWindow() {
isFloatWindowShowing = true
binding.btnStep2.isEnabled = !isFloatWindowShowing
binding.btnStep3.isEnabled = isFloatWindowShowing
window.show()
FloatingWindowHelper.show()
binding.btnStep2.isEnabled = !FloatingWindowHelper.isShowing
binding.btnStep3.isEnabled = FloatingWindowHelper.isShowing
}
private fun hideOverlayWindow() {
isFloatWindowShowing = false
binding.btnStep2.isEnabled = !isFloatWindowShowing
binding.btnStep3.isEnabled = isFloatWindowShowing
window.cancel()
FloatingWindowHelper.hide()
binding.btnStep2.isEnabled = !FloatingWindowHelper.isShowing
binding.btnStep3.isEnabled = FloatingWindowHelper.isShowing
}
}

View File

@ -0,0 +1,21 @@
package com.ray650128.easywindowtest
import android.app.Application
import android.content.Context
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
private val TAG = MyApp::class.java.simpleName
var instance: Application? = null
val appContext: Context
get() = instance!!.applicationContext
}
}

View File

@ -6,21 +6,39 @@
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第一步:請先允許懸浮窗權限"
app:layout_constraintBottom_toTopOf="@+id/btnStep1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnStep1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第一步,開啟懸浮窗權限"
android:text="授予懸浮窗權限"
app:layout_constraintBottom_toTopOf="@+id/btnStep2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第二步:開啟懸浮窗"
app:layout_constraintBottom_toTopOf="@+id/btnStep2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnStep2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第二步,啟動懸浮窗"
android:text="啟動懸浮窗"
app:layout_constraintBottom_toTopOf="@+id/btnStep3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -36,4 +54,13 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnStep2" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="若想關閉懸浮窗,按一下:"
app:layout_constraintBottom_toTopOf="@+id/btnStep3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,3 +1,3 @@
<resources>
<string name="app_name">EasyWindowTest</string>
<string name="app_name">懸浮視窗 by 楓小夜</string>
</resources>