From 49fbe33f8de86d21092927dd40e867e6563cce4f Mon Sep 17 00:00:00 2001 From: Raymond Yang Date: Mon, 3 Jul 2023 14:39:30 +0800 Subject: [PATCH] first commit --- .gitignore | 137 +++++++++++++ app/.gitignore | 1 + app/build.gradle.kts | 52 +++++ app/proguard-rules.pro | 21 ++ .../easywindowtest/ExampleInstrumentedTest.kt | 24 +++ app/src/main/AndroidManifest.xml | 29 +++ .../ray650128/easywindowtest/MainActivity.kt | 111 +++++++++++ .../easywindowtest/MovingDraggable.kt | 68 +++++++ app/src/main/res/drawable/bg_window.xml | 5 + app/src/main/res/drawable/ic_chicken.png | Bin 0 -> 13806 bytes .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++++++ .../res/drawable/ic_launcher_foreground.xml | 30 +++ app/src/main/res/layout/activity_main.xml | 39 ++++ app/src/main/res/layout/window_hint.xml | 20 ++ .../main/res/mipmap-anydpi/ic_launcher.xml | 6 + .../res/mipmap-anydpi/ic_launcher_round.xml | 6 + app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes app/src/main/res/values-night/themes.xml | 7 + app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/themes.xml | 9 + app/src/main/res/xml/backup_rules.xml | 13 ++ .../main/res/xml/data_extraction_rules.xml | 19 ++ .../easywindowtest/ExampleUnitTest.kt | 17 ++ build.gradle.kts | 5 + gradle.properties | 23 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 ++++++++++++++++++ gradlew.bat | 89 +++++++++ settings.gradle.kts | 19 ++ 40 files changed, 1119 insertions(+) create mode 100644 .gitignore create mode 100644 app/.gitignore create mode 100644 app/build.gradle.kts create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/ray650128/easywindowtest/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/ray650128/easywindowtest/MainActivity.kt create mode 100644 app/src/main/java/com/ray650128/easywindowtest/MovingDraggable.kt create mode 100644 app/src/main/res/drawable/bg_window.xml create mode 100644 app/src/main/res/drawable/ic_chicken.png create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/window_hint.xml create mode 100644 app/src/main/res/mipmap-anydpi/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/backup_rules.xml create mode 100644 app/src/main/res/xml/data_extraction_rules.xml create mode 100644 app/src/test/java/com/ray650128/easywindowtest/ExampleUnitTest.kt create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a7057f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,137 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen +### Android template +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log/OS Files +*.log + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ +*.iml +.idea/ +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Android Profiling +*.hprof + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..8b6b21b --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,52 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.ray650128.easywindowtest" + compileSdk = 33 + + defaultConfig { + applicationId = "com.ray650128.easywindowtest" + minSdk = 26 + targetSdk = 33 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + viewBinding { + enable = true + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.9.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.9.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + + implementation("com.github.getActivity:EasyWindow:10.2") +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/ray650128/easywindowtest/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/ray650128/easywindowtest/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..62e1766 --- /dev/null +++ b/app/src/androidTest/java/com/ray650128/easywindowtest/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.ray650128.easywindowtest + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.ray650128.easywindowtest", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d77cd08 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/ray650128/easywindowtest/MainActivity.kt b/app/src/main/java/com/ray650128/easywindowtest/MainActivity.kt new file mode 100644 index 0000000..d0ff28b --- /dev/null +++ b/app/src/main/java/com/ray650128/easywindowtest/MainActivity.kt @@ -0,0 +1,111 @@ +package com.ray650128.easywindowtest + +import android.app.Activity +import android.content.Intent +import android.net.Uri +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.provider.Settings +import android.util.Log +import android.view.Gravity +import android.view.MotionEvent +import android.view.View +import android.view.WindowManager +import android.widget.TextView +import androidx.activity.result.contract.ActivityResultContracts +import com.hjq.window.EasyWindow +import com.ray650128.easywindowtest.databinding.ActivityMainBinding + +class MainActivity : AppCompatActivity() { + + private lateinit var binding: ActivityMainBinding + + 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 + return@registerForActivityResult + } + showOverlayWindow() + } + } + + private var isFloatWindowShowing = false + + private val window by lazy { + 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 { + 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 { + showOverlayWindow() + } + + binding.btnStep3.isEnabled = isFloatWindowShowing + binding.btnStep3.setOnClickListener { + hideOverlayWindow() + } + } + + private fun showOverlayWindow() { + isFloatWindowShowing = true + binding.btnStep2.isEnabled = !isFloatWindowShowing + binding.btnStep3.isEnabled = isFloatWindowShowing + window.show() + } + + private fun hideOverlayWindow() { + isFloatWindowShowing = false + binding.btnStep2.isEnabled = !isFloatWindowShowing + binding.btnStep3.isEnabled = isFloatWindowShowing + window.cancel() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ray650128/easywindowtest/MovingDraggable.kt b/app/src/main/java/com/ray650128/easywindowtest/MovingDraggable.kt new file mode 100644 index 0000000..be123e6 --- /dev/null +++ b/app/src/main/java/com/ray650128/easywindowtest/MovingDraggable.kt @@ -0,0 +1,68 @@ +package com.ray650128.easywindowtest + +import android.annotation.SuppressLint +import android.view.MotionEvent +import android.view.View +import android.view.WindowManager +import com.hjq.window.EasyWindow +import com.hjq.window.draggable.BaseDraggable + +/** + * author : Raymond Yang + * time : 2023/07/03 + * desc : 移動拖曳處理實現類別 + */ +class MovingDraggable(private val window: EasyWindow<*>) : BaseDraggable() { + /** 手指按下的座標 */ + private var mViewDownX = 0f + private var mViewDownY = 0f + + /** 觸控移動標記 */ + private var mMoveTouch = false + @SuppressLint("ClickableViewAccessibility") + override fun onTouch(v: View, event: MotionEvent): Boolean { + 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() + // 記錄按下的位置(相對 View 的座標) + mViewDownX = event.x + mViewDownY = event.y + mMoveTouch = false + } + + MotionEvent.ACTION_MOVE -> { + // 記錄移動的位置(相對螢幕的座標) + val rawMoveX = event.rawX - windowInvisibleWidth + val rawMoveY = event.rawY - windowInvisibleHeight + var newX = rawMoveX - mViewDownX + var newY = rawMoveY - mViewDownY + if (newX < 0) { + newX = 0f + } + if (newY < 0) { + newY = 0f + } + + // 更新移動的位置 + updateLocation(newX, newY) + if (!mMoveTouch && isFingerMove(mViewDownX, event.x, mViewDownY, event.y)) { + // 如果使用者移動了手指,那麼就攔截本次觸控事件,從而不讓點選事件生效 + mMoveTouch = true + } + } + + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> return mMoveTouch + 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() + } + else -> {} + } + return true + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_window.xml b/app/src/main/res/drawable/bg_window.xml new file mode 100644 index 0000000..767fb89 --- /dev/null +++ b/app/src/main/res/drawable/bg_window.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_chicken.png b/app/src/main/res/drawable/ic_chicken.png new file mode 100644 index 0000000000000000000000000000000000000000..0fdd5fd881516acf45f551e375003770080d25bd GIT binary patch literal 13806 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..6df2c5d --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,39 @@ + + + +