Migrate from Kotlin synthetics to Jetpack view binding

This commit is contained in:
MM20 2021-12-11 14:46:46 +01:00
parent 299d421e5c
commit 89a2754eaf
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
49 changed files with 423 additions and 431 deletions

View File

@ -4,7 +4,6 @@ import java.util.*
plugins { plugins {
id("com.android.application") id("com.android.application")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -14,7 +14,7 @@ import androidx.preference.PreferenceFragmentCompat
import de.mm20.launcher2.R import de.mm20.launcher2.R
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import kotlinx.android.synthetic.main.fragment_card_settings.* import de.mm20.launcher2.ui.legacy.view.LauncherCardView
import kotlin.math.roundToInt import kotlin.math.roundToInt
class PreferencesCardFragment : Fragment(R.layout.fragment_card_settings) { class PreferencesCardFragment : Fragment(R.layout.fragment_card_settings) {
@ -23,12 +23,9 @@ class PreferencesCardFragment : Fragment(R.layout.fragment_card_settings) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val previewCard = view.findViewById<LauncherCardView>(R.id.previewCard)
previewCard.strokeOpacity = 0xFF previewCard.strokeOpacity = 0xFF
val context = requireContext()
val previewCard = previewCard
val prefFragment = PreferenesCardInnerFragment() val prefFragment = PreferenesCardInnerFragment()
prefFragment.onPreferencesReady = { prefFragment.onPreferencesReady = {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
id("kotlin-kapt") id("kotlin-kapt")
} }

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
id("kotlin-kapt") id("kotlin-kapt")
} }

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {
@ -30,6 +29,10 @@ android {
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
buildFeatures {
viewBinding = true
}
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = "1.8"
} }

View File

@ -2,36 +2,40 @@ package de.mm20.launcher2.nextcloud
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.webkit.WebResourceRequest import android.webkit.WebResourceRequest
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_nextcloud_login.* import de.mm20.launcher2.nextcloud.databinding.ActivityNextcloudLoginBinding
import kotlinx.coroutines.* import kotlinx.coroutines.*
class LoginActivity : AppCompatActivity() { class LoginActivity : AppCompatActivity() {
private val nextcloudClient = NextcloudApiHelper(this) private val nextcloudClient = NextcloudApiHelper(this)
private lateinit var binding: ActivityNextcloudLoginBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_nextcloud_login) binding = ActivityNextcloudLoginBinding.inflate(LayoutInflater.from(this))
nextButton.setOnClickListener { setContentView(binding.root)
serverUrlInputLayout.error = null binding.nextButton.setOnClickListener {
binding.serverUrlInputLayout.error = null
lifecycleScope.launch { lifecycleScope.launch {
var url = serverUrlInput.text.toString() var url = binding.serverUrlInput.text.toString()
if (!(url.startsWith("http://") || url.startsWith("https://"))) { if (!(url.startsWith("http://") || url.startsWith("https://"))) {
url = "https://$url" url = "https://$url"
} }
if (url.isBlank()) { if (url.isBlank()) {
serverUrlInputLayout.error = getString(R.string.next_cloud_server_url_empty) binding.serverUrlInputLayout.error = getString(R.string.next_cloud_server_url_empty)
return@launch return@launch
} }
if (nextcloudClient.checkNextcloudInstallation(url)) { if (nextcloudClient.checkNextcloudInstallation(url)) {
openLoginPage(url) openLoginPage(url)
} else { } else {
serverUrlInputLayout.error = getString(R.string.next_cloud_server_invalid_url) binding.serverUrlInputLayout.error = getString(R.string.next_cloud_server_invalid_url)
} }
} }
} }

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {
@ -33,6 +32,10 @@ android {
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = "1.8"
} }
buildFeatures {
viewBinding = true
}
} }
dependencies { dependencies {

View File

@ -2,10 +2,11 @@ package de.mm20.launcher2.owncloud
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_owncloud_login.* import de.mm20.launcher2.owncloud.databinding.ActivityOwncloudLoginBinding
import kotlinx.android.synthetic.main.activity_owncloud_login_username_password.* import de.mm20.launcher2.owncloud.databinding.ActivityOwncloudLoginUsernamePasswordBinding
import kotlinx.coroutines.* import kotlinx.coroutines.*
class LoginActivity : AppCompatActivity() { class LoginActivity : AppCompatActivity() {
@ -14,37 +15,39 @@ class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_owncloud_login) val binding = ActivityOwncloudLoginBinding.inflate(LayoutInflater.from(this))
nextButton.setOnClickListener { setContentView(binding.root)
serverUrlInputLayout.error = null binding.nextButton.setOnClickListener {
binding.serverUrlInputLayout.error = null
lifecycleScope.launch { lifecycleScope.launch {
var url = serverUrlInput.text.toString() var url = binding.serverUrlInput.text.toString()
if (!(url.startsWith("http://") || url.startsWith("https://"))) { if (!(url.startsWith("http://") || url.startsWith("https://"))) {
url = "https://$url" url = "https://$url"
} }
if (url.isBlank()) { if (url.isBlank()) {
serverUrlInputLayout.error = getString(R.string.next_cloud_server_url_empty) binding.serverUrlInputLayout.error = getString(R.string.next_cloud_server_url_empty)
return@launch return@launch
} }
if (owncloudClient.checkOwncloudInstallation(url)) { if (owncloudClient.checkOwncloudInstallation(url)) {
openLoginPage(url) openLoginPage(url)
} else { } else {
serverUrlInputLayout.error = getString(R.string.owncloud_server_invalid_url) binding.serverUrlInputLayout.error = getString(R.string.owncloud_server_invalid_url)
} }
} }
} }
} }
private fun openLoginPage(url: String) { private fun openLoginPage(url: String) {
setContentView(R.layout.activity_owncloud_login_username_password) val binding = ActivityOwncloudLoginUsernamePasswordBinding.inflate(LayoutInflater.from(this))
loginButton.setOnClickListener { setContentView(binding.root)
val username = username.text.toString() binding.loginButton.setOnClickListener {
val password = password.text.toString() val username = binding.username.text.toString()
val password = binding.password.text.toString()
if (username.isEmpty()) { if (username.isEmpty()) {
usernameInputLayout.error = getString(R.string.owncloud_username_empty) binding.usernameInputLayout.error = getString(R.string.owncloud_username_empty)
} }
if (password.isEmpty()) { if (password.isEmpty()) {
passwordInputLayout.error = getString(R.string.owncloud_password_empty) binding.passwordInputLayout.error = getString(R.string.owncloud_password_empty)
} }
if(username.isEmpty() || password.isEmpty()) { if(username.isEmpty() || password.isEmpty()) {
return@setOnClickListener return@setOnClickListener
@ -54,7 +57,7 @@ class LoginActivity : AppCompatActivity() {
setResult(Activity.RESULT_OK) setResult(Activity.RESULT_OK)
finish() finish()
} else { } else {
passwordInputLayout.error = getString(R.string.owncloud_login_failed) binding.passwordInputLayout.error = getString(R.string.owncloud_login_failed)
} }
} }
} }

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {
@ -36,6 +35,7 @@ android {
buildFeatures { buildFeatures {
// Enables Jetpack Compose for this module // Enables Jetpack Compose for this module
compose = true compose = true
viewBinding = true
} }
composeOptions { composeOptions {

View File

@ -12,19 +12,15 @@ import android.content.ActivityNotFoundException
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color import android.graphics.Color
import android.graphics.Point import android.graphics.Point
import android.os.Bundle import android.os.Bundle
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.MotionEvent import android.view.*
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.ViewGroupOverlay
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.LinearLayout import android.widget.LinearLayout
@ -60,6 +56,7 @@ import de.mm20.launcher2.search.SearchViewModel
import de.mm20.launcher2.transition.ChangingLayoutTransition import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.transition.OneShotLayoutTransition import de.mm20.launcher2.transition.OneShotLayoutTransition
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ActivityLauncherBinding
import de.mm20.launcher2.ui.legacy.component.EditFavoritesView import de.mm20.launcher2.ui.legacy.component.EditFavoritesView
import de.mm20.launcher2.ui.legacy.component.WidgetView import de.mm20.launcher2.ui.legacy.component.WidgetView
import de.mm20.launcher2.ui.legacy.search.SearchGridView import de.mm20.launcher2.ui.legacy.search.SearchGridView
@ -68,7 +65,6 @@ import de.mm20.launcher2.weather.WeatherViewModel
import de.mm20.launcher2.widgets.Widget import de.mm20.launcher2.widgets.Widget
import de.mm20.launcher2.widgets.WidgetType import de.mm20.launcher2.widgets.WidgetType
import de.mm20.launcher2.widgets.WidgetViewModel import de.mm20.launcher2.widgets.WidgetViewModel
import kotlinx.android.synthetic.main.activity_launcher.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
@ -98,23 +94,23 @@ class LauncherActivity : AppCompatActivity() {
set(value) { set(value) {
field = value field = value
if (value) { if (value) {
widgetSpacer.visibility = View.GONE binding.widgetSpacer.visibility = View.GONE
smartWidget.visibility = View.GONE binding.smartWidget.visibility = View.GONE
searchBar.setRightIcon(R.drawable.ic_done) binding.searchBar.setRightIcon(R.drawable.ic_done)
scrollView.setOnTouchListener(null) binding.scrollView.setOnTouchListener(null)
for (v in widgetList.iterator()) { for (v in binding.widgetList.iterator()) {
if (v is WidgetView) { if (v is WidgetView) {
v.editMode = true v.editMode = true
v.onResizeModeChange = { v.onResizeModeChange = {
OneShotLayoutTransition.run(widgetList) OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(widgetContainer) OneShotLayoutTransition.run(binding.widgetContainer)
} }
} }
} }
OneShotLayoutTransition.run(widgetList) OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(widgetContainer) OneShotLayoutTransition.run(binding.widgetContainer)
OneShotLayoutTransition.run(scrollContainer) OneShotLayoutTransition.run(binding.scrollContainer)
fabEditWidget.apply { binding.fabEditWidget.apply {
setIconResource(R.drawable.ic_add) setIconResource(R.drawable.ic_add)
setText(R.string.widget_add_widget) setText(R.string.widget_add_widget)
setOnClickListener { setOnClickListener {
@ -133,31 +129,31 @@ class LauncherActivity : AppCompatActivity() {
val insetsController = WindowInsetsControllerCompat(window, window.decorView) val insetsController = WindowInsetsControllerCompat(window, window.decorView)
insetsController.isAppearanceLightStatusBars = true insetsController.isAppearanceLightStatusBars = true
} }
searchBar.visibility = View.INVISIBLE binding.searchBar.visibility = View.INVISIBLE
editWidgetToolbar binding.editWidgetToolbar
.animate() .animate()
.translationY(0f) .translationY(0f)
.alpha(1f) .alpha(1f)
.withStartAction { .withStartAction {
editWidgetToolbar.visibility = View.VISIBLE binding.editWidgetToolbar.visibility = View.VISIBLE
} }
.start() .start()
} else { } else {
widgetViewModel.saveWidgets(widgets) widgetViewModel.saveWidgets(widgets)
widgetSpacer.visibility = View.VISIBLE binding.widgetSpacer.visibility = View.VISIBLE
widgetList.layoutTransition = ChangingLayoutTransition() binding.widgetList.layoutTransition = ChangingLayoutTransition()
widgetContainer.layoutTransition = ChangingLayoutTransition() binding.widgetContainer.layoutTransition = ChangingLayoutTransition()
scrollContainer.layoutTransition = ChangingLayoutTransition() binding.scrollContainer.layoutTransition = ChangingLayoutTransition()
searchBar.setRightIcon(R.drawable.ic_more_vert) binding.searchBar.setRightIcon(R.drawable.ic_more_vert)
scrollView.setOnTouchListener(scrollViewOnTouchListener) binding.scrollView.setOnTouchListener(scrollViewOnTouchListener)
smartWidget.visibility = View.VISIBLE binding.smartWidget.visibility = View.VISIBLE
for (v in widgetList.iterator()) { for (v in binding.widgetList.iterator()) {
if (v is WidgetView) { if (v is WidgetView) {
v.editMode = false v.editMode = false
v.layoutTransition = ChangingLayoutTransition() v.layoutTransition = ChangingLayoutTransition()
} }
} }
fabEditWidget.apply { binding.fabEditWidget.apply {
setIconResource(R.drawable.ic_edit) setIconResource(R.drawable.ic_edit)
setText(R.string.menu_edit_widgets) setText(R.string.menu_edit_widgets)
setOnClickListener { setOnClickListener {
@ -168,13 +164,13 @@ class LauncherActivity : AppCompatActivity() {
updateSystemBarAppearance() updateSystemBarAppearance()
searchBar.visibility = View.VISIBLE binding.searchBar.visibility = View.VISIBLE
editWidgetToolbar binding.editWidgetToolbar
.animate() .animate()
.translationY(-editWidgetToolbar.height.toFloat()) .translationY(-binding.editWidgetToolbar.height.toFloat())
.alpha(0f) .alpha(0f)
.withEndAction { .withEndAction {
editWidgetToolbar.visibility = View.GONE binding.editWidgetToolbar.visibility = View.GONE
} }
.start() .start()
} }
@ -188,6 +184,8 @@ class LauncherActivity : AppCompatActivity() {
insetsController.isAppearanceLightStatusBars = insetsController.isAppearanceLightStatusBars =
allowLightSystemBars && preferences.lightStatusBar allowLightSystemBars && preferences.lightStatusBar
} }
private lateinit var binding: ActivityLauncherBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -212,64 +210,65 @@ class LauncherActivity : AppCompatActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
setContentView(R.layout.activity_launcher) binding = ActivityLauncherBinding.inflate(LayoutInflater.from(this))
setContentView(binding.root)
overlayView = rootView.overlay overlayView = binding.rootView.overlay
if (LauncherPreferences.instance.dimWallpaper) { if (LauncherPreferences.instance.dimWallpaper) {
dimWallpaper.setBackgroundColor(getColor(R.color.wallpaper_dim)) binding.dimWallpaper.setBackgroundColor(getColor(R.color.wallpaper_dim))
} }
scrollContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING) binding.scrollContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
searchContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING) binding.searchContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
widgetContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING) binding.widgetContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
val params = widgetSpacer.layoutParams as LinearLayout.LayoutParams val params = binding.widgetSpacer.layoutParams as LinearLayout.LayoutParams
params.topMargin = Point().also { windowManager.defaultDisplay.getSize(it) }.y params.topMargin = Point().also { windowManager.defaultDisplay.getSize(it) }.y
widgetSpacer.layoutParams = params binding.widgetSpacer.layoutParams = params
container.doOnLayout { binding.container.doOnLayout {
adjustWidgetSpace() adjustWidgetSpace()
} }
initWidgets() initWidgets()
scrollView.setOnTouchListener(scrollViewOnTouchListener) binding.scrollView.setOnTouchListener(scrollViewOnTouchListener)
scrollView.setOnScrollChangeListener { _: NestedScrollView?, _: Int, scrollY: Int, _: Int, oldScrollY: Int -> binding.scrollView.setOnScrollChangeListener { _: NestedScrollView?, _: Int, scrollY: Int, _: Int, oldScrollY: Int ->
when { when {
/* Hide searchbar*/ /* Hide searchbar*/
scrollY > oldScrollY && ((searchVisibility && scrollY > searchBar.height) || widgetEditMode || scrollY > oldScrollY && ((searchVisibility && scrollY > binding.searchBar.height) || widgetEditMode ||
scrollY > widgetSpacer.height + searchBar.height scrollY > binding.widgetSpacer.height + binding.searchBar.height
+ (widgetSpacer.layoutParams as LinearLayout.LayoutParams).topMargin) -> { + (binding.widgetSpacer.layoutParams as LinearLayout.LayoutParams).topMargin) -> {
var newTransY = searchBar.translationY - scrollY + oldScrollY var newTransY = binding.searchBar.translationY - scrollY + oldScrollY
if (newTransY < -searchBar.height.toFloat() * 1.5f) { if (newTransY < -binding.searchBar.height.toFloat() * 1.5f) {
newTransY = -searchBar.height.toFloat() * 1.5f newTransY = -binding.searchBar.height.toFloat() * 1.5f
} }
searchBar.translationY = newTransY binding.searchBar.translationY = newTransY
} }
/* Show searchbar*/ /* Show searchbar*/
scrollY < oldScrollY -> { scrollY < oldScrollY -> {
var newTransY = searchBar.translationY - scrollY + oldScrollY var newTransY = binding.searchBar.translationY - scrollY + oldScrollY
if (newTransY > 0f) { if (newTransY > 0f) {
newTransY = 0f newTransY = 0f
} }
searchBar.translationY = newTransY binding.searchBar.translationY = newTransY
} }
} }
if (scrollY > 0 && (searchVisibility || widgetEditMode || if (scrollY > 0 && (searchVisibility || widgetEditMode ||
scrollY > widgetSpacer.height scrollY > binding.widgetSpacer.height
+ (widgetSpacer.layoutParams as LinearLayout.LayoutParams).topMargin) + (binding.widgetSpacer.layoutParams as LinearLayout.LayoutParams).topMargin)
) { ) {
searchBar.raise() binding.searchBar.raise()
} else searchBar.drop() } else binding.searchBar.drop()
if (scrollY == 0) { if (scrollY == 0) {
smartWidget.translucent = true binding.smartWidget.translucent = true
if (!searchVisibility) searchBar.hide() if (!searchVisibility) binding.searchBar.hide()
} else { } else {
smartWidget.translucent = false binding.smartWidget.translucent = false
searchBar.show() binding.searchBar.show()
} }
} }
searchBar.onRightIconClick = onRightIconClick@{ binding.searchBar.onRightIconClick = onRightIconClick@{
if (widgetEditMode) widgetEditMode = false if (widgetEditMode) widgetEditMode = false
else { else {
val menu = PopupMenu(this, it) val menu = PopupMenu(this, it)
@ -339,21 +338,21 @@ class LauncherActivity : AppCompatActivity() {
menu.show() menu.show()
} }
} }
searchBar.setOnTouchListener { _, _ -> binding.searchBar.setOnTouchListener { _, _ ->
if (!searchVisibility) showSearch() if (!searchVisibility) showSearch()
false false
} }
searchBar.onSearchQueryChanged = { binding.searchBar.onSearchQueryChanged = {
search(it) search(it)
} }
widgetList.layoutTransition.enableTransitionType(LayoutTransition.CHANGING) binding.widgetList.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
fabEditWidget.setOnClickListener { binding.fabEditWidget.setOnClickListener {
widgetEditMode = true widgetEditMode = true
} }
editWidgetToolbar.apply { binding.editWidgetToolbar.apply {
navigationIcon = navigationIcon =
ContextCompat.getDrawable(this@LauncherActivity, R.drawable.ic_done)?.apply { ContextCompat.getDrawable(this@LauncherActivity, R.drawable.ic_done)?.apply {
setTint(ContextCompat.getColor(this@LauncherActivity, R.color.icon_color)) setTint(ContextCompat.getColor(this@LauncherActivity, R.color.icon_color))
@ -376,7 +375,7 @@ class LauncherActivity : AppCompatActivity() {
private fun initWidgets() { private fun initWidgets() {
widgetHost = AppWidgetHost(applicationContext, 0xacab) widgetHost = AppWidgetHost(applicationContext, 0xacab)
widgetList.removeAllViews() binding.widgetList.removeAllViews()
val params = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT) val params = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
params.topMargin = (8 * dp).roundToInt() params.topMargin = (8 * dp).roundToInt()
for (w in widgets) { for (w in widgets) {
@ -384,21 +383,21 @@ class LauncherActivity : AppCompatActivity() {
view.layoutTransition = ChangingLayoutTransition() view.layoutTransition = ChangingLayoutTransition()
view.layoutParams = params view.layoutParams = params
if (view.setWidget(w, widgetHost)) { if (view.setWidget(w, widgetHost)) {
widgetList.addDragView(view, view.getDragHandle()) binding.widgetList.addDragView(view, view.getDragHandle())
view.onRemove = { view.onRemove = {
OneShotLayoutTransition.run(widgetList) OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(widgetContainer) OneShotLayoutTransition.run(binding.widgetContainer)
widgetList.removeDragView(view) binding.widgetList.removeDragView(view)
removeWidget(view.widget) removeWidget(view.widget)
} }
view.onResizeModeChange = { view.onResizeModeChange = {
OneShotLayoutTransition.run(widgetList) OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(widgetContainer) OneShotLayoutTransition.run(binding.widgetContainer)
} }
} }
} }
widgetList.setOnViewSwapListener { _, firstPosition, _, secondPosition -> binding.widgetList.setOnViewSwapListener { _, firstPosition, _, secondPosition ->
Collections.swap(widgets, firstPosition, secondPosition) Collections.swap(widgets, firstPosition, secondPosition)
} }
updateWidgets() updateWidgets()
@ -463,35 +462,35 @@ class LauncherActivity : AppCompatActivity() {
} }
private fun adjustWidgetSpace() { private fun adjustWidgetSpace() {
val firstWidget = smartWidget val firstWidget = binding.smartWidget
if (firstWidget == null) { if (firstWidget == null) {
val m = scrollContainer.paddingTop val m = binding.scrollContainer.paddingTop
val params = widgetSpacer.layoutParams as LinearLayout.LayoutParams val params = binding.widgetSpacer.layoutParams as LinearLayout.LayoutParams
params.topMargin = params.topMargin =
scrollView.height - m - widgetContainer.paddingTop - widgetSpacer.height binding.scrollView.height - m - binding.widgetContainer.paddingTop - binding.widgetSpacer.height
widgetSpacer.layoutParams = params binding.widgetSpacer.layoutParams = params
return return
} }
val m = scrollContainer.paddingTop + val m = binding.scrollContainer.paddingTop +
(firstWidget.layoutParams as LinearLayout.LayoutParams).run { topMargin + bottomMargin } (firstWidget.layoutParams as LinearLayout.LayoutParams).run { topMargin + bottomMargin }
val params = widgetSpacer.layoutParams as LinearLayout.LayoutParams val params = binding.widgetSpacer.layoutParams as LinearLayout.LayoutParams
params.topMargin = params.topMargin =
scrollView.height - firstWidget.measuredHeight - m - widgetContainer.paddingTop - widgetSpacer.height binding.scrollView.height - firstWidget.measuredHeight - m - binding.widgetContainer.paddingTop - binding.widgetSpacer.height
widgetSpacer.layoutParams = params binding.widgetSpacer.layoutParams = params
} }
private fun search(text: String) { private fun search(text: String) {
searchViewModel.search(text) searchViewModel.search(text)
if (webSearchViewSpacer.tag != "measured" || webSearchViewSpacer.height == 0) { if (binding.webSearchViewSpacer.tag != "measured" || binding.webSearchViewSpacer.height == 0) {
val webSearchView = searchBar.getWebSearchView() val webSearchView = binding.searchBar.getWebSearchView()
webSearchView.doOnNextLayout { webSearchView.doOnNextLayout {
webSearchViewSpacer.layoutParams = webSearchViewSpacer.layoutParams binding.webSearchViewSpacer.layoutParams = binding.webSearchViewSpacer.layoutParams
.apply { height = webSearchView.height } .apply { height = webSearchView.height }
webSearchViewSpacer.tag = "measured" binding.webSearchViewSpacer.tag = "measured"
} }
} }
webSearchViewSpacer.visibility = if (text.isBlank()) View.GONE else View.VISIBLE binding.webSearchViewSpacer.visibility = if (text.isBlank()) View.GONE else View.VISIBLE
} }
private fun toggleSearch() { private fun toggleSearch() {
@ -508,40 +507,40 @@ class LauncherActivity : AppCompatActivity() {
val set = AnimatorSet() val set = AnimatorSet()
set.duration = 300 set.duration = 300
set.doOnEnd { set.doOnEnd {
searchContainer.visibility = View.GONE binding.searchContainer.visibility = View.GONE
widgetContainer.visibility = View.VISIBLE binding.widgetContainer.visibility = View.VISIBLE
} }
set.playTogether( set.playTogether(
ObjectAnimator.ofFloat(widgetContainer, "translationY", 0f), ObjectAnimator.ofFloat(binding.widgetContainer, "translationY", 0f),
ObjectAnimator.ofInt(scrollView, "scrollY", 0), ObjectAnimator.ofInt(binding.scrollView, "scrollY", 0),
ObjectAnimator.ofFloat( ObjectAnimator.ofFloat(
searchContainer, "translationY", 0f, binding.searchContainer, "translationY", 0f,
if (scrollView.scrollY > searchContainer.height / 2f) -searchContainer.height.toFloat() else scrollView.height.toFloat() if (binding.scrollView.scrollY > binding.searchContainer.height / 2f) -binding.searchContainer.height.toFloat() else binding.scrollView.height.toFloat()
) )
) )
set.start() set.start()
scrollView.scrollTo(0, 0) binding.scrollView.scrollTo(0, 0)
searchBar.hide() binding.searchBar.hide()
if (!searchBar.getSearchQuery().isEmpty()) searchBar.setSearchQuery("") if (!binding.searchBar.getSearchQuery().isEmpty()) binding.searchBar.setSearchQuery("")
(getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
.hideSoftInputFromWindow(searchBar.windowToken, 0) .hideSoftInputFromWindow(binding.searchBar.windowToken, 0)
} }
private fun showSearch() { private fun showSearch() {
searchVisibility = true searchVisibility = true
searchBar.show() binding.searchBar.show()
searchContainer.visibility = View.VISIBLE binding.searchContainer.visibility = View.VISIBLE
widgetContainer.visibility = View.GONE binding.widgetContainer.visibility = View.GONE
val set = AnimatorSet() val set = AnimatorSet()
set.duration = 300 set.duration = 300
set.doOnEnd { set.doOnEnd {
search("") search("")
} }
set.playTogether( set.playTogether(
ObjectAnimator.ofFloat(widgetContainer, "translationY", scrollView.height.toFloat()), ObjectAnimator.ofFloat(binding.widgetContainer, "translationY", binding.scrollView.height.toFloat()),
ObjectAnimator.ofInt(scrollView, "scrollY", 0), ObjectAnimator.ofInt(binding.scrollView, "scrollY", 0),
ObjectAnimator.ofFloat(searchContainer, "translationY", scrollView.height.toFloat(), 0f) ObjectAnimator.ofFloat(binding.searchContainer, "translationY", binding.scrollView.height.toFloat(), 0f)
) )
set.start() set.start()
} }
@ -549,7 +548,7 @@ class LauncherActivity : AppCompatActivity() {
override fun onBackPressed() { override fun onBackPressed() {
if (widgetEditMode) widgetEditMode = false if (widgetEditMode) widgetEditMode = false
if (searchVisibility) hideSearch() if (searchVisibility) hideSearch()
else ObjectAnimator.ofInt(scrollView, "scrollY", 0).setDuration(200).start() else ObjectAnimator.ofInt(binding.scrollView, "scrollY", 0).setDuration(200).start()
} }
@ -557,17 +556,17 @@ class LauncherActivity : AppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
ActivityStarter.resume() ActivityStarter.resume()
ActivityStarter.create(rootView) ActivityStarter.create(binding.rootView)
activityStartOverlay.visibility = View.INVISIBLE binding.activityStartOverlay.visibility = View.INVISIBLE
val widgetViewModel by viewModels<WidgetViewModel>() val widgetViewModel by viewModels<WidgetViewModel>()
widgetViewModel.requestCalendarUpdate() widgetViewModel.requestCalendarUpdate()
search(searchBar.getSearchQuery()) search(binding.searchBar.getSearchQuery())
updateWidgets() updateWidgets()
updateSystemBarAppearance() updateSystemBarAppearance()
container.doOnNextLayout { binding.container.doOnNextLayout {
WallpaperManager.getInstance(this).setWallpaperOffsets(it.windowToken, 0.5f, 0.5f) WallpaperManager.getInstance(this).setWallpaperOffsets(it.windowToken, 0.5f, 0.5f)
} }
@ -641,7 +640,7 @@ class LauncherActivity : AppCompatActivity() {
grantResults: IntArray grantResults: IntArray
) { ) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
search(searchBar.getSearchQuery()) search(binding.searchBar.getSearchQuery())
when (requestCode) { when (requestCode) {
PermissionsManager.LOCATION -> { PermissionsManager.LOCATION -> {
ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this) ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this)
@ -652,7 +651,7 @@ class LauncherActivity : AppCompatActivity() {
PermissionsManager.ALL -> { PermissionsManager.ALL -> {
ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this) ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this)
widgetViewModel.requestCalendarUpdate() widgetViewModel.requestCalendarUpdate()
search(searchBar.getSearchQuery()) search(binding.searchBar.getSearchQuery())
} }
} }
} }
@ -661,7 +660,7 @@ class LauncherActivity : AppCompatActivity() {
var topWidget: LauncherWidget? = null var topWidget: LauncherWidget? = null
var topWidgetRanking = 0 var topWidgetRanking = 0
var topWidgetView: WidgetView? = null var topWidgetView: WidgetView? = null
for (widget in widgetList.iterator()) { for (widget in binding.widgetList.iterator()) {
if (widget is WidgetView) { if (widget is WidgetView) {
widget.update() widget.update()
if (topWidgetRanking < widget.widgetView?.compactViewRanking ?: 0) { if (topWidgetRanking < widget.widgetView?.compactViewRanking ?: 0) {
@ -675,11 +674,11 @@ class LauncherActivity : AppCompatActivity() {
compactView?.update() compactView?.update()
compactView?.goToParent = { compactView?.goToParent = {
ObjectAnimator.ofFloat( ObjectAnimator.ofFloat(
scrollView, "scrollY", topWidgetView?.top?.toFloat() binding.scrollView, "scrollY", topWidgetView?.top?.toFloat()
?: 0f ?: 0f
).start() ).start()
} }
smartWidget.compactView = compactView binding.smartWidget.compactView = compactView
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@ -727,16 +726,16 @@ class LauncherActivity : AppCompatActivity() {
if (view.setWidget(widget, widgetHost)) { if (view.setWidget(widget, widgetHost)) {
view.editMode = true view.editMode = true
widgetList.addDragView(view, view.getDragHandle()) binding.widgetList.addDragView(view, view.getDragHandle())
view.onRemove = { view.onRemove = {
OneShotLayoutTransition.run(widgetList) OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(widgetContainer) OneShotLayoutTransition.run(binding.widgetContainer)
widgetList.removeDragView(view) binding.widgetList.removeDragView(view)
removeWidget(view.widget) removeWidget(view.widget)
} }
view.onResizeModeChange = { view.onResizeModeChange = {
OneShotLayoutTransition.run(widgetList) OneShotLayoutTransition.run(binding.widgetList)
OneShotLayoutTransition.run(widgetContainer) OneShotLayoutTransition.run(binding.widgetContainer)
} }
widgets.add(widget) widgets.add(widget)
} }
@ -748,37 +747,37 @@ class LauncherActivity : AppCompatActivity() {
MotionEvent.ACTION_DOWN -> true MotionEvent.ACTION_DOWN -> true
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
when { when {
scrollView.scrollY == 0 -> { binding.scrollView.scrollY == 0 -> {
if (event.historySize > 0) { if (event.historySize > 0) {
val dY = event.y - event.getHistoricalY(0) val dY = event.y - event.getHistoricalY(0)
val newTransY = 0.4f * dY + container.translationY val newTransY = 0.4f * dY + binding.container.translationY
if (newTransY > 0 && newTransY < searchBar.height) { if (newTransY > 0 && newTransY < binding.searchBar.height) {
container.translationY = newTransY binding.container.translationY = newTransY
searchBar.show() binding.searchBar.show()
} else if (newTransY <= 0) { } else if (newTransY <= 0) {
container.translationY = 0f binding.container.translationY = 0f
} else { } else {
container.translationY = searchBar.height.toFloat() binding.container.translationY = binding.searchBar.height.toFloat()
} }
if (container.translationY == 0f) return@onTouch false if (binding.container.translationY == 0f) return@onTouch false
} }
} }
scrollView.scrollY == scrollContainer.height - scrollView.height && searchVisibility -> { binding.scrollView.scrollY == binding.scrollContainer.height - binding.scrollView.height && searchVisibility -> {
if (event.historySize > 0) { if (event.historySize > 0) {
val dY = event.y - event.getHistoricalY(0) val dY = event.y - event.getHistoricalY(0)
val newTransY = 0.4f * dY + container.translationY val newTransY = 0.4f * dY + binding.container.translationY
if (newTransY <= 0 && newTransY > -searchBar.height) { if (newTransY <= 0 && newTransY > -binding.searchBar.height) {
container.translationY = newTransY binding.container.translationY = newTransY
searchBar.show() binding.searchBar.show()
} else if (newTransY > 0) { } else if (newTransY > 0) {
container.translationY = 0f binding.container.translationY = 0f
} else { } else {
container.translationY = -searchBar.height.toFloat() binding.container.translationY = -binding.searchBar.height.toFloat()
} }
if (container.translationY == 0f) return@onTouch false if (binding.container.translationY == 0f) return@onTouch false
} }
} }
else -> return@onTouch false else -> return@onTouch false
@ -786,10 +785,10 @@ class LauncherActivity : AppCompatActivity() {
true true
} }
MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> {
if (container.translationY >= searchBar.height * 0.6) toggleSearch() if (binding.container.translationY >= binding.searchBar.height * 0.6) toggleSearch()
if (container.translationY <= -searchBar.height) hideSearch() if (binding.container.translationY <= -binding.searchBar.height) hideSearch()
container.animate().translationY(0f).setDuration(200).start() binding.container.animate().translationY(0f).setDuration(200).start()
if (!searchVisibility && scrollView.scrollY == 0) searchBar.hide() if (!searchVisibility && binding.scrollView.scrollY == 0) binding.searchBar.hide()
false false
} }
else -> false else -> false

View File

@ -3,14 +3,14 @@ package de.mm20.launcher2.ui.legacy.component
import android.animation.LayoutTransition import android.animation.LayoutTransition
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.* import androidx.lifecycle.*
import de.mm20.launcher2.applications.AppViewModel import de.mm20.launcher2.applications.AppViewModel
import de.mm20.launcher2.search.data.Application import de.mm20.launcher2.search.data.Application
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.databinding.ViewApplicationBinding
import kotlinx.android.synthetic.main.view_application.view.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
class ApplicationView : FrameLayout { class ApplicationView : FrameLayout {
@ -21,16 +21,17 @@ class ApplicationView : FrameLayout {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
private val binding = ViewApplicationBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
View.inflate(context, R.layout.view_application, this)
layoutTransition = LayoutTransition() layoutTransition = LayoutTransition()
layoutTransition.enableTransitionType(LayoutTransition.CHANGING) layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
applicationCard.layoutTransition.enableTransitionType(LayoutTransition.CHANGING) binding.applicationCard.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
val viewModel: AppViewModel by (context as AppCompatActivity).viewModel() val viewModel: AppViewModel by (context as AppCompatActivity).viewModel()
applications = viewModel.applications applications = viewModel.applications
applications.observe(context as AppCompatActivity, Observer<List<Application>> { applications.observe(context as AppCompatActivity, Observer<List<Application>> {
visibility = if (it.isEmpty()) View.GONE else View.VISIBLE visibility = if (it.isEmpty()) View.GONE else View.VISIBLE
applicationGrid.submitItems(it) binding.applicationGrid.submitItems(it)
}) })
} }
} }

View File

@ -2,16 +2,16 @@ package de.mm20.launcher2.ui.legacy.component
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.calculator.CalculatorViewModel import de.mm20.launcher2.calculator.CalculatorViewModel
import de.mm20.launcher2.search.data.Calculator import de.mm20.launcher2.search.data.Calculator
import kotlinx.android.synthetic.main.view_calculator.view.* import de.mm20.launcher2.ui.databinding.ViewCalculatorBinding
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import kotlin.math.round import kotlin.math.round
@ -23,8 +23,9 @@ class CalculatorView : FrameLayout {
private val calculator: LiveData<Calculator?> private val calculator: LiveData<Calculator?>
private val binding = ViewCalculatorBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
View.inflate(context, R.layout.view_calculator, this)
val viewModel: CalculatorViewModel by (context as AppCompatActivity).viewModel() val viewModel: CalculatorViewModel by (context as AppCompatActivity).viewModel()
calculator = viewModel.calculator calculator = viewModel.calculator
calculator.observe(context as AppCompatActivity, Observer { calculator.observe(context as AppCompatActivity, Observer {
@ -39,19 +40,19 @@ class CalculatorView : FrameLayout {
private fun bind(calc: Calculator) { private fun bind(calc: Calculator) {
calculatorTerm.text = beautifyTerm(calc.term) binding.calculatorTerm.text = beautifyTerm(calc.term)
calculatorSolution.text = context.getString(R.string.calculator_solution, calc.formattedString) binding.calculatorSolution.text = context.getString(R.string.calculator_solution, calc.formattedString)
if (calc.solution == round(calc.solution) && calc.term.matches(Regex("[0-9]+"))) { if (calc.solution == round(calc.solution) && calc.term.matches(Regex("[0-9]+"))) {
val binHexOct = StringBuilder() val binHexOct = StringBuilder()
binHexOct.append(calc.formattedBinaryString).append("\n") binHexOct.append(calc.formattedBinaryString).append("\n")
.append(calc.formattedOctString).append("\n") .append(calc.formattedOctString).append("\n")
.append(calc.formattedHexString) .append(calc.formattedHexString)
calculatorSolutionHexBinOct.text = binHexOct.toString() binding.calculatorSolutionHexBinOct.text = binHexOct.toString()
calculatorSolutionHexBinOct.visibility = View.VISIBLE binding.calculatorSolutionHexBinOct.visibility = View.VISIBLE
calculatorLabelHexBinOct.visibility = View.VISIBLE binding.calculatorLabelHexBinOct.visibility = View.VISIBLE
} else { } else {
calculatorSolutionHexBinOct.visibility = GONE binding.calculatorSolutionHexBinOct.visibility = GONE
calculatorLabelHexBinOct.visibility = GONE binding.calculatorLabelHexBinOct.visibility = GONE
} }
} }

View File

@ -2,14 +2,14 @@ package de.mm20.launcher2.ui.legacy.component
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import de.mm20.launcher2.favorites.FavoritesItem import de.mm20.launcher2.favorites.FavoritesItem
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleScope import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.databinding.EditFavoritesRowBinding
import kotlinx.android.synthetic.main.edit_favorites_row.view.*
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
@ -21,17 +21,18 @@ class EditFavoritesRow @JvmOverloads constructor(
val iconRepository: IconRepository by inject() val iconRepository: IconRepository by inject()
private val binding = EditFavoritesRowBinding.inflate(LayoutInflater.from(context), this, false)
init { init {
View.inflate(context, R.layout.edit_favorites_row, this) binding.label.text = favoritesItem.searchable?.label
label.text = favoritesItem.searchable?.label
lifecycleScope.launch { lifecycleScope.launch {
iconRepository.getIcon(favoritesItem.searchable!!, (48*dp).toInt()).collect{ iconRepository.getIcon(favoritesItem.searchable!!, (48*dp).toInt()).collect{
icon.icon = it binding.icon.icon = it
} }
} }
} }
fun getDragHandle(): View { fun getDragHandle(): View {
return dragHandle return binding.dragHandle
} }
} }

View File

@ -2,6 +2,7 @@ package de.mm20.launcher2.ui.legacy.component
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView import android.widget.TextView
@ -10,14 +11,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.updateMargins import androidx.core.view.updateMargins
import androidx.core.widget.TextViewCompat import androidx.core.widget.TextViewCompat
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.favorites.FavoritesItem import de.mm20.launcher2.favorites.FavoritesItem
import de.mm20.launcher2.favorites.FavoritesViewModel import de.mm20.launcher2.favorites.FavoritesViewModel
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleScope import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.ktx.setPadding import de.mm20.launcher2.ktx.setPadding
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import kotlinx.android.synthetic.main.dialog_edit_favorites.view.* import de.mm20.launcher2.ui.databinding.DialogEditFavoritesBinding
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -29,6 +29,8 @@ class EditFavoritesView @JvmOverloads constructor(
val viewModel : FavoritesViewModel by (context as AppCompatActivity).viewModel() val viewModel : FavoritesViewModel by (context as AppCompatActivity).viewModel()
private val binding = DialogEditFavoritesBinding.inflate(LayoutInflater.from(context), this)
init { init {
View.inflate(context, R.layout.dialog_edit_favorites, this) View.inflate(context, R.layout.dialog_edit_favorites, this)
lifecycleScope.launch { lifecycleScope.launch {
@ -42,45 +44,45 @@ class EditFavoritesView @JvmOverloads constructor(
favorites = withContext(Dispatchers.IO) { favorites = withContext(Dispatchers.IO) {
viewModel.getAllFavoriteItems().toMutableList() viewModel.getAllFavoriteItems().toMutableList()
} }
progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
itemList.addView(getLabel(R.string.edit_favorites_dialog_stage0)) binding.itemList.addView(getLabel(R.string.edit_favorites_dialog_stage0))
itemList.setContainerScrollView(scrollView) binding.itemList.setContainerScrollView(binding.scrollView)
var stage = 0 var stage = 0
for (favorite in favorites) { for (favorite in favorites) {
if (favorite.pinPosition <= 1 && stage == 0) { if (favorite.pinPosition <= 1 && stage == 0) {
getLabel(R.string.edit_favorites_dialog_stage1).let { getLabel(R.string.edit_favorites_dialog_stage1).let {
it.tag = "stage1" it.tag = "stage1"
itemList.addDragView(it, it.getChildAt(1)) binding.itemList.addDragView(it, it.getChildAt(1))
} }
stage++ stage++
} }
if (favorite.pinPosition == 0 && stage == 1) { if (favorite.pinPosition == 0 && stage == 1) {
getLabel(R.string.edit_favorites_dialog_stage2).let { getLabel(R.string.edit_favorites_dialog_stage2).let {
it.tag = "stage2" it.tag = "stage2"
itemList.addDragView(it, it.getChildAt(1)) binding.itemList.addDragView(it, it.getChildAt(1))
} }
stage++ stage++
} }
val view = EditFavoritesRow(context, favoritesItem = favorite) val view = EditFavoritesRow(context, favoritesItem = favorite)
itemList.addDragView(view, view.getDragHandle()) binding.itemList.addDragView(view, view.getDragHandle())
} }
if (stage == 0) { if (stage == 0) {
getLabel(R.string.edit_favorites_dialog_stage1).let { getLabel(R.string.edit_favorites_dialog_stage1).let {
it.tag = "stage1" it.tag = "stage1"
itemList.addDragView(it, it.getChildAt(1)) binding.itemList.addDragView(it, it.getChildAt(1))
} }
stage++ stage++
} }
if (stage == 1) { if (stage == 1) {
getLabel(R.string.edit_favorites_dialog_stage2).let { getLabel(R.string.edit_favorites_dialog_stage2).let {
it.tag = "stage2" it.tag = "stage2"
itemList.addDragView(it, it.getChildAt(1)) binding.itemList.addDragView(it, it.getChildAt(1))
} }
} }
itemList.setOnViewSwapListener { firstView, firstPosition, secondView, secondPosition -> binding.itemList.setOnViewSwapListener { firstView, firstPosition, secondView, secondPosition ->
if (firstView is EditFavoritesRow && secondView is EditFavoritesRow) { if (firstView is EditFavoritesRow && secondView is EditFavoritesRow) {
val firstItem = firstView.favoritesItem val firstItem = firstView.favoritesItem
val secondItem = secondView.favoritesItem val secondItem = secondView.favoritesItem

View File

@ -3,6 +3,7 @@ package de.mm20.launcher2.ui.legacy.component
import android.animation.LayoutTransition import android.animation.LayoutTransition
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@ -10,7 +11,7 @@ import androidx.lifecycle.*
import de.mm20.launcher2.favorites.FavoritesViewModel import de.mm20.launcher2.favorites.FavoritesViewModel
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import kotlinx.android.synthetic.main.view_favorites.view.* import de.mm20.launcher2.ui.databinding.ViewFavoritesBinding
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
class FavoritesView : FrameLayout { class FavoritesView : FrameLayout {
@ -21,17 +22,18 @@ class FavoritesView : FrameLayout {
private val favorites: LiveData<List<Searchable>> private val favorites: LiveData<List<Searchable>>
private val binding = ViewFavoritesBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
View.inflate(context, R.layout.view_favorites, this)
val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel() val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
favorites = viewModel.getFavorites(context.resources.getInteger(R.integer.config_columnCount)) favorites = viewModel.getFavorites(context.resources.getInteger(R.integer.config_columnCount))
favorites.observe(context as AppCompatActivity, Observer { favorites.observe(context as AppCompatActivity, Observer {
visibility = if (it?.isEmpty() == true) View.GONE else View.VISIBLE visibility = if (it?.isEmpty() == true) View.GONE else View.VISIBLE
favoritesGrid.submitItems(it) binding.favoritesGrid.submitItems(it)
}) })
layoutTransition = LayoutTransition().apply { enableTransitionType(LayoutTransition.CHANGING) } layoutTransition = LayoutTransition().apply { enableTransitionType(LayoutTransition.CHANGING) }
favoritesCard.layoutTransition = LayoutTransition().apply { enableTransitionType(LayoutTransition.CHANGING) } binding.favoritesCard.layoutTransition = LayoutTransition().apply { enableTransitionType(LayoutTransition.CHANGING) }
} }
} }

View File

@ -8,6 +8,7 @@ import android.graphics.Color
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.animation.AccelerateInterpolator import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
@ -15,7 +16,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.postDelayed import androidx.core.view.postDelayed
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.airbnb.lottie.LottieCompositionFactory import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieDrawable import com.airbnb.lottie.LottieDrawable
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
@ -24,8 +24,8 @@ import de.mm20.launcher2.preferences.SearchStyles
import de.mm20.launcher2.search.SearchViewModel import de.mm20.launcher2.search.SearchViewModel
import de.mm20.launcher2.transition.ChangingLayoutTransition import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewSearchBarBinding
import de.mm20.launcher2.ui.legacy.view.LauncherCardView import de.mm20.launcher2.ui.legacy.view.LauncherCardView
import kotlinx.android.synthetic.main.view_search_bar.view.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
class SearchBar @JvmOverloads constructor( class SearchBar @JvmOverloads constructor(
@ -43,13 +43,14 @@ class SearchBar @JvmOverloads constructor(
repeatMode = LottieDrawable.REVERSE repeatMode = LottieDrawable.REVERSE
} }
private val binding = ViewSearchBarBinding.inflate(LayoutInflater.from(context), this)
init { init {
View.inflate(context, R.layout.view_search_bar, this) binding.overflowMenu.setImageDrawable(rightDrawable)
overflowMenu.setImageDrawable(rightDrawable) binding.searchEdit.addTextChangedListener(object : TextWatcher {
searchEdit.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
val text = searchEdit.text.toString() val text = binding.searchEdit.text.toString()
onSearchQueryChanged?.invoke(searchEdit.text.toString()) onSearchQueryChanged?.invoke(binding.searchEdit.text.toString())
if (text.isEmpty()) { if (text.isEmpty()) {
if (rightDrawable.frame > rightDrawable.minFrame.toInt()) { if (rightDrawable.frame > rightDrawable.minFrame.toInt()) {
rightDrawable.speed = -1f rightDrawable.speed = -1f
@ -74,10 +75,10 @@ class SearchBar @JvmOverloads constructor(
val viewModel = (context as AppCompatActivity).viewModel<SearchViewModel>().value val viewModel = (context as AppCompatActivity).viewModel<SearchViewModel>().value
viewModel.isSearching.observe(context, Observer { viewModel.isSearching.observe(context, Observer {
searchProgressBar.visibility = if (it) View.VISIBLE else View.GONE binding.searchProgressBar.visibility = if (it) View.VISIBLE else View.GONE
}) })
overflowMenu.setOnClickListener { binding.overflowMenu.setOnClickListener {
if (getSearchQuery().isEmpty()) onRightIconClick?.invoke(it) if (getSearchQuery().isEmpty()) onRightIconClick?.invoke(it)
else (setSearchQuery("")) else (setSearchQuery(""))
} }
@ -90,22 +91,22 @@ class SearchBar @JvmOverloads constructor(
} }
fun setRightIcon(iconRes: Int) { fun setRightIcon(iconRes: Int) {
overflowMenu.setImageResource(iconRes) binding.overflowMenu.setImageResource(iconRes)
} }
var onSearchQueryChanged: ((String) -> Unit)? = null var onSearchQueryChanged: ((String) -> Unit)? = null
var onRightIconClick: ((View) -> Unit)? = null var onRightIconClick: ((View) -> Unit)? = null
override fun setOnTouchListener(l: OnTouchListener?) { override fun setOnTouchListener(l: OnTouchListener?) {
searchEdit.setOnTouchListener(l) binding.searchEdit.setOnTouchListener(l)
} }
fun setSearchQuery(text: String) { fun setSearchQuery(text: String) {
searchEdit.setText(text) binding.searchEdit.setText(text)
} }
fun getSearchQuery(): String { fun getSearchQuery(): String {
return searchEdit.text.toString() return binding.searchEdit.text.toString()
} }
/** /**
@ -168,7 +169,7 @@ class SearchBar @JvmOverloads constructor(
} }
fun getWebSearchView(): View { fun getWebSearchView(): View {
return webSearchView return binding.webSearchView
} }
private fun getHideAnimator(): AnimatorSet { private fun getHideAnimator(): AnimatorSet {
@ -180,7 +181,7 @@ class SearchBar @JvmOverloads constructor(
val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y) val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y)
val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius) val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius)
val shadowC = Color.argb(66, 0, 0, 0) val shadowC = Color.argb(66, 0, 0, 0)
searchEdit.setShadowLayer(shadowR, 0f, shadowY, shadowC) binding.searchEdit.setShadowLayer(shadowR, 0f, shadowY, shadowC)
AnimatorSet().apply { AnimatorSet().apply {
duration = 200 duration = 200
playTogether( playTogether(
@ -191,13 +192,13 @@ class SearchBar @JvmOverloads constructor(
interpolator = DecelerateInterpolator(3f) interpolator = DecelerateInterpolator(3f)
duration = 150 duration = 150
}, },
ObjectAnimator.ofArgb(searchEdit, "hintTextColor", searchEdit.hintTextColors.defaultColor, Color.WHITE), ObjectAnimator.ofArgb(binding.searchEdit, "hintTextColor", binding.searchEdit.hintTextColors.defaultColor, Color.WHITE),
ObjectAnimator.ofArgb(searchIcon, "colorFilter", iconColor, Color.WHITE), ObjectAnimator.ofArgb(binding.searchIcon, "colorFilter", iconColor, Color.WHITE),
ObjectAnimator.ofArgb(overflowMenu, "colorFilter", iconColor, Color.WHITE), ObjectAnimator.ofArgb(binding.overflowMenu, "colorFilter", iconColor, Color.WHITE),
ObjectAnimator.ofFloat(searchIcon, "alpha", 1f), ObjectAnimator.ofFloat(binding.searchIcon, "alpha", 1f),
ObjectAnimator.ofFloat(overflowMenu, "alpha", 1f), ObjectAnimator.ofFloat(binding.overflowMenu, "alpha", 1f),
ObjectAnimator.ofFloat(searchIcon, "elevation", cardElevation), ObjectAnimator.ofFloat(binding.searchIcon, "elevation", cardElevation),
ObjectAnimator.ofFloat(overflowMenu, "elevation", cardElevation) ObjectAnimator.ofFloat(binding.overflowMenu, "elevation", cardElevation)
) )
} }
} }
@ -226,7 +227,7 @@ class SearchBar @JvmOverloads constructor(
val iconAlpha = iconAttrs.getFloat(0, 0f) val iconAlpha = iconAttrs.getFloat(0, 0f)
iconAttrs.recycle() iconAttrs.recycle()
val iconColor = ContextCompat.getColor(context, R.color.icon_color) val iconColor = ContextCompat.getColor(context, R.color.icon_color)
searchEdit.setShadowLayer(0f, 0f, 0f, 0) binding.searchEdit.setShadowLayer(0f, 0f, 0f, 0)
AnimatorSet().apply { AnimatorSet().apply {
duration = 200 duration = 200
playTogether( playTogether(
@ -236,13 +237,13 @@ class SearchBar @JvmOverloads constructor(
ObjectAnimator.ofInt(this@SearchBar, "backgroundOpacity", LauncherPreferences.instance.cardOpacity).apply { ObjectAnimator.ofInt(this@SearchBar, "backgroundOpacity", LauncherPreferences.instance.cardOpacity).apply {
interpolator = DecelerateInterpolator(3f) interpolator = DecelerateInterpolator(3f)
}, },
ObjectAnimator.ofArgb(searchEdit, "hintTextColor", Color.WHITE, hint), ObjectAnimator.ofArgb(binding.searchEdit, "hintTextColor", Color.WHITE, hint),
ObjectAnimator.ofArgb(searchIcon, "colorFilter", Color.WHITE, iconColor), ObjectAnimator.ofArgb(binding.searchIcon, "colorFilter", Color.WHITE, iconColor),
ObjectAnimator.ofArgb(overflowMenu, "colorFilter", Color.WHITE, iconColor), ObjectAnimator.ofArgb(binding.overflowMenu, "colorFilter", Color.WHITE, iconColor),
ObjectAnimator.ofFloat(searchIcon, "alpha", iconAlpha), ObjectAnimator.ofFloat(binding.searchIcon, "alpha", iconAlpha),
ObjectAnimator.ofFloat(overflowMenu, "alpha", iconAlpha), ObjectAnimator.ofFloat(binding.overflowMenu, "alpha", iconAlpha),
ObjectAnimator.ofFloat(searchIcon, "elevation", 0f), ObjectAnimator.ofFloat(binding.searchIcon, "elevation", 0f),
ObjectAnimator.ofFloat(overflowMenu, "elevation", 0f) ObjectAnimator.ofFloat(binding.overflowMenu, "elevation", 0f)
) )
} }
} }

View File

@ -7,6 +7,7 @@ import android.text.Spanned
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.TextView import android.widget.TextView
@ -14,8 +15,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsIntent
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
@ -29,9 +28,9 @@ import de.mm20.launcher2.ktx.sp
import de.mm20.launcher2.search.data.CurrencyUnitConverter import de.mm20.launcher2.search.data.CurrencyUnitConverter
import de.mm20.launcher2.search.data.UnitConverter import de.mm20.launcher2.search.data.UnitConverter
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewUnitconverterBinding
import de.mm20.launcher2.unitconverter.UnitConverterViewModel import de.mm20.launcher2.unitconverter.UnitConverterViewModel
import de.mm20.launcher2.unitconverter.UnitValue import de.mm20.launcher2.unitconverter.UnitValue
import kotlinx.android.synthetic.main.view_unitconverter.view.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import java.text.DateFormat import java.text.DateFormat
import java.util.* import java.util.*
@ -46,8 +45,9 @@ class UnitConverterView : FrameLayout {
private val unitConverter: LiveData<UnitConverter?> private val unitConverter: LiveData<UnitConverter?>
private val adapter: GroupAdapter<GroupieViewHolder> private val adapter: GroupAdapter<GroupieViewHolder>
private val binding = ViewUnitconverterBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
View.inflate(context, R.layout.view_unitconverter, this)
val unitConverterViewModel by (context as AppCompatActivity).viewModel<UnitConverterViewModel>() val unitConverterViewModel by (context as AppCompatActivity).viewModel<UnitConverterViewModel>()
unitConverter = unitConverterViewModel.unitConverter unitConverter = unitConverterViewModel.unitConverter
unitConverter.observe(context as AppCompatActivity, Observer { unitConverter.observe(context as AppCompatActivity, Observer {
@ -58,7 +58,7 @@ class UnitConverterView : FrameLayout {
} }
}) })
adapter = GroupAdapter() adapter = GroupAdapter()
unitConverterValues.also { binding.unitConverterValues.also {
it.adapter = adapter it.adapter = adapter
it.addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL)) it.addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
} }
@ -67,7 +67,7 @@ class UnitConverterView : FrameLayout {
private fun bind(converter: UnitConverter) { private fun bind(converter: UnitConverter) {
val title = converter.inputValue.formattedValue + " " + converter.inputValue.formattedName val title = converter.inputValue.formattedValue + " " + converter.inputValue.formattedName
unitConverterInput.text = title binding.unitConverterInput.text = title
/*val sb = StringBuilder() /*val sb = StringBuilder()
for (unit in converter.values) { for (unit in converter.values) {
@ -99,16 +99,16 @@ class UnitConverterView : FrameLayout {
} }
if (converter.values.size > 5) { if (converter.values.size > 5) {
showAllButton.visibility = View.VISIBLE binding.showAllButton.visibility = View.VISIBLE
showAllButton.setOnClickListener { binding.showAllButton.setOnClickListener {
section.addAll(converter.values.subList( 5, converter.values.size).map { section.addAll(converter.values.subList( 5, converter.values.size).map {
ValueItem(it, maxValueLength * 8f * sp) ValueItem(it, maxValueLength * 8f * sp)
}) })
showAllButton.visibility = View.GONE binding.showAllButton.visibility = View.GONE
showAllButton.setOnClickListener(null) binding.showAllButton.setOnClickListener(null)
} }
} else { } else {
showAllButton.visibility = View.GONE binding.showAllButton.visibility = View.GONE
} }
@ -141,13 +141,13 @@ class UnitConverterView : FrameLayout {
} }
}, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
unitConverterInfo.apply { binding.unitConverterInfo.apply {
text = infoText text = infoText
visibility = View.VISIBLE visibility = View.VISIBLE
movementMethod = LinkMovementMethod.getInstance() movementMethod = LinkMovementMethod.getInstance()
} }
} else { } else {
unitConverterInfo.visibility = View.GONE binding.unitConverterInfo.visibility = View.GONE
} }
} }

View File

@ -4,13 +4,13 @@ import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition import com.bumptech.glide.request.transition.Transition
@ -20,7 +20,7 @@ import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.WebsearchViewModel import de.mm20.launcher2.search.WebsearchViewModel
import de.mm20.launcher2.search.data.Websearch import de.mm20.launcher2.search.data.Websearch
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import kotlinx.android.synthetic.main.view_websearch.view.* import de.mm20.launcher2.ui.databinding.ViewWebsearchBinding
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
class WebSearchView : FrameLayout { class WebSearchView : FrameLayout {
@ -30,6 +30,8 @@ class WebSearchView : FrameLayout {
private val websearches: LiveData<List<Websearch>> private val websearches: LiveData<List<Websearch>>
private val binding = ViewWebsearchBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
View.inflate(context, R.layout.view_websearch, this) View.inflate(context, R.layout.view_websearch, this)
val viewModel: WebsearchViewModel by (context as AppCompatActivity).viewModel() val viewModel: WebsearchViewModel by (context as AppCompatActivity).viewModel()
@ -41,7 +43,7 @@ class WebSearchView : FrameLayout {
private fun updateWebsearches(websearches: List<Websearch>) { private fun updateWebsearches(websearches: List<Websearch>) {
visibility = if (websearches.isEmpty()) View.GONE else View.VISIBLE visibility = if (websearches.isEmpty()) View.GONE else View.VISIBLE
webSearchList.removeAllViews() binding.webSearchList.removeAllViews()
for (search in websearches) { for (search in websearches) {
val chip = Chip(context) val chip = Chip(context)
chip.text = search.label chip.text = search.label
@ -68,7 +70,7 @@ class WebSearchView : FrameLayout {
ActivityStarter.start(context, chip, intent = search.getLaunchIntent()) ActivityStarter.start(context, chip, intent = search.getLaunchIntent())
} }
webSearchList.addView(chip) binding.webSearchList.addView(chip)
} }
} }

View File

@ -4,6 +4,7 @@ import android.animation.LayoutTransition
import android.appwidget.AppWidgetHost import android.appwidget.AppWidgetHost
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View import android.view.View
import androidx.appcompat.widget.TooltipCompat import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.get import androidx.core.view.get
@ -11,11 +12,11 @@ import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.transition.ChangingLayoutTransition import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.transition.OneShotLayoutTransition import de.mm20.launcher2.transition.OneShotLayoutTransition
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewWidgetBinding
import de.mm20.launcher2.ui.legacy.view.LauncherCardView import de.mm20.launcher2.ui.legacy.view.LauncherCardView
import de.mm20.launcher2.ui.legacy.widget.* import de.mm20.launcher2.ui.legacy.widget.*
import de.mm20.launcher2.widgets.Widget import de.mm20.launcher2.widgets.Widget
import de.mm20.launcher2.widgets.WidgetType import de.mm20.launcher2.widgets.WidgetType
import kotlinx.android.synthetic.main.view_widget.view.*
class WidgetView : LauncherCardView { class WidgetView : LauncherCardView {
@ -29,24 +30,24 @@ class WidgetView : LauncherCardView {
var editMode = false var editMode = false
set(value) { set(value) {
if (value) { if (value) {
widgetControlPanel.visibility = View.VISIBLE binding.widgetControlPanel.visibility = View.VISIBLE
val widget = widgetWrapper[2] val widget = binding.widgetWrapper[2]
widget.visibility = View.GONE widget.visibility = View.GONE
widgetName.visibility = View.VISIBLE binding.widgetName.visibility = View.VISIBLE
visibility = View.VISIBLE visibility = View.VISIBLE
layoutTransition = OneShotLayoutTransition(this) layoutTransition = OneShotLayoutTransition(this)
widgetView?.layoutTransition = null widgetView?.layoutTransition = null
widgetWrapper.layoutTransition = null binding.widgetWrapper.layoutTransition = null
} else { } else {
resizeMode = false resizeMode = false
widgetControlPanel.visibility = View.GONE binding.widgetControlPanel.visibility = View.GONE
val widget = widgetWrapper[2] as LauncherWidget val widget = binding.widgetWrapper[2] as LauncherWidget
widget.visibility = View.VISIBLE widget.visibility = View.VISIBLE
widgetName.visibility = View.GONE binding.widgetName.visibility = View.GONE
visibility = if (widget.show) View.VISIBLE else View.GONE visibility = if (widget.show) View.VISIBLE else View.GONE
layoutTransition = ChangingLayoutTransition() layoutTransition = ChangingLayoutTransition()
widgetView?.layoutTransition = ChangingLayoutTransition() widgetView?.layoutTransition = ChangingLayoutTransition()
widgetWrapper.layoutTransition = ChangingLayoutTransition() binding.widgetWrapper.layoutTransition = ChangingLayoutTransition()
} }
field = value field = value
} }
@ -56,16 +57,16 @@ class WidgetView : LauncherCardView {
if (value == field) return if (value == field) return
onResizeModeChange?.invoke(value) onResizeModeChange?.invoke(value)
if (value) { if (value) {
widgetResizeDragHandle.visibility = View.VISIBLE binding.widgetResizeDragHandle.visibility = View.VISIBLE
val widget = widgetWrapper[2] val widget = binding.widgetWrapper[2]
widget.visibility = View.VISIBLE widget.visibility = View.VISIBLE
widgetName.visibility = View.GONE binding.widgetName.visibility = View.GONE
} else { } else {
widgetResizeDragHandle.visibility = View.GONE binding.widgetResizeDragHandle.visibility = View.GONE
if (editMode) { if (editMode) {
val widget = widgetWrapper[2] val widget = binding.widgetWrapper[2]
widget.visibility = View.GONE widget.visibility = View.GONE
widgetName.visibility = View.VISIBLE binding.widgetName.visibility = View.VISIBLE
} }
} }
@ -77,14 +78,13 @@ class WidgetView : LauncherCardView {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
private val binding = ViewWidgetBinding.inflate(LayoutInflater.from(context), this)
init { init {
View.inflate(context, R.layout.view_widget, this) binding.widgetActionResize.setOnClickListener {
widgetActionResize.setOnClickListener {
resizeMode = !resizeMode resizeMode = !resizeMode
} }
widgetActionRemove.setOnClickListener { binding.widgetActionRemove.setOnClickListener {
onRemove?.invoke() onRemove?.invoke()
} }
layoutTransition = LayoutTransition().apply { layoutTransition = LayoutTransition().apply {
@ -93,9 +93,9 @@ class WidgetView : LauncherCardView {
elevation = if (backgroundOpacity < 255) 0f else resources.getDimension(R.dimen.card_elevation) elevation = if (backgroundOpacity < 255) 0f else resources.getDimension(R.dimen.card_elevation)
TooltipCompat.setTooltipText(widgetActionResize, context.getString(R.string.widget_action_adjust_height)) TooltipCompat.setTooltipText(binding.widgetActionResize, context.getString(R.string.widget_action_adjust_height))
TooltipCompat.setTooltipText(widgetActionRemove, context.getString(R.string.widget_action_remove)) TooltipCompat.setTooltipText(binding.widgetActionRemove, context.getString(R.string.widget_action_remove))
TooltipCompat.setTooltipText(widgetActionSettings, context.getString(R.string.widget_action_settings)) TooltipCompat.setTooltipText(binding.widgetActionSettings, context.getString(R.string.widget_action_settings))
} }
var onResizeModeChange: ((Boolean) -> Unit)? = null var onResizeModeChange: ((Boolean) -> Unit)? = null
@ -108,13 +108,13 @@ class WidgetView : LauncherCardView {
MusicWidget.ID -> MusicWidget(context) MusicWidget.ID -> MusicWidget(context)
else -> return false else -> return false
} }
widgetActionResize.visibility = View.GONE binding.widgetActionResize.visibility = View.GONE
widgetActionSettings.visibility = if (widgetView?.hasSettings == true) View.VISIBLE else View.GONE binding.widgetActionSettings.visibility = if (widgetView?.hasSettings == true) View.VISIBLE else View.GONE
widgetResizeDragHandle.resizeView = widgetView binding.widgetResizeDragHandle.resizeView = widgetView
widgetWrapper.addView(widgetView, 2) binding.widgetWrapper.addView(widgetView, 2)
widgetName.text = widgetView?.name binding.widgetName.text = widgetView?.name
visibility = if (widgetView?.show == true) View.VISIBLE else View.GONE visibility = if (widgetView?.show == true) View.VISIBLE else View.GONE
widgetActionSettings.setOnClickListener { binding.widgetActionSettings.setOnClickListener {
widgetView?.openSettings() widgetView?.openSettings()
/*(context as? Activity)?.finish() /*(context as? Activity)?.finish()
context.startActivity(Intent(context, SettingsActivity::class.java).apply { context.startActivity(Intent(context, SettingsActivity::class.java).apply {
@ -123,14 +123,14 @@ class WidgetView : LauncherCardView {
} }
} else { } else {
widgetView = ExternalWidget(context, widget, widgetHost) widgetView = ExternalWidget(context, widget, widgetHost)
widgetResizeDragHandle.resizeView = widgetView binding.widgetResizeDragHandle.resizeView = widgetView
widgetResizeDragHandle.onResize = { binding.widgetResizeDragHandle.onResize = {
widget.height = (it / dp).toInt() widget.height = (it / dp).toInt()
} }
widgetWrapper.addView(widgetView, 2) binding.widgetWrapper.addView(widgetView, 2)
widgetName.text = widgetView?.name binding.widgetName.text = widgetView?.name
widgetActionResize.visibility = View.VISIBLE binding.widgetActionResize.visibility = View.VISIBLE
widgetActionSettings.visibility = View.GONE binding.widgetActionSettings.visibility = View.GONE
visibility = if (widgetView?.show == true) View.VISIBLE else View.GONE visibility = if (widgetView?.show == true) View.VISIBLE else View.GONE
} }
widgetView?.onVisibilityChanged = { widgetView?.onVisibilityChanged = {
@ -144,11 +144,11 @@ class WidgetView : LauncherCardView {
} }
fun getDragHandle(): View { fun getDragHandle(): View {
return widgetDragHandle return binding.widgetDragHandle
} }
fun update() { fun update() {
val widget = widgetWrapper[2] as? LauncherWidget ?: return val widget = binding.widgetWrapper[2] as? LauncherWidget ?: return
widget.update() widget.update()
visibility = if (widget.show) View.VISIBLE else View.GONE visibility = if (widget.show) View.VISIBLE else View.GONE
} }

View File

@ -7,12 +7,12 @@ import android.content.Intent
import android.provider.CalendarContract import android.provider.CalendarContract
import android.text.format.DateUtils import android.text.format.DateUtils
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.calendar.CalendarViewModel import de.mm20.launcher2.calendar.CalendarViewModel
import de.mm20.launcher2.favorites.FavoritesViewModel import de.mm20.launcher2.favorites.FavoritesViewModel
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.legacy.helper.ActivityStarter
@ -22,7 +22,7 @@ import de.mm20.launcher2.ui.legacy.data.InformationText
import de.mm20.launcher2.search.data.MissingPermission import de.mm20.launcher2.search.data.MissingPermission
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import kotlinx.android.synthetic.main.view_calendar_widget.view.* import de.mm20.launcher2.ui.databinding.ViewCalendarWidgetBinding
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import java.util.* import java.util.*
import kotlin.math.max import kotlin.math.max
@ -48,7 +48,7 @@ class CalendarWidget : LauncherWidget {
private var selectedDay = 0L private var selectedDay = 0L
set(value) { set(value) {
field = value field = value
calendarDate.text = formatDay(value) binding.calendarDate.text = formatDay(value)
updateEventList() updateEventList()
} }
@ -73,19 +73,20 @@ class CalendarWidget : LauncherWidget {
} }
} }
private val binding = ViewCalendarWidgetBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
clipToPadding = false clipToPadding = false
clipChildren = false clipChildren = false
View.inflate(context, R.layout.view_calendar_widget, this) binding.calendarNewEvent.setOnClickListener {
calendarNewEvent.setOnClickListener {
val intent = Intent(Intent.ACTION_EDIT) val intent = Intent(Intent.ACTION_EDIT)
intent.data = CalendarContract.Events.CONTENT_URI intent.data = CalendarContract.Events.CONTENT_URI
ActivityStarter.start(context, this, intent = intent) ActivityStarter.start(context, this, intent = intent)
} }
calendarDate.setOnClickListener { binding.calendarDate.setOnClickListener {
val menu = PopupMenu(context, calendarDate) val menu = PopupMenu(context, binding.calendarDate)
for (d in availableDays) { for (d in availableDays) {
menu.menu.add( menu.menu.add(
Menu.NONE, Menu.NONE,
@ -101,21 +102,21 @@ class CalendarWidget : LauncherWidget {
menu.show() menu.show()
} }
calendarOpenApp.setOnClickListener { binding.calendarOpenApp.setOnClickListener {
val startMillis = System.currentTimeMillis() val startMillis = System.currentTimeMillis()
val builder = CalendarContract.CONTENT_URI.buildUpon() val builder = CalendarContract.CONTENT_URI.buildUpon()
builder.appendPath("time") builder.appendPath("time")
ContentUris.appendId(builder, startMillis) ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
.setData(builder.build()) .setData(builder.build())
ActivityStarter.start(context, calendarWidgetRoot, intent = intent) ActivityStarter.start(context, binding.calendarWidgetRoot, intent = intent)
} }
calendarDateNext.setOnClickListener { binding.calendarDateNext.setOnClickListener {
val i = min(availableDays.lastIndex - 1, availableDays.indexOf(selectedDay)) val i = min(availableDays.lastIndex - 1, availableDays.indexOf(selectedDay))
selectedDay = availableDays[i + 1] selectedDay = availableDays[i + 1]
} }
calendarDatePrev.setOnClickListener { binding.calendarDatePrev.setOnClickListener {
val i = max(1, availableDays.indexOf(selectedDay)) val i = max(1, availableDays.indexOf(selectedDay))
selectedDay = availableDays[i - 1] selectedDay = availableDays[i - 1]
} }
@ -127,7 +128,7 @@ class CalendarWidget : LauncherWidget {
calendarEvents.observe(context as AppCompatActivity, { calendarEvents.observe(context as AppCompatActivity, {
if (!PermissionsManager.checkPermission(context, PermissionsManager.CALENDAR)) { if (!PermissionsManager.checkPermission(context, PermissionsManager.CALENDAR)) {
calendarWidgetList.submitItems(listOf( binding.calendarWidgetList.submitItems(listOf(
MissingPermission( MissingPermission(
context.getString(R.string.permission_calendar_widget), context.getString(R.string.permission_calendar_widget),
PermissionsManager.CALENDAR PermissionsManager.CALENDAR
@ -145,21 +146,21 @@ class CalendarWidget : LauncherWidget {
}) })
pinnedCalendarEvents.observe(context as AppCompatActivity) { pinnedCalendarEvents.observe(context as AppCompatActivity) {
val today = getToday() val today = getToday()
calendarWidgetPinnedList.submitItems(it.filter { binding.calendarWidgetPinnedList.submitItems(it.filter {
it.endTime > System.currentTimeMillis() && it.endTime > System.currentTimeMillis() &&
(it.startTime + zoneOffset) / (1000 * 60 * 60 * 24) != today && (it.startTime + zoneOffset) / (1000 * 60 * 60 * 24) != today &&
(it.endTime + zoneOffset) / (1000 * 60 * 60 * 24) != today (it.endTime + zoneOffset) / (1000 * 60 * 60 * 24) != today
}.sortedBy { it.startTime }) }.sortedBy { it.startTime })
if (it.isEmpty()) { if (it.isEmpty()) {
calendarWidgetPinnedList.visibility = View.GONE binding.calendarWidgetPinnedList.visibility = View.GONE
calendarUpcomingEventsTitle.visibility = View.GONE binding.calendarUpcomingEventsTitle.visibility = View.GONE
} else { } else {
calendarWidgetPinnedList.visibility = View.VISIBLE binding.calendarWidgetPinnedList.visibility = View.VISIBLE
calendarUpcomingEventsTitle.visibility = View.VISIBLE binding.calendarUpcomingEventsTitle.visibility = View.VISIBLE
} }
} }
calendarWidgetRoot.layoutTransition = LayoutTransition().apply { binding.calendarWidgetRoot.layoutTransition = LayoutTransition().apply {
enableTransitionType(LayoutTransition.CHANGING) enableTransitionType(LayoutTransition.CHANGING)
} }
} }
@ -190,7 +191,7 @@ class CalendarWidget : LauncherWidget {
} }
} }
calendarWidgetList.submitItems(events) binding.calendarWidgetList.submitItems(events)
} }

View File

@ -5,7 +5,7 @@ import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.AnimatedVectorDrawable import android.graphics.drawable.AnimatedVectorDrawable
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -13,21 +13,17 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.alpha import androidx.core.graphics.alpha
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.music.MusicViewModel import de.mm20.launcher2.music.MusicViewModel
import de.mm20.launcher2.music.PlaybackState import de.mm20.launcher2.music.PlaybackState
import de.mm20.launcher2.search.SearchViewModel
import de.mm20.launcher2.ui.LegacyLauncherTheme import de.mm20.launcher2.ui.LegacyLauncherTheme
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.CompactMusicBinding
import de.mm20.launcher2.ui.widget.MusicWidget import de.mm20.launcher2.ui.widget.MusicWidget
import de.mm20.launcher2.ui.widget.WeatherWidget
import kotlinx.android.synthetic.main.compact_music.view.*
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
class MusicWidget : LauncherWidget { class MusicWidget : LauncherWidget {
@ -83,33 +79,35 @@ class MusicCompactView : FrameLayout, CompactView {
private val viewModel: MusicViewModel by (context as AppCompatActivity).viewModel() private val viewModel: MusicViewModel by (context as AppCompatActivity).viewModel()
private val binding = CompactMusicBinding.inflate(LayoutInflater.from(context), this)
override fun setTranslucent(translucent: Boolean) { override fun setTranslucent(translucent: Boolean) {
if (translucent) { if (translucent) {
musicCompactTitle.setTextColor(Color.WHITE) binding.musicCompactTitle.setTextColor(Color.WHITE)
musicCompactArtist.setTextColor(Color.WHITE) binding.musicCompactArtist.setTextColor(Color.WHITE)
musicCompactNext.elevation = 2 * dp binding.musicCompactNext.elevation = 2 * dp
musicCompactPlay.elevation = 2 * dp binding.musicCompactPlay.elevation = 2 * dp
musicCompactNext.alpha = 1f binding.musicCompactNext.alpha = 1f
musicCompactPlay.alpha = 1f binding.musicCompactPlay.alpha = 1f
musicCompactNext.imageTintList = ColorStateList.valueOf(Color.WHITE) binding.musicCompactNext.imageTintList = ColorStateList.valueOf(Color.WHITE)
musicCompactPlay.imageTintList = ColorStateList.valueOf(Color.WHITE) binding.musicCompactPlay.imageTintList = ColorStateList.valueOf(Color.WHITE)
val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y) val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y)
val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius) val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius)
val shadowC = Color.argb(66, 0, 0, 0) val shadowC = Color.argb(66, 0, 0, 0)
musicCompactTitle.setShadowLayer(shadowR, 0f, shadowY, shadowC) binding.musicCompactTitle.setShadowLayer(shadowR, 0f, shadowY, shadowC)
musicCompactArtist.setShadowLayer(shadowR, 0f, shadowY, shadowC) binding.musicCompactArtist.setShadowLayer(shadowR, 0f, shadowY, shadowC)
} else { } else {
val primaryColor = ContextCompat.getColorStateList(context, R.color.text_color_primary)!! val primaryColor = ContextCompat.getColorStateList(context, R.color.text_color_primary)!!
musicCompactTitle.setTextColor(primaryColor) binding.musicCompactTitle.setTextColor(primaryColor)
musicCompactArtist.setTextColor(ContextCompat.getColorStateList(context, R.color.text_color_secondary)) binding.musicCompactArtist.setTextColor(ContextCompat.getColorStateList(context, R.color.text_color_secondary))
musicCompactNext.elevation = 0f binding.musicCompactNext.elevation = 0f
musicCompactPlay.elevation = 0f binding.musicCompactPlay.elevation = 0f
musicCompactNext.alpha = primaryColor.defaultColor.alpha / 255f binding.musicCompactNext.alpha = primaryColor.defaultColor.alpha / 255f
musicCompactPlay.alpha = primaryColor.defaultColor.alpha / 255f binding.musicCompactPlay.alpha = primaryColor.defaultColor.alpha / 255f
musicCompactNext.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color)) binding.musicCompactNext.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color))
musicCompactPlay.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color)) binding.musicCompactPlay.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color))
musicCompactTitle.setShadowLayer(0f, 0f, 0f, 0) binding.musicCompactTitle.setShadowLayer(0f, 0f, 0f, 0)
musicCompactArtist.setShadowLayer(0f, 0f, 0f, 0) binding.musicCompactArtist.setShadowLayer(0f, 0f, 0f, 0)
} }
} }
@ -117,7 +115,7 @@ class MusicCompactView : FrameLayout, CompactView {
set(value) { set(value) {
if (value != field) { if (value != field) {
val icon = context.getDrawable(value) val icon = context.getDrawable(value)
musicCompactPlay.setImageDrawable(icon) binding.musicCompactPlay.setImageDrawable(icon)
(icon as? AnimatedVectorDrawable)?.start() (icon as? AnimatedVectorDrawable)?.start()
field = value field = value
} }
@ -131,48 +129,47 @@ class MusicCompactView : FrameLayout, CompactView {
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
init { init {
View.inflate(context, R.layout.compact_music, this)
clipChildren = false clipChildren = false
musicCompactNext.setOnClickListener { binding.musicCompactNext.setOnClickListener {
viewModel.next() viewModel.next()
(musicCompactNext.drawable as AnimatedVectorDrawable).start() (binding.musicCompactNext.drawable as AnimatedVectorDrawable).start()
} }
musicCompactPlay.setOnClickListener { _ -> binding.musicCompactPlay.setOnClickListener { _ ->
viewModel.togglePause() viewModel.togglePause()
} }
musicCompactMeta.setOnClickListener { binding.musicCompactMeta.setOnClickListener {
ActivityStarter.start(context, this, pendingIntent = viewModel.getLaunchIntent(context)) ActivityStarter.start(context, this, pendingIntent = viewModel.getLaunchIntent(context))
} }
viewModel.title.observe(context as AppCompatActivity, Observer { viewModel.title.observe(context as AppCompatActivity, Observer {
musicCompactTitle.text = it binding.musicCompactTitle.text = it
}) })
viewModel.artist.observe(context as AppCompatActivity, Observer { viewModel.artist.observe(context as AppCompatActivity, Observer {
musicCompactArtist.text = it binding.musicCompactArtist.text = it
}) })
viewModel.playbackState.observe(context as AppCompatActivity, Observer { viewModel.playbackState.observe(context as AppCompatActivity, Observer {
if (it == PlaybackState.Playing) { if (it == PlaybackState.Playing) {
playPauseIcon = R.drawable.ic_play_to_pause playPauseIcon = R.drawable.ic_play_to_pause
musicCompactPlay.setOnClickListener { binding.musicCompactPlay.setOnClickListener {
viewModel.pause() viewModel.pause()
} }
musicCompactTitle.isSelected = true binding.musicCompactTitle.isSelected = true
musicCompactArtist.isSelected = true binding.musicCompactArtist.isSelected = true
} else { } else {
playPauseIcon = R.drawable.ic_pause_to_play playPauseIcon = R.drawable.ic_pause_to_play
musicCompactPlay.setOnClickListener { binding.musicCompactPlay.setOnClickListener {
viewModel.play() viewModel.play()
} }
musicCompactTitle.isSelected = false binding.musicCompactTitle.isSelected = false
musicCompactArtist.isSelected = false binding.musicCompactArtist.isSelected = false
} }
}) })
} }
override fun update() { override fun update() {
musicCompactTitle.text = viewModel.title.value binding.musicCompactTitle.text = viewModel.title.value
musicCompactArtist.text = viewModel.artist.value binding.musicCompactArtist.text = viewModel.artist.value
playPauseIcon = if (viewModel.playbackState.value == PlaybackState.Playing) R.drawable.ic_pause else R.drawable.ic_play playPauseIcon = if (viewModel.playbackState.value == PlaybackState.Playing) R.drawable.ic_pause else R.drawable.ic_play
} }
} }

View File

@ -13,54 +13,44 @@ import android.provider.CalendarContract
import android.text.format.DateFormat import android.text.format.DateFormat
import android.util.AttributeSet import android.util.AttributeSet
import android.util.TypedValue import android.util.TypedValue
import android.view.Gravity import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.animation.AccelerateInterpolator import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.TextClock import android.widget.TextClock
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.postDelayed import androidx.core.view.postDelayed
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.badges.BadgeProvider
import de.mm20.launcher2.favorites.FavoritesViewModel
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.legacy.fragment.SearchableBottomSheet import de.mm20.launcher2.ui.databinding.ViewDateTimeBinding
import de.mm20.launcher2.ui.legacy.view.LauncherCardView import de.mm20.launcher2.ui.legacy.view.LauncherCardView
import de.mm20.launcher2.ui.legacy.view.LauncherIconView
import kotlinx.android.synthetic.main.view_date_time.view.*
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.util.* import java.util.*
class SmartWidget : LauncherCardView { class SmartWidget : LauncherCardView {
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(
context,
attrs,
defStyleRes
)
private val binding = ViewDateTimeBinding.inflate(LayoutInflater.from(context), this, true)
init { init {
View.inflate(context, R.layout.view_date_time, this)
clipToPadding = false clipToPadding = false
clipChildren = false clipChildren = false
layoutTransition = LayoutTransition() layoutTransition = LayoutTransition()
dateTimeTimeView.format12Hour = "hh:mm" binding.dateTimeTimeView.format12Hour = "hh:mm"
dateTimeTimeView.format24Hour = "HH:mm" binding.dateTimeTimeView.format24Hour = "HH:mm"
dateTimeTimeView.setOnClickListener { binding.dateTimeTimeView.setOnClickListener {
try { try {
val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS) val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
ActivityStarter.start(context, this, intent = intent) ActivityStarter.start(context, this, intent = intent)
@ -75,12 +65,12 @@ class SmartWidget : LauncherCardView {
private val translucentDisableRunnable = Runnable@{ private val translucentDisableRunnable = Runnable@{
if (translucent) return@Runnable if (translucent) return@Runnable
dateTimeTimeView.setShadowLayer(0f, 0f, 0f, 0) binding.dateTimeTimeView.setShadowLayer(0f, 0f, 0f, 0)
val textColor = ContextCompat.getColorStateList(context, R.color.text_color_primary) val textColor = ContextCompat.getColorStateList(context, R.color.text_color_primary)
val dividerColor = ContextCompat.getColor(context, R.color.color_divider) val dividerColor = ContextCompat.getColor(context, R.color.color_divider)
dateTimeTimeView.setTextColor(textColor) binding.dateTimeTimeView.setTextColor(textColor)
bottomPadding.setBackgroundColor(dividerColor) binding.bottomPadding.setBackgroundColor(dividerColor)
bottomPadding.elevation = 0f binding.bottomPadding.elevation = 0f
compactView?.setTranslucent(false) compactView?.setTranslucent(false)
} }
@ -90,10 +80,10 @@ class SmartWidget : LauncherCardView {
val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y) val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y)
val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius) val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius)
val shadowC = Color.argb(66, 0, 0, 0) val shadowC = Color.argb(66, 0, 0, 0)
dateTimeTimeView.setTextColor(textColor) binding.dateTimeTimeView.setTextColor(textColor)
dateTimeTimeView.setShadowLayer(shadowR, 0f, shadowY, shadowC) binding.dateTimeTimeView.setShadowLayer(shadowR, 0f, shadowY, shadowC)
bottomPadding.setBackgroundColor(textColor) binding.bottomPadding.setBackgroundColor(textColor)
bottomPadding.elevation = 1f binding.bottomPadding.elevation = 1f
compactView?.setTranslucent(true) compactView?.setTranslucent(true)
} }
@ -106,12 +96,12 @@ class SmartWidget : LauncherCardView {
AnimatorSet().apply { AnimatorSet().apply {
duration = 200 duration = 200
playTogether( playTogether(
ObjectAnimator.ofInt(this@SmartWidget, "backgroundOpacity", 0).apply { ObjectAnimator.ofInt(this@SmartWidget, "backgroundOpacity", 0).apply {
interpolator = AccelerateInterpolator(3f) interpolator = AccelerateInterpolator(3f)
}, },
ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", -elevation).apply { ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", -elevation).apply {
interpolator = DecelerateInterpolator(3f) interpolator = DecelerateInterpolator(3f)
} }
) )
}.start() }.start()
@ -121,12 +111,16 @@ class SmartWidget : LauncherCardView {
AnimatorSet().apply { AnimatorSet().apply {
duration = 200 duration = 200
playTogether( playTogether(
ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", 0f).apply { ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", 0f).apply {
interpolator = AccelerateInterpolator(3f) interpolator = AccelerateInterpolator(3f)
}, },
ObjectAnimator.ofInt(this@SmartWidget, "backgroundOpacity", LauncherPreferences.instance.cardOpacity).apply { ObjectAnimator.ofInt(
interpolator = DecelerateInterpolator(3f) this@SmartWidget,
} "backgroundOpacity",
LauncherPreferences.instance.cardOpacity
).apply {
interpolator = DecelerateInterpolator(3f)
}
) )
}.start() }.start()
@ -137,7 +131,7 @@ class SmartWidget : LauncherCardView {
var compactView: CompactView? = getDefaultCompactView() var compactView: CompactView? = getDefaultCompactView()
set(value) { set(value) {
smartWidgetContainer.removeView(field as? View) binding.smartWidgetContainer.removeView(field as? View)
if (value == null) { if (value == null) {
field = getDefaultCompactView() field = getDefaultCompactView()
} else { } else {
@ -145,7 +139,7 @@ class SmartWidget : LauncherCardView {
} }
(field as? View)?.let { (field as? View)?.let {
it.layoutParams = getCompactViewLayoutParams() it.layoutParams = getCompactViewLayoutParams()
smartWidgetContainer.addView(it) binding.smartWidgetContainer.addView(it)
} }
field?.setTranslucent(translucent) field?.setTranslucent(translucent)
} }
@ -155,8 +149,10 @@ class SmartWidget : LauncherCardView {
} }
private fun getCompactViewLayoutParams(): RelativeLayout.LayoutParams { private fun getCompactViewLayoutParams(): RelativeLayout.LayoutParams {
val params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, val params = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT) RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
)
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE) params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE)
params.addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE) params.addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE)
params.addRule(RelativeLayout.START_OF, R.id.smartWidgetDivider) params.addRule(RelativeLayout.START_OF, R.id.smartWidgetDivider)
@ -186,7 +182,11 @@ class DateCompactView : TextClock, CompactView {
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(
context,
attrs,
defStyleRes
)
init { init {
isClickable = true isClickable = true
@ -201,18 +201,23 @@ class DateCompactView : TextClock, CompactView {
builder.appendPath("time") builder.appendPath("time")
ContentUris.appendId(builder, startMillis) ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
.setData(builder.build()) .setData(builder.build())
ActivityStarter.start(context, this, intent = intent) ActivityStarter.start(context, this, intent = intent)
} }
val dayFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMMdyyyy") val dayFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMMdyyyy")
val dayOfWeekFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), "EEEE") val dayOfWeekFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), "EEEE")
val dateFormat = context.getString(R.string.date_format_clock_widget, dayOfWeekFormat, dayFormat) val dateFormat =
context.getString(R.string.date_format_clock_widget, dayOfWeekFormat, dayFormat)
format12Hour = dateFormat format12Hour = dateFormat
format24Hour = dateFormat format24Hour = dateFormat
val outValue = TypedValue() val outValue = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, outValue, true) context.theme.resolveAttribute(
android.R.attr.selectableItemBackgroundBorderless,
outValue,
true
)
foreground = context.getDrawable(outValue.resourceId) foreground = context.getDrawable(outValue.resourceId)
} }
} }

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {

View File

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
id("kotlin-android") id("kotlin-android")
id("kotlin-android-extensions")
} }
android { android {