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 {
id("com.android.application")
id("kotlin-android")
id("kotlin-android-extensions")
}
android {

View File

@ -14,7 +14,7 @@ import androidx.preference.PreferenceFragmentCompat
import de.mm20.launcher2.R
import de.mm20.launcher2.ktx.dp
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
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?) {
super.onViewCreated(view, savedInstanceState)
val previewCard = view.findViewById<LauncherCardView>(R.id.previewCard)
previewCard.strokeOpacity = 0xFF
val context = requireContext()
val previewCard = previewCard
val prefFragment = PreferenesCardInnerFragment()
prefFragment.onPreferencesReady = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,14 +3,14 @@ package de.mm20.launcher2.ui.legacy.component
import android.animation.LayoutTransition
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.*
import de.mm20.launcher2.applications.AppViewModel
import de.mm20.launcher2.search.data.Application
import de.mm20.launcher2.ui.R
import kotlinx.android.synthetic.main.view_application.view.*
import de.mm20.launcher2.ui.databinding.ViewApplicationBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
class ApplicationView : FrameLayout {
@ -21,16 +21,17 @@ class ApplicationView : FrameLayout {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
private val binding = ViewApplicationBinding.inflate(LayoutInflater.from(context), this, true)
init {
View.inflate(context, R.layout.view_application, this)
layoutTransition = LayoutTransition()
layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
applicationCard.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
binding.applicationCard.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
val viewModel: AppViewModel by (context as AppCompatActivity).viewModel()
applications = viewModel.applications
applications.observe(context as AppCompatActivity, Observer<List<Application>> {
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.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.calculator.CalculatorViewModel
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 kotlin.math.round
@ -23,8 +23,9 @@ class CalculatorView : FrameLayout {
private val calculator: LiveData<Calculator?>
private val binding = ViewCalculatorBinding.inflate(LayoutInflater.from(context), this, true)
init {
View.inflate(context, R.layout.view_calculator, this)
val viewModel: CalculatorViewModel by (context as AppCompatActivity).viewModel()
calculator = viewModel.calculator
calculator.observe(context as AppCompatActivity, Observer {
@ -39,19 +40,19 @@ class CalculatorView : FrameLayout {
private fun bind(calc: Calculator) {
calculatorTerm.text = beautifyTerm(calc.term)
calculatorSolution.text = context.getString(R.string.calculator_solution, calc.formattedString)
binding.calculatorTerm.text = beautifyTerm(calc.term)
binding.calculatorSolution.text = context.getString(R.string.calculator_solution, calc.formattedString)
if (calc.solution == round(calc.solution) && calc.term.matches(Regex("[0-9]+"))) {
val binHexOct = StringBuilder()
binHexOct.append(calc.formattedBinaryString).append("\n")
.append(calc.formattedOctString).append("\n")
.append(calc.formattedHexString)
calculatorSolutionHexBinOct.text = binHexOct.toString()
calculatorSolutionHexBinOct.visibility = View.VISIBLE
calculatorLabelHexBinOct.visibility = View.VISIBLE
binding.calculatorSolutionHexBinOct.text = binHexOct.toString()
binding.calculatorSolutionHexBinOct.visibility = View.VISIBLE
binding.calculatorLabelHexBinOct.visibility = View.VISIBLE
} else {
calculatorSolutionHexBinOct.visibility = GONE
calculatorLabelHexBinOct.visibility = GONE
binding.calculatorSolutionHexBinOct.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.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import de.mm20.launcher2.favorites.FavoritesItem
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.ui.R
import kotlinx.android.synthetic.main.edit_favorites_row.view.*
import de.mm20.launcher2.ui.databinding.EditFavoritesRowBinding
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
@ -21,17 +21,18 @@ class EditFavoritesRow @JvmOverloads constructor(
val iconRepository: IconRepository by inject()
private val binding = EditFavoritesRowBinding.inflate(LayoutInflater.from(context), this, false)
init {
View.inflate(context, R.layout.edit_favorites_row, this)
label.text = favoritesItem.searchable?.label
binding.label.text = favoritesItem.searchable?.label
lifecycleScope.launch {
iconRepository.getIcon(favoritesItem.searchable!!, (48*dp).toInt()).collect{
icon.icon = it
binding.icon.icon = it
}
}
}
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.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
@ -10,14 +11,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.updateMargins
import androidx.core.widget.TextViewCompat
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.favorites.FavoritesItem
import de.mm20.launcher2.favorites.FavoritesViewModel
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.ktx.setPadding
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.launch
import kotlinx.coroutines.withContext
@ -29,6 +29,8 @@ class EditFavoritesView @JvmOverloads constructor(
val viewModel : FavoritesViewModel by (context as AppCompatActivity).viewModel()
private val binding = DialogEditFavoritesBinding.inflate(LayoutInflater.from(context), this)
init {
View.inflate(context, R.layout.dialog_edit_favorites, this)
lifecycleScope.launch {
@ -42,45 +44,45 @@ class EditFavoritesView @JvmOverloads constructor(
favorites = withContext(Dispatchers.IO) {
viewModel.getAllFavoriteItems().toMutableList()
}
progressBar.visibility = View.GONE
itemList.addView(getLabel(R.string.edit_favorites_dialog_stage0))
binding.progressBar.visibility = View.GONE
binding.itemList.addView(getLabel(R.string.edit_favorites_dialog_stage0))
itemList.setContainerScrollView(scrollView)
binding.itemList.setContainerScrollView(binding.scrollView)
var stage = 0
for (favorite in favorites) {
if (favorite.pinPosition <= 1 && stage == 0) {
getLabel(R.string.edit_favorites_dialog_stage1).let {
it.tag = "stage1"
itemList.addDragView(it, it.getChildAt(1))
binding.itemList.addDragView(it, it.getChildAt(1))
}
stage++
}
if (favorite.pinPosition == 0 && stage == 1) {
getLabel(R.string.edit_favorites_dialog_stage2).let {
it.tag = "stage2"
itemList.addDragView(it, it.getChildAt(1))
binding.itemList.addDragView(it, it.getChildAt(1))
}
stage++
}
val view = EditFavoritesRow(context, favoritesItem = favorite)
itemList.addDragView(view, view.getDragHandle())
binding.itemList.addDragView(view, view.getDragHandle())
}
if (stage == 0) {
getLabel(R.string.edit_favorites_dialog_stage1).let {
it.tag = "stage1"
itemList.addDragView(it, it.getChildAt(1))
binding.itemList.addDragView(it, it.getChildAt(1))
}
stage++
}
if (stage == 1) {
getLabel(R.string.edit_favorites_dialog_stage2).let {
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) {
val firstItem = firstView.favoritesItem
val secondItem = secondView.favoritesItem

View File

@ -3,6 +3,7 @@ package de.mm20.launcher2.ui.legacy.component
import android.animation.LayoutTransition
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
@ -10,7 +11,7 @@ import androidx.lifecycle.*
import de.mm20.launcher2.favorites.FavoritesViewModel
import de.mm20.launcher2.search.data.Searchable
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
class FavoritesView : FrameLayout {
@ -21,17 +22,18 @@ class FavoritesView : FrameLayout {
private val favorites: LiveData<List<Searchable>>
private val binding = ViewFavoritesBinding.inflate(LayoutInflater.from(context), this, true)
init {
View.inflate(context, R.layout.view_favorites, this)
val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
favorites = viewModel.getFavorites(context.resources.getInteger(R.integer.config_columnCount))
favorites.observe(context as AppCompatActivity, Observer {
visibility = if (it?.isEmpty() == true) View.GONE else View.VISIBLE
favoritesGrid.submitItems(it)
binding.favoritesGrid.submitItems(it)
})
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.TextWatcher
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
@ -15,7 +16,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.postDelayed
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieDrawable
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.transition.ChangingLayoutTransition
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewSearchBarBinding
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
class SearchBar @JvmOverloads constructor(
@ -43,13 +43,14 @@ class SearchBar @JvmOverloads constructor(
repeatMode = LottieDrawable.REVERSE
}
private val binding = ViewSearchBarBinding.inflate(LayoutInflater.from(context), this)
init {
View.inflate(context, R.layout.view_search_bar, this)
overflowMenu.setImageDrawable(rightDrawable)
searchEdit.addTextChangedListener(object : TextWatcher {
binding.overflowMenu.setImageDrawable(rightDrawable)
binding.searchEdit.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
val text = searchEdit.text.toString()
onSearchQueryChanged?.invoke(searchEdit.text.toString())
val text = binding.searchEdit.text.toString()
onSearchQueryChanged?.invoke(binding.searchEdit.text.toString())
if (text.isEmpty()) {
if (rightDrawable.frame > rightDrawable.minFrame.toInt()) {
rightDrawable.speed = -1f
@ -74,10 +75,10 @@ class SearchBar @JvmOverloads constructor(
val viewModel = (context as AppCompatActivity).viewModel<SearchViewModel>().value
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)
else (setSearchQuery(""))
}
@ -90,22 +91,22 @@ class SearchBar @JvmOverloads constructor(
}
fun setRightIcon(iconRes: Int) {
overflowMenu.setImageResource(iconRes)
binding.overflowMenu.setImageResource(iconRes)
}
var onSearchQueryChanged: ((String) -> Unit)? = null
var onRightIconClick: ((View) -> Unit)? = null
override fun setOnTouchListener(l: OnTouchListener?) {
searchEdit.setOnTouchListener(l)
binding.searchEdit.setOnTouchListener(l)
}
fun setSearchQuery(text: String) {
searchEdit.setText(text)
binding.searchEdit.setText(text)
}
fun getSearchQuery(): String {
return searchEdit.text.toString()
return binding.searchEdit.text.toString()
}
/**
@ -168,7 +169,7 @@ class SearchBar @JvmOverloads constructor(
}
fun getWebSearchView(): View {
return webSearchView
return binding.webSearchView
}
private fun getHideAnimator(): AnimatorSet {
@ -180,7 +181,7 @@ class SearchBar @JvmOverloads constructor(
val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y)
val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius)
val shadowC = Color.argb(66, 0, 0, 0)
searchEdit.setShadowLayer(shadowR, 0f, shadowY, shadowC)
binding.searchEdit.setShadowLayer(shadowR, 0f, shadowY, shadowC)
AnimatorSet().apply {
duration = 200
playTogether(
@ -191,13 +192,13 @@ class SearchBar @JvmOverloads constructor(
interpolator = DecelerateInterpolator(3f)
duration = 150
},
ObjectAnimator.ofArgb(searchEdit, "hintTextColor", searchEdit.hintTextColors.defaultColor, Color.WHITE),
ObjectAnimator.ofArgb(searchIcon, "colorFilter", iconColor, Color.WHITE),
ObjectAnimator.ofArgb(overflowMenu, "colorFilter", iconColor, Color.WHITE),
ObjectAnimator.ofFloat(searchIcon, "alpha", 1f),
ObjectAnimator.ofFloat(overflowMenu, "alpha", 1f),
ObjectAnimator.ofFloat(searchIcon, "elevation", cardElevation),
ObjectAnimator.ofFloat(overflowMenu, "elevation", cardElevation)
ObjectAnimator.ofArgb(binding.searchEdit, "hintTextColor", binding.searchEdit.hintTextColors.defaultColor, Color.WHITE),
ObjectAnimator.ofArgb(binding.searchIcon, "colorFilter", iconColor, Color.WHITE),
ObjectAnimator.ofArgb(binding.overflowMenu, "colorFilter", iconColor, Color.WHITE),
ObjectAnimator.ofFloat(binding.searchIcon, "alpha", 1f),
ObjectAnimator.ofFloat(binding.overflowMenu, "alpha", 1f),
ObjectAnimator.ofFloat(binding.searchIcon, "elevation", cardElevation),
ObjectAnimator.ofFloat(binding.overflowMenu, "elevation", cardElevation)
)
}
}
@ -226,7 +227,7 @@ class SearchBar @JvmOverloads constructor(
val iconAlpha = iconAttrs.getFloat(0, 0f)
iconAttrs.recycle()
val iconColor = ContextCompat.getColor(context, R.color.icon_color)
searchEdit.setShadowLayer(0f, 0f, 0f, 0)
binding.searchEdit.setShadowLayer(0f, 0f, 0f, 0)
AnimatorSet().apply {
duration = 200
playTogether(
@ -236,13 +237,13 @@ class SearchBar @JvmOverloads constructor(
ObjectAnimator.ofInt(this@SearchBar, "backgroundOpacity", LauncherPreferences.instance.cardOpacity).apply {
interpolator = DecelerateInterpolator(3f)
},
ObjectAnimator.ofArgb(searchEdit, "hintTextColor", Color.WHITE, hint),
ObjectAnimator.ofArgb(searchIcon, "colorFilter", Color.WHITE, iconColor),
ObjectAnimator.ofArgb(overflowMenu, "colorFilter", Color.WHITE, iconColor),
ObjectAnimator.ofFloat(searchIcon, "alpha", iconAlpha),
ObjectAnimator.ofFloat(overflowMenu, "alpha", iconAlpha),
ObjectAnimator.ofFloat(searchIcon, "elevation", 0f),
ObjectAnimator.ofFloat(overflowMenu, "elevation", 0f)
ObjectAnimator.ofArgb(binding.searchEdit, "hintTextColor", Color.WHITE, hint),
ObjectAnimator.ofArgb(binding.searchIcon, "colorFilter", Color.WHITE, iconColor),
ObjectAnimator.ofArgb(binding.overflowMenu, "colorFilter", Color.WHITE, iconColor),
ObjectAnimator.ofFloat(binding.searchIcon, "alpha", iconAlpha),
ObjectAnimator.ofFloat(binding.overflowMenu, "alpha", iconAlpha),
ObjectAnimator.ofFloat(binding.searchIcon, "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.style.ClickableSpan
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
@ -14,8 +15,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.browser.customtabs.CustomTabsIntent
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
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.UnitConverter
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewUnitconverterBinding
import de.mm20.launcher2.unitconverter.UnitConverterViewModel
import de.mm20.launcher2.unitconverter.UnitValue
import kotlinx.android.synthetic.main.view_unitconverter.view.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import java.text.DateFormat
import java.util.*
@ -46,8 +45,9 @@ class UnitConverterView : FrameLayout {
private val unitConverter: LiveData<UnitConverter?>
private val adapter: GroupAdapter<GroupieViewHolder>
private val binding = ViewUnitconverterBinding.inflate(LayoutInflater.from(context), this, true)
init {
View.inflate(context, R.layout.view_unitconverter, this)
val unitConverterViewModel by (context as AppCompatActivity).viewModel<UnitConverterViewModel>()
unitConverter = unitConverterViewModel.unitConverter
unitConverter.observe(context as AppCompatActivity, Observer {
@ -58,7 +58,7 @@ class UnitConverterView : FrameLayout {
}
})
adapter = GroupAdapter()
unitConverterValues.also {
binding.unitConverterValues.also {
it.adapter = adapter
it.addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
}
@ -67,7 +67,7 @@ class UnitConverterView : FrameLayout {
private fun bind(converter: UnitConverter) {
val title = converter.inputValue.formattedValue + " " + converter.inputValue.formattedName
unitConverterInput.text = title
binding.unitConverterInput.text = title
/*val sb = StringBuilder()
for (unit in converter.values) {
@ -99,16 +99,16 @@ class UnitConverterView : FrameLayout {
}
if (converter.values.size > 5) {
showAllButton.visibility = View.VISIBLE
showAllButton.setOnClickListener {
binding.showAllButton.visibility = View.VISIBLE
binding.showAllButton.setOnClickListener {
section.addAll(converter.values.subList( 5, converter.values.size).map {
ValueItem(it, maxValueLength * 8f * sp)
})
showAllButton.visibility = View.GONE
showAllButton.setOnClickListener(null)
binding.showAllButton.visibility = View.GONE
binding.showAllButton.setOnClickListener(null)
}
} else {
showAllButton.visibility = View.GONE
binding.showAllButton.visibility = View.GONE
}
@ -141,13 +141,13 @@ class UnitConverterView : FrameLayout {
}
}, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
unitConverterInfo.apply {
binding.unitConverterInfo.apply {
text = infoText
visibility = View.VISIBLE
movementMethod = LinkMovementMethod.getInstance()
}
} 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.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.SimpleTarget
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.data.Websearch
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
class WebSearchView : FrameLayout {
@ -30,6 +30,8 @@ class WebSearchView : FrameLayout {
private val websearches: LiveData<List<Websearch>>
private val binding = ViewWebsearchBinding.inflate(LayoutInflater.from(context), this, true)
init {
View.inflate(context, R.layout.view_websearch, this)
val viewModel: WebsearchViewModel by (context as AppCompatActivity).viewModel()
@ -41,7 +43,7 @@ class WebSearchView : FrameLayout {
private fun updateWebsearches(websearches: List<Websearch>) {
visibility = if (websearches.isEmpty()) View.GONE else View.VISIBLE
webSearchList.removeAllViews()
binding.webSearchList.removeAllViews()
for (search in websearches) {
val chip = Chip(context)
chip.text = search.label
@ -68,7 +70,7 @@ class WebSearchView : FrameLayout {
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.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.widget.TooltipCompat
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.OneShotLayoutTransition
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.widget.*
import de.mm20.launcher2.widgets.Widget
import de.mm20.launcher2.widgets.WidgetType
import kotlinx.android.synthetic.main.view_widget.view.*
class WidgetView : LauncherCardView {
@ -29,24 +30,24 @@ class WidgetView : LauncherCardView {
var editMode = false
set(value) {
if (value) {
widgetControlPanel.visibility = View.VISIBLE
val widget = widgetWrapper[2]
binding.widgetControlPanel.visibility = View.VISIBLE
val widget = binding.widgetWrapper[2]
widget.visibility = View.GONE
widgetName.visibility = View.VISIBLE
binding.widgetName.visibility = View.VISIBLE
visibility = View.VISIBLE
layoutTransition = OneShotLayoutTransition(this)
widgetView?.layoutTransition = null
widgetWrapper.layoutTransition = null
binding.widgetWrapper.layoutTransition = null
} else {
resizeMode = false
widgetControlPanel.visibility = View.GONE
val widget = widgetWrapper[2] as LauncherWidget
binding.widgetControlPanel.visibility = View.GONE
val widget = binding.widgetWrapper[2] as LauncherWidget
widget.visibility = View.VISIBLE
widgetName.visibility = View.GONE
binding.widgetName.visibility = View.GONE
visibility = if (widget.show) View.VISIBLE else View.GONE
layoutTransition = ChangingLayoutTransition()
widgetView?.layoutTransition = ChangingLayoutTransition()
widgetWrapper.layoutTransition = ChangingLayoutTransition()
binding.widgetWrapper.layoutTransition = ChangingLayoutTransition()
}
field = value
}
@ -56,16 +57,16 @@ class WidgetView : LauncherCardView {
if (value == field) return
onResizeModeChange?.invoke(value)
if (value) {
widgetResizeDragHandle.visibility = View.VISIBLE
val widget = widgetWrapper[2]
binding.widgetResizeDragHandle.visibility = View.VISIBLE
val widget = binding.widgetWrapper[2]
widget.visibility = View.VISIBLE
widgetName.visibility = View.GONE
binding.widgetName.visibility = View.GONE
} else {
widgetResizeDragHandle.visibility = View.GONE
binding.widgetResizeDragHandle.visibility = View.GONE
if (editMode) {
val widget = widgetWrapper[2]
val widget = binding.widgetWrapper[2]
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?, defStyleRes: Int) : super(context, attrs, defStyleRes)
private val binding = ViewWidgetBinding.inflate(LayoutInflater.from(context), this)
init {
View.inflate(context, R.layout.view_widget, this)
widgetActionResize.setOnClickListener {
binding.widgetActionResize.setOnClickListener {
resizeMode = !resizeMode
}
widgetActionRemove.setOnClickListener {
binding.widgetActionRemove.setOnClickListener {
onRemove?.invoke()
}
layoutTransition = LayoutTransition().apply {
@ -93,9 +93,9 @@ class WidgetView : LauncherCardView {
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(widgetActionRemove, context.getString(R.string.widget_action_remove))
TooltipCompat.setTooltipText(widgetActionSettings, context.getString(R.string.widget_action_settings))
TooltipCompat.setTooltipText(binding.widgetActionResize, context.getString(R.string.widget_action_adjust_height))
TooltipCompat.setTooltipText(binding.widgetActionRemove, context.getString(R.string.widget_action_remove))
TooltipCompat.setTooltipText(binding.widgetActionSettings, context.getString(R.string.widget_action_settings))
}
var onResizeModeChange: ((Boolean) -> Unit)? = null
@ -108,13 +108,13 @@ class WidgetView : LauncherCardView {
MusicWidget.ID -> MusicWidget(context)
else -> return false
}
widgetActionResize.visibility = View.GONE
widgetActionSettings.visibility = if (widgetView?.hasSettings == true) View.VISIBLE else View.GONE
widgetResizeDragHandle.resizeView = widgetView
widgetWrapper.addView(widgetView, 2)
widgetName.text = widgetView?.name
binding.widgetActionResize.visibility = View.GONE
binding.widgetActionSettings.visibility = if (widgetView?.hasSettings == true) View.VISIBLE else View.GONE
binding.widgetResizeDragHandle.resizeView = widgetView
binding.widgetWrapper.addView(widgetView, 2)
binding.widgetName.text = widgetView?.name
visibility = if (widgetView?.show == true) View.VISIBLE else View.GONE
widgetActionSettings.setOnClickListener {
binding.widgetActionSettings.setOnClickListener {
widgetView?.openSettings()
/*(context as? Activity)?.finish()
context.startActivity(Intent(context, SettingsActivity::class.java).apply {
@ -123,14 +123,14 @@ class WidgetView : LauncherCardView {
}
} else {
widgetView = ExternalWidget(context, widget, widgetHost)
widgetResizeDragHandle.resizeView = widgetView
widgetResizeDragHandle.onResize = {
binding.widgetResizeDragHandle.resizeView = widgetView
binding.widgetResizeDragHandle.onResize = {
widget.height = (it / dp).toInt()
}
widgetWrapper.addView(widgetView, 2)
widgetName.text = widgetView?.name
widgetActionResize.visibility = View.VISIBLE
widgetActionSettings.visibility = View.GONE
binding.widgetWrapper.addView(widgetView, 2)
binding.widgetName.text = widgetView?.name
binding.widgetActionResize.visibility = View.VISIBLE
binding.widgetActionSettings.visibility = View.GONE
visibility = if (widgetView?.show == true) View.VISIBLE else View.GONE
}
widgetView?.onVisibilityChanged = {
@ -144,11 +144,11 @@ class WidgetView : LauncherCardView {
}
fun getDragHandle(): View {
return widgetDragHandle
return binding.widgetDragHandle
}
fun update() {
val widget = widgetWrapper[2] as? LauncherWidget ?: return
val widget = binding.widgetWrapper[2] as? LauncherWidget ?: return
widget.update()
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.text.format.DateUtils
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.calendar.CalendarViewModel
import de.mm20.launcher2.favorites.FavoritesViewModel
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.Searchable
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 java.util.*
import kotlin.math.max
@ -48,7 +48,7 @@ class CalendarWidget : LauncherWidget {
private var selectedDay = 0L
set(value) {
field = value
calendarDate.text = formatDay(value)
binding.calendarDate.text = formatDay(value)
updateEventList()
}
@ -73,19 +73,20 @@ class CalendarWidget : LauncherWidget {
}
}
private val binding = ViewCalendarWidgetBinding.inflate(LayoutInflater.from(context), this, true)
init {
clipToPadding = false
clipChildren = false
View.inflate(context, R.layout.view_calendar_widget, this)
calendarNewEvent.setOnClickListener {
binding.calendarNewEvent.setOnClickListener {
val intent = Intent(Intent.ACTION_EDIT)
intent.data = CalendarContract.Events.CONTENT_URI
ActivityStarter.start(context, this, intent = intent)
}
calendarDate.setOnClickListener {
val menu = PopupMenu(context, calendarDate)
binding.calendarDate.setOnClickListener {
val menu = PopupMenu(context, binding.calendarDate)
for (d in availableDays) {
menu.menu.add(
Menu.NONE,
@ -101,21 +102,21 @@ class CalendarWidget : LauncherWidget {
menu.show()
}
calendarOpenApp.setOnClickListener {
binding.calendarOpenApp.setOnClickListener {
val startMillis = System.currentTimeMillis()
val builder = CalendarContract.CONTENT_URI.buildUpon()
builder.appendPath("time")
ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW)
.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))
selectedDay = availableDays[i + 1]
}
calendarDatePrev.setOnClickListener {
binding.calendarDatePrev.setOnClickListener {
val i = max(1, availableDays.indexOf(selectedDay))
selectedDay = availableDays[i - 1]
}
@ -127,7 +128,7 @@ class CalendarWidget : LauncherWidget {
calendarEvents.observe(context as AppCompatActivity, {
if (!PermissionsManager.checkPermission(context, PermissionsManager.CALENDAR)) {
calendarWidgetList.submitItems(listOf(
binding.calendarWidgetList.submitItems(listOf(
MissingPermission(
context.getString(R.string.permission_calendar_widget),
PermissionsManager.CALENDAR
@ -145,21 +146,21 @@ class CalendarWidget : LauncherWidget {
})
pinnedCalendarEvents.observe(context as AppCompatActivity) {
val today = getToday()
calendarWidgetPinnedList.submitItems(it.filter {
binding.calendarWidgetPinnedList.submitItems(it.filter {
it.endTime > System.currentTimeMillis() &&
(it.startTime + zoneOffset) / (1000 * 60 * 60 * 24) != today &&
(it.endTime + zoneOffset) / (1000 * 60 * 60 * 24) != today
}.sortedBy { it.startTime })
if (it.isEmpty()) {
calendarWidgetPinnedList.visibility = View.GONE
calendarUpcomingEventsTitle.visibility = View.GONE
binding.calendarWidgetPinnedList.visibility = View.GONE
binding.calendarUpcomingEventsTitle.visibility = View.GONE
} else {
calendarWidgetPinnedList.visibility = View.VISIBLE
calendarUpcomingEventsTitle.visibility = View.VISIBLE
binding.calendarWidgetPinnedList.visibility = View.VISIBLE
binding.calendarUpcomingEventsTitle.visibility = View.VISIBLE
}
}
calendarWidgetRoot.layoutTransition = LayoutTransition().apply {
binding.calendarWidgetRoot.layoutTransition = LayoutTransition().apply {
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.drawable.AnimatedVectorDrawable
import android.util.AttributeSet
import android.view.View
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
@ -13,21 +13,17 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.ComposeView
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.graphics.alpha
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.music.MusicViewModel
import de.mm20.launcher2.music.PlaybackState
import de.mm20.launcher2.search.SearchViewModel
import de.mm20.launcher2.ui.LegacyLauncherTheme
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.WeatherWidget
import kotlinx.android.synthetic.main.compact_music.view.*
import org.koin.androidx.viewmodel.ext.android.viewModel
class MusicWidget : LauncherWidget {
@ -83,33 +79,35 @@ class MusicCompactView : FrameLayout, CompactView {
private val viewModel: MusicViewModel by (context as AppCompatActivity).viewModel()
private val binding = CompactMusicBinding.inflate(LayoutInflater.from(context), this)
override fun setTranslucent(translucent: Boolean) {
if (translucent) {
musicCompactTitle.setTextColor(Color.WHITE)
musicCompactArtist.setTextColor(Color.WHITE)
musicCompactNext.elevation = 2 * dp
musicCompactPlay.elevation = 2 * dp
musicCompactNext.alpha = 1f
musicCompactPlay.alpha = 1f
musicCompactNext.imageTintList = ColorStateList.valueOf(Color.WHITE)
musicCompactPlay.imageTintList = ColorStateList.valueOf(Color.WHITE)
binding.musicCompactTitle.setTextColor(Color.WHITE)
binding.musicCompactArtist.setTextColor(Color.WHITE)
binding.musicCompactNext.elevation = 2 * dp
binding.musicCompactPlay.elevation = 2 * dp
binding.musicCompactNext.alpha = 1f
binding.musicCompactPlay.alpha = 1f
binding.musicCompactNext.imageTintList = ColorStateList.valueOf(Color.WHITE)
binding.musicCompactPlay.imageTintList = ColorStateList.valueOf(Color.WHITE)
val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y)
val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius)
val shadowC = Color.argb(66, 0, 0, 0)
musicCompactTitle.setShadowLayer(shadowR, 0f, shadowY, shadowC)
musicCompactArtist.setShadowLayer(shadowR, 0f, shadowY, shadowC)
binding.musicCompactTitle.setShadowLayer(shadowR, 0f, shadowY, shadowC)
binding.musicCompactArtist.setShadowLayer(shadowR, 0f, shadowY, shadowC)
} else {
val primaryColor = ContextCompat.getColorStateList(context, R.color.text_color_primary)!!
musicCompactTitle.setTextColor(primaryColor)
musicCompactArtist.setTextColor(ContextCompat.getColorStateList(context, R.color.text_color_secondary))
musicCompactNext.elevation = 0f
musicCompactPlay.elevation = 0f
musicCompactNext.alpha = primaryColor.defaultColor.alpha / 255f
musicCompactPlay.alpha = primaryColor.defaultColor.alpha / 255f
musicCompactNext.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color))
musicCompactPlay.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color))
musicCompactTitle.setShadowLayer(0f, 0f, 0f, 0)
musicCompactArtist.setShadowLayer(0f, 0f, 0f, 0)
binding.musicCompactTitle.setTextColor(primaryColor)
binding.musicCompactArtist.setTextColor(ContextCompat.getColorStateList(context, R.color.text_color_secondary))
binding.musicCompactNext.elevation = 0f
binding.musicCompactPlay.elevation = 0f
binding.musicCompactNext.alpha = primaryColor.defaultColor.alpha / 255f
binding.musicCompactPlay.alpha = primaryColor.defaultColor.alpha / 255f
binding.musicCompactNext.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color))
binding.musicCompactPlay.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(context, R.color.icon_color))
binding.musicCompactTitle.setShadowLayer(0f, 0f, 0f, 0)
binding.musicCompactArtist.setShadowLayer(0f, 0f, 0f, 0)
}
}
@ -117,7 +115,7 @@ class MusicCompactView : FrameLayout, CompactView {
set(value) {
if (value != field) {
val icon = context.getDrawable(value)
musicCompactPlay.setImageDrawable(icon)
binding.musicCompactPlay.setImageDrawable(icon)
(icon as? AnimatedVectorDrawable)?.start()
field = value
}
@ -131,48 +129,47 @@ class MusicCompactView : FrameLayout, CompactView {
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
init {
View.inflate(context, R.layout.compact_music, this)
clipChildren = false
musicCompactNext.setOnClickListener {
binding.musicCompactNext.setOnClickListener {
viewModel.next()
(musicCompactNext.drawable as AnimatedVectorDrawable).start()
(binding.musicCompactNext.drawable as AnimatedVectorDrawable).start()
}
musicCompactPlay.setOnClickListener { _ ->
binding.musicCompactPlay.setOnClickListener { _ ->
viewModel.togglePause()
}
musicCompactMeta.setOnClickListener {
binding.musicCompactMeta.setOnClickListener {
ActivityStarter.start(context, this, pendingIntent = viewModel.getLaunchIntent(context))
}
viewModel.title.observe(context as AppCompatActivity, Observer {
musicCompactTitle.text = it
binding.musicCompactTitle.text = it
})
viewModel.artist.observe(context as AppCompatActivity, Observer {
musicCompactArtist.text = it
binding.musicCompactArtist.text = it
})
viewModel.playbackState.observe(context as AppCompatActivity, Observer {
if (it == PlaybackState.Playing) {
playPauseIcon = R.drawable.ic_play_to_pause
musicCompactPlay.setOnClickListener {
binding.musicCompactPlay.setOnClickListener {
viewModel.pause()
}
musicCompactTitle.isSelected = true
musicCompactArtist.isSelected = true
binding.musicCompactTitle.isSelected = true
binding.musicCompactArtist.isSelected = true
} else {
playPauseIcon = R.drawable.ic_pause_to_play
musicCompactPlay.setOnClickListener {
binding.musicCompactPlay.setOnClickListener {
viewModel.play()
}
musicCompactTitle.isSelected = false
musicCompactArtist.isSelected = false
binding.musicCompactTitle.isSelected = false
binding.musicCompactArtist.isSelected = false
}
})
}
override fun update() {
musicCompactTitle.text = viewModel.title.value
musicCompactArtist.text = viewModel.artist.value
binding.musicCompactTitle.text = viewModel.title.value
binding.musicCompactArtist.text = viewModel.artist.value
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.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextClock
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
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.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.preferences.LauncherPreferences
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.LauncherIconView
import kotlinx.android.synthetic.main.view_date_time.view.*
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.util.*
class SmartWidget : LauncherCardView {
constructor(context: Context) : super(context)
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 {
View.inflate(context, R.layout.view_date_time, this)
clipToPadding = false
clipChildren = false
layoutTransition = LayoutTransition()
dateTimeTimeView.format12Hour = "hh:mm"
dateTimeTimeView.format24Hour = "HH:mm"
binding.dateTimeTimeView.format12Hour = "hh:mm"
binding.dateTimeTimeView.format24Hour = "HH:mm"
dateTimeTimeView.setOnClickListener {
binding.dateTimeTimeView.setOnClickListener {
try {
val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
ActivityStarter.start(context, this, intent = intent)
@ -75,12 +65,12 @@ class SmartWidget : LauncherCardView {
private val translucentDisableRunnable = 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 dividerColor = ContextCompat.getColor(context, R.color.color_divider)
dateTimeTimeView.setTextColor(textColor)
bottomPadding.setBackgroundColor(dividerColor)
bottomPadding.elevation = 0f
binding.dateTimeTimeView.setTextColor(textColor)
binding.bottomPadding.setBackgroundColor(dividerColor)
binding.bottomPadding.elevation = 0f
compactView?.setTranslucent(false)
}
@ -90,10 +80,10 @@ class SmartWidget : LauncherCardView {
val shadowY = resources.getDimension(R.dimen.elevation_shadow_1dp_y)
val shadowR = resources.getDimension(R.dimen.elevation_shadow_1dp_radius)
val shadowC = Color.argb(66, 0, 0, 0)
dateTimeTimeView.setTextColor(textColor)
dateTimeTimeView.setShadowLayer(shadowR, 0f, shadowY, shadowC)
bottomPadding.setBackgroundColor(textColor)
bottomPadding.elevation = 1f
binding.dateTimeTimeView.setTextColor(textColor)
binding.dateTimeTimeView.setShadowLayer(shadowR, 0f, shadowY, shadowC)
binding.bottomPadding.setBackgroundColor(textColor)
binding.bottomPadding.elevation = 1f
compactView?.setTranslucent(true)
}
@ -106,12 +96,12 @@ class SmartWidget : LauncherCardView {
AnimatorSet().apply {
duration = 200
playTogether(
ObjectAnimator.ofInt(this@SmartWidget, "backgroundOpacity", 0).apply {
interpolator = AccelerateInterpolator(3f)
},
ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", -elevation).apply {
interpolator = DecelerateInterpolator(3f)
}
ObjectAnimator.ofInt(this@SmartWidget, "backgroundOpacity", 0).apply {
interpolator = AccelerateInterpolator(3f)
},
ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", -elevation).apply {
interpolator = DecelerateInterpolator(3f)
}
)
}.start()
@ -121,12 +111,16 @@ class SmartWidget : LauncherCardView {
AnimatorSet().apply {
duration = 200
playTogether(
ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", 0f).apply {
interpolator = AccelerateInterpolator(3f)
},
ObjectAnimator.ofInt(this@SmartWidget, "backgroundOpacity", LauncherPreferences.instance.cardOpacity).apply {
interpolator = DecelerateInterpolator(3f)
}
ObjectAnimator.ofFloat(this@SmartWidget, "translationZ", 0f).apply {
interpolator = AccelerateInterpolator(3f)
},
ObjectAnimator.ofInt(
this@SmartWidget,
"backgroundOpacity",
LauncherPreferences.instance.cardOpacity
).apply {
interpolator = DecelerateInterpolator(3f)
}
)
}.start()
@ -137,7 +131,7 @@ class SmartWidget : LauncherCardView {
var compactView: CompactView? = getDefaultCompactView()
set(value) {
smartWidgetContainer.removeView(field as? View)
binding.smartWidgetContainer.removeView(field as? View)
if (value == null) {
field = getDefaultCompactView()
} else {
@ -145,7 +139,7 @@ class SmartWidget : LauncherCardView {
}
(field as? View)?.let {
it.layoutParams = getCompactViewLayoutParams()
smartWidgetContainer.addView(it)
binding.smartWidgetContainer.addView(it)
}
field?.setTranslucent(translucent)
}
@ -155,8 +149,10 @@ class SmartWidget : LauncherCardView {
}
private fun getCompactViewLayoutParams(): RelativeLayout.LayoutParams {
val params = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT)
val params = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
)
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE)
params.addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE)
params.addRule(RelativeLayout.START_OF, R.id.smartWidgetDivider)
@ -186,7 +182,11 @@ class DateCompactView : TextClock, CompactView {
constructor(context: Context) : super(context)
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 {
isClickable = true
@ -201,18 +201,23 @@ class DateCompactView : TextClock, CompactView {
builder.appendPath("time")
ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW)
.setData(builder.build())
.setData(builder.build())
ActivityStarter.start(context, this, intent = intent)
}
val dayFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMMdyyyy")
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
format24Hour = dateFormat
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)
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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