將浮動視窗以單例模式生成
This commit is contained in:
parent
49fbe33f8d
commit
ea629e45a7
@ -6,6 +6,7 @@
|
|||||||
<uses-permission android:name="android.permission.TYPE_APPLICATION_OVERLAY" />
|
<uses-permission android:name="android.permission.TYPE_APPLICATION_OVERLAY" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".MyApp"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
@ -17,6 +18,7 @@
|
|||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
android:screenOrientation="landscape"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|||||||
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package com.ray650128.easywindowtest
|
package com.ray650128.easywindowtest
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@ -20,92 +21,63 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
|
|
||||||
|
private val mContext: Context by lazy { this }
|
||||||
|
|
||||||
private val floatingWindowPermission = registerForActivityResult(
|
private val floatingWindowPermission = registerForActivityResult(
|
||||||
ActivityResultContracts.StartActivityForResult()
|
ActivityResultContracts.StartActivityForResult()
|
||||||
) { result ->
|
) { result ->
|
||||||
if (result.resultCode == Activity.RESULT_CANCELED) {
|
if (result.resultCode == Activity.RESULT_CANCELED) {
|
||||||
if (!Settings.canDrawOverlays(this)) {
|
if (!Settings.canDrawOverlays(mContext)) {
|
||||||
binding.btnStep1.isEnabled = !Settings.canDrawOverlays(this)
|
binding.btnStep1.isEnabled = !Settings.canDrawOverlays(mContext)
|
||||||
binding.btnStep2.isEnabled = Settings.canDrawOverlays(this)
|
binding.btnStep2.isEnabled = Settings.canDrawOverlays(mContext)
|
||||||
binding.btnStep3.isEnabled = isFloatWindowShowing
|
binding.btnStep3.isEnabled = FloatingWindowHelper.isShowing
|
||||||
return@registerForActivityResult
|
return@registerForActivityResult
|
||||||
}
|
}
|
||||||
showOverlayWindow()
|
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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
binding.btnStep1.isEnabled = !Settings.canDrawOverlays(this)
|
binding.apply {
|
||||||
binding.btnStep1.setOnClickListener {
|
btnStep1.setOnClickListener {
|
||||||
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
|
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
|
||||||
intent.data = Uri.parse("package:$packageName")
|
intent.data = Uri.parse("package:$packageName")
|
||||||
floatingWindowPermission.launch(intent)
|
floatingWindowPermission.launch(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.btnStep2.isEnabled = Settings.canDrawOverlays(this)
|
btnStep2.setOnClickListener {
|
||||||
binding.btnStep2.setOnClickListener {
|
showOverlayWindow()
|
||||||
showOverlayWindow()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
binding.btnStep3.isEnabled = isFloatWindowShowing
|
btnStep3.setOnClickListener {
|
||||||
binding.btnStep3.setOnClickListener {
|
hideOverlayWindow()
|
||||||
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() {
|
private fun showOverlayWindow() {
|
||||||
isFloatWindowShowing = true
|
FloatingWindowHelper.show()
|
||||||
binding.btnStep2.isEnabled = !isFloatWindowShowing
|
binding.btnStep2.isEnabled = !FloatingWindowHelper.isShowing
|
||||||
binding.btnStep3.isEnabled = isFloatWindowShowing
|
binding.btnStep3.isEnabled = FloatingWindowHelper.isShowing
|
||||||
window.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideOverlayWindow() {
|
private fun hideOverlayWindow() {
|
||||||
isFloatWindowShowing = false
|
FloatingWindowHelper.hide()
|
||||||
binding.btnStep2.isEnabled = !isFloatWindowShowing
|
binding.btnStep2.isEnabled = !FloatingWindowHelper.isShowing
|
||||||
binding.btnStep3.isEnabled = isFloatWindowShowing
|
binding.btnStep3.isEnabled = FloatingWindowHelper.isShowing
|
||||||
window.cancel()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
21
app/src/main/java/com/ray650128/easywindowtest/MyApp.kt
Normal file
21
app/src/main/java/com/ray650128/easywindowtest/MyApp.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,21 +6,39 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".MainActivity">
|
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
|
<Button
|
||||||
android:id="@+id/btnStep1"
|
android:id="@+id/btnStep1"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="第一步,開啟懸浮窗權限"
|
android:text="授予懸浮窗權限"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/btnStep2"
|
app:layout_constraintBottom_toTopOf="@+id/btnStep2"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="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
|
<Button
|
||||||
android:id="@+id/btnStep2"
|
android:id="@+id/btnStep2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="第二步,啟動懸浮窗"
|
android:text="啟動懸浮窗"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/btnStep3"
|
app:layout_constraintBottom_toTopOf="@+id/btnStep3"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@ -36,4 +54,13 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/btnStep2" />
|
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>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@ -1,3 +1,3 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">EasyWindowTest</string>
|
<string name="app_name">懸浮視窗 by 楓小夜</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user