This commit is contained in:
Josia Pietsch 2025-05-24 22:51:11 +02:00
parent 85a7ed24ab
commit 3b70416b66
Signed by: jrpie
GPG key ID: E70B571D66986A2D
6 changed files with 149 additions and 100 deletions

View file

@ -1,5 +1,6 @@
package de.jrpie.android.launcher.actions package de.jrpie.android.launcher.actions
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Rect import android.graphics.Rect
@ -25,11 +26,18 @@ class WidgetPanelAction(val widgetPanelId: Int) : Action {
override fun invoke(context: Context, rect: Rect?): Boolean { override fun invoke(context: Context, rect: Rect?): Boolean {
if (WidgetPanel.byId(widgetPanelId) == null) { if (context is WidgetPanelActivity) {
if (context.widgetPanelId == widgetPanelId) {
context.finish()
return true
}
}
if (WidgetPanel.byId(this.widgetPanelId) == null) {
Toast.makeText(context, R.string.alert_widget_panel_not_found, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.alert_widget_panel_not_found, Toast.LENGTH_LONG).show()
} else { } else {
context.startActivity(Intent(context, WidgetPanelActivity::class.java).also { context.startActivity(Intent(context, WidgetPanelActivity::class.java).also {
it.putExtra(EXTRA_PANEL_ID, widgetPanelId) it.putExtra(EXTRA_PANEL_ID, this.widgetPanelId)
}) })
} }
return true return true

View file

@ -1,16 +1,9 @@
package de.jrpie.android.launcher.ui package de.jrpie.android.launcher.ui
import android.annotation.SuppressLint
import android.app.Activity
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View import android.view.View
import android.window.OnBackInvokedDispatcher
import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Action
import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.Gesture
@ -19,6 +12,7 @@ import de.jrpie.android.launcher.databinding.ActivityHomeBinding
import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.openTutorial
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.tutorial.TutorialActivity import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
import de.jrpie.android.launcher.ui.util.LauncherGestureActivity
/** /**
* [HomeActivity] is the actual application Launcher, * [HomeActivity] is the actual application Launcher,
@ -32,10 +26,9 @@ import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
* - Setting global variables (preferences etc.) * - Setting global variables (preferences etc.)
* - Opening the [TutorialActivity] on new installations * - Opening the [TutorialActivity] on new installations
*/ */
class HomeActivity : UIObject, Activity() { class HomeActivity : UIObject, LauncherGestureActivity() {
private lateinit var binding: ActivityHomeBinding private lateinit var binding: ActivityHomeBinding
private var touchGestureDetector: TouchGestureDetector? = null
private var sharedPreferencesListener = private var sharedPreferencesListener =
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey -> SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
@ -54,35 +47,21 @@ class HomeActivity : UIObject, Activity() {
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super<Activity>.onCreate(savedInstanceState) super<LauncherGestureActivity>.onCreate(savedInstanceState)
super<UIObject>.onCreate() super<UIObject>.onCreate()
// Initialise layout // Initialise layout
binding = ActivityHomeBinding.inflate(layoutInflater) binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
// Handle back key / gesture on Android 13+, cf. onKeyDown()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_OVERLAY
) {
handleBack()
}
}
binding.buttonFallbackSettings.setOnClickListener { binding.buttonFallbackSettings.setOnClickListener {
LauncherAction.SETTINGS.invoke(this) LauncherAction.SETTINGS.invoke(this)
} }
} }
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
touchGestureDetector?.updateScreenSize(windowManager)
}
override fun onStart() { override fun onStart() {
super<Activity>.onStart() super<LauncherGestureActivity>.onStart()
super<UIObject>.onStart() super<UIObject>.onStart()
// If the tutorial was not finished, start it // If the tutorial was not finished, start it
@ -133,82 +112,30 @@ class HomeActivity : UIObject, Activity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
/* This should be initialized in onCreate()
However on some devices there seems to be a bug where the touchGestureDetector
is not working properly after resuming the app.
Reinitializing the touchGestureDetector every time the app is resumed might help to fix that.
(see issue #138)
*/
touchGestureDetector = TouchGestureDetector(
this, 0, 0,
LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f
).also {
it.updateScreenSize(windowManager)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
binding.root.setOnApplyWindowInsetsListener { _, windowInsets ->
@Suppress("deprecation") // required to support API 29
val insets = windowInsets.systemGestureInsets
touchGestureDetector?.setSystemGestureInsets(insets)
windowInsets
}
}
updateSettingsFallbackButtonVisibility() updateSettingsFallbackButtonVisibility()
binding.homeWidgetContainer.updateWidgets(this@HomeActivity, binding.homeWidgetContainer.updateWidgets(this@HomeActivity,
LauncherPreferences.widgets().widgets() LauncherPreferences.widgets().widgets()
) )
(application as Application).appWidgetHost.startListening() (application as Application).appWidgetHost.startListening()
} }
override fun onDestroy() { override fun onDestroy() {
LauncherPreferences.getSharedPreferences() LauncherPreferences.getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener) .unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener)
super.onDestroy() super.onDestroy()
} }
@SuppressLint("GestureBackNavigation") override fun handleBack() {
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_BACK -> {
// Only used pre Android 13, cf. onBackInvokedDispatcher
handleBack()
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if (Action.forGesture(Gesture.VOLUME_UP) == LauncherAction.VOLUME_UP) {
// Let the OS handle the key event. This works better with some custom ROMs
// and apps like Samsung Sound Assistant.
return false
}
Gesture.VOLUME_UP(this)
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if (Action.forGesture(Gesture.VOLUME_DOWN) == LauncherAction.VOLUME_DOWN) {
// see above
return false
}
Gesture.VOLUME_DOWN(this)
}
}
return true
}
override fun onTouchEvent(event: MotionEvent): Boolean {
touchGestureDetector?.onTouchEvent(event)
return true
}
private fun handleBack() {
Gesture.BACK(this) Gesture.BACK(this)
} }
override fun getRootView(): View {
return binding.root
}
override fun isHomeScreen(): Boolean { override fun isHomeScreen(): Boolean {
return true return true
} }

View file

@ -0,0 +1,104 @@
package de.jrpie.android.launcher.ui.util
import android.annotation.SuppressLint
import android.app.Activity
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.window.OnBackInvokedDispatcher
import de.jrpie.android.launcher.actions.Action
import de.jrpie.android.launcher.actions.Gesture
import de.jrpie.android.launcher.actions.LauncherAction
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.TouchGestureDetector
/**
* An activity with a [TouchGestureDetector] as well as handling of volume and back keys set up.
*/
abstract class LauncherGestureActivity: Activity() {
protected var touchGestureDetector: TouchGestureDetector? = null
override fun onTouchEvent(event: MotionEvent): Boolean {
touchGestureDetector?.onTouchEvent(event)
return true
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Handle back key / gesture on Android 13+, cf. onKeyDown()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_OVERLAY
) {
handleBack()
}
}
}
override fun onResume() {
super.onResume()
/* This should be initialized in onCreate()
However on some devices there seems to be a bug where the touchGestureDetector
is not working properly after resuming the app.
Reinitializing the touchGestureDetector every time the app is resumed might help to fix that.
(see issue #138)
*/
touchGestureDetector = TouchGestureDetector(
this, 0, 0,
LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f
).also {
it.updateScreenSize(windowManager)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
getRootView()?.setOnApplyWindowInsetsListener { _, windowInsets ->
@Suppress("deprecation") // required to support API 29
val insets = windowInsets.systemGestureInsets
touchGestureDetector?.setSystemGestureInsets(insets)
windowInsets
}
}
}
@SuppressLint("GestureBackNavigation")
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_BACK -> {
// Only used pre Android 13, cf. onBackInvokedDispatcher
handleBack()
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if (Action.forGesture(Gesture.VOLUME_UP) == LauncherAction.VOLUME_UP) {
// Let the OS handle the key event. This works better with some custom ROMs
// and apps like Samsung Sound Assistant.
return false
}
Gesture.VOLUME_UP(this)
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if (Action.forGesture(Gesture.VOLUME_DOWN) == LauncherAction.VOLUME_DOWN) {
// see above
return false
}
Gesture.VOLUME_DOWN(this)
}
}
return true
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
touchGestureDetector?.updateScreenSize(windowManager)
}
protected abstract fun getRootView(): View?
protected abstract fun handleBack()
}

View file

@ -8,9 +8,11 @@ import androidx.core.view.isVisible
import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.Gesture
import de.jrpie.android.launcher.databinding.WidgetClockBinding import de.jrpie.android.launcher.databinding.WidgetClockBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.widgets.WidgetPanel
import java.util.Locale import java.util.Locale
class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int): ConstraintLayout(context, attrs) { class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int, val panelId: Int): ConstraintLayout(context, attrs) {
constructor(context: Context, attrs: AttributeSet?): this(context, attrs, WidgetPanel.HOME.id, -1)
val binding: WidgetClockBinding = WidgetClockBinding.inflate(LayoutInflater.from(context), this, true) val binding: WidgetClockBinding = WidgetClockBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
@ -57,7 +59,7 @@ class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId:
binding.clockUpperView.format12Hour = upperFormat binding.clockUpperView.format12Hour = upperFormat
} }
fun setOnClicks() { private fun setOnClicks() {
binding.clockUpperView.setOnClickListener { binding.clockUpperView.setOnClickListener {
if (LauncherPreferences.clock().flipDateTime()) { if (LauncherPreferences.clock().flipDateTime()) {
Gesture.TIME(context) Gesture.TIME(context)
@ -74,7 +76,4 @@ class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId:
} }
} }
} }
} }

View file

@ -1,27 +1,31 @@
package de.jrpie.android.launcher.ui.widgets package de.jrpie.android.launcher.ui.widgets
import android.app.Activity
import android.content.res.Resources import android.content.res.Resources
import android.os.Bundle import android.os.Bundle
import android.view.View
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.databinding.ActivityWidgetPanelBinding import de.jrpie.android.launcher.databinding.ActivityWidgetPanelBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.UIObject import de.jrpie.android.launcher.ui.UIObject
import de.jrpie.android.launcher.ui.util.LauncherGestureActivity
import de.jrpie.android.launcher.ui.widgets.manage.EXTRA_PANEL_ID import de.jrpie.android.launcher.ui.widgets.manage.EXTRA_PANEL_ID
import de.jrpie.android.launcher.widgets.WidgetPanel import de.jrpie.android.launcher.widgets.WidgetPanel
class WidgetPanelActivity : Activity(), UIObject { class WidgetPanelActivity : LauncherGestureActivity(), UIObject {
lateinit var binding: ActivityWidgetPanelBinding var binding: ActivityWidgetPanelBinding? = null
private var widgetPanelId: Int = WidgetPanel.HOME.id
var widgetPanelId: Int = WidgetPanel.HOME.id
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super<Activity>.onCreate(savedInstanceState) super<LauncherGestureActivity>.onCreate(savedInstanceState)
super<UIObject>.onCreate() super<UIObject>.onCreate()
widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id)
val binding = ActivityWidgetPanelBinding.inflate(layoutInflater) val binding = ActivityWidgetPanelBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id)
// The widget container should extend below the status and navigation bars, // The widget container should extend below the status and navigation bars,
// so let's set an empty WindowInsetsListener to prevent it from being moved. // so let's set an empty WindowInsetsListener to prevent it from being moved.
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets -> ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
@ -56,9 +60,8 @@ class WidgetPanelActivity : Activity(), UIObject {
} }
override fun onStart() { override fun onStart() {
super<Activity>.onStart() super<LauncherGestureActivity>.onStart()
super<UIObject>.onStart() super<UIObject>.onStart()
} }
override fun onPause() { override fun onPause() {
@ -76,6 +79,14 @@ class WidgetPanelActivity : Activity(), UIObject {
(application as Application).appWidgetHost.startListening() (application as Application).appWidgetHost.startListening()
} }
override fun getRootView(): View? {
return binding?.root
}
override fun handleBack() {
finish()
}
override fun isHomeScreen(): Boolean { override fun isHomeScreen(): Boolean {
return true return true
} }

View file

@ -18,8 +18,8 @@ class ClockWidget(
override var allowInteraction: Boolean = true override var allowInteraction: Boolean = true
) : Widget() { ) : Widget() {
override fun createView(activity: Activity): View? { override fun createView(activity: Activity): View {
return ClockView(activity, null, id) return ClockView(activity, null, id, panelId)
} }
override fun findView(views: Sequence<View>): ClockView? { override fun findView(views: Sequence<View>): ClockView? {