Use compose clock widget

This commit is contained in:
MM20 2021-12-15 19:51:46 +01:00
parent 5ff244dd1b
commit cb49908bdc
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
5 changed files with 27 additions and 245 deletions

View File

@ -256,10 +256,10 @@ class LauncherActivity : AppCompatActivity() {
binding.searchBar.raise() binding.searchBar.raise()
} else binding.searchBar.drop() } else binding.searchBar.drop()
if (scrollY == 0) { if (scrollY == 0) {
binding.clockWidget.translucent = true binding.clockWidget.transparentBackground = true
if (!searchVisibility) binding.searchBar.hide() if (!searchVisibility) binding.searchBar.hide()
} else { } else {
binding.clockWidget.translucent = false binding.clockWidget.transparentBackground = false
binding.searchBar.show() binding.searchBar.show()
} }
@ -660,22 +660,8 @@ class LauncherActivity : AppCompatActivity() {
for (widget in binding.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) {
topWidget = widget.widgetView
topWidgetRanking = widget.widgetView?.compactViewRanking ?: 0
topWidgetView = widget
}
} }
} }
val compactView = topWidget?.compactView
compactView?.update()
compactView?.goToParent = {
ObjectAnimator.ofFloat(
binding.scrollView, "scrollY", topWidgetView?.top?.toFloat()
?: 0f
).start()
}
binding.clockWidget.compactView = compactView
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View File

@ -3,33 +3,33 @@ package de.mm20.launcher2.ui.legacy.widget
import android.animation.AnimatorSet import android.animation.AnimatorSet
import android.animation.LayoutTransition import android.animation.LayoutTransition
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.content.ActivityNotFoundException
import android.content.ContentUris import android.content.ContentUris
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.provider.AlarmClock
import android.provider.CalendarContract 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.LayoutInflater
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.RelativeLayout import android.widget.FrameLayout
import android.widget.TextClock import android.widget.TextClock
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.platform.ComposeView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.postDelayed import androidx.lifecycle.MutableLiveData
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.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.ui.ClockWidget
import de.mm20.launcher2.ui.LegacyLauncherTheme
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewDateTimeBinding
import de.mm20.launcher2.ui.legacy.view.LauncherCardView import de.mm20.launcher2.ui.legacy.view.LauncherCardView
import java.util.* import java.util.*
class ClockWidget : LauncherCardView { class ClockWidget : FrameLayout {
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)
@ -39,186 +39,31 @@ class ClockWidget : LauncherCardView {
defStyleRes defStyleRes
) )
private val binding = ViewDateTimeBinding.inflate(LayoutInflater.from(context), this, true) val view = ComposeView(context)
init { init {
clipToPadding = false clipToPadding = false
clipChildren = false clipChildren = false
layoutTransition = LayoutTransition() layoutTransition = LayoutTransition()
binding.dateTimeTimeView.format12Hour = "hh:mm" val composeView = ComposeView(context)
binding.dateTimeTimeView.format24Hour = "HH:mm"
addView(composeView)
composeView.layoutParams =
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
binding.dateTimeTimeView.setOnClickListener { composeView.setContent {
try { val transparentBg by transparentBackgroundState.observeAsState(true)
val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS) LegacyLauncherTheme {
ActivityStarter.start(context, this, intent = intent) ClockWidget(transparentBackground = transparentBg)
} catch (_: ActivityNotFoundException) {
// Ignore
} }
} }
postDelayed(1) {
translucent = true
}
} }
private val translucentDisableRunnable = Runnable@{ private val transparentBackgroundState = MutableLiveData<Boolean>()
if (translucent) return@Runnable
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)
binding.dateTimeTimeView.setTextColor(textColor)
binding.bottomPadding.setBackgroundColor(dividerColor)
binding.bottomPadding.elevation = 0f
compactView?.setTranslucent(false)
}
private val translucentEnableRunnable = Runnable@{ var transparentBackground: Boolean = true
if (!translucent) return@Runnable
val textColor = Color.argb(255, 255, 255, 255)
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)
binding.dateTimeTimeView.setTextColor(textColor)
binding.dateTimeTimeView.setShadowLayer(shadowR, 0f, shadowY, shadowC)
binding.bottomPadding.setBackgroundColor(textColor)
binding.bottomPadding.elevation = 1f
compactView?.setTranslucent(true)
}
var translucent: Boolean = false
set(value) {
if (value == field) return
if (value) {
removeCallbacks(translucentDisableRunnable)
postDelayed(translucentEnableRunnable, 100)
AnimatorSet().apply {
duration = 200
playTogether(
ObjectAnimator.ofInt(this@ClockWidget, "backgroundOpacity", 0).apply {
interpolator = AccelerateInterpolator(3f)
},
ObjectAnimator.ofFloat(this@ClockWidget, "translationZ", -elevation).apply {
interpolator = DecelerateInterpolator(3f)
}
)
}.start()
} else {
removeCallbacks(translucentEnableRunnable)
postDelayed(translucentDisableRunnable, 70)
AnimatorSet().apply {
duration = 200
playTogether(
ObjectAnimator.ofFloat(this@ClockWidget, "translationZ", 0f).apply {
interpolator = AccelerateInterpolator(3f)
},
ObjectAnimator.ofInt(
this@ClockWidget,
"backgroundOpacity",
LauncherPreferences.instance.cardOpacity
).apply {
interpolator = DecelerateInterpolator(3f)
}
)
}.start()
}
field = value
}
var compactView: CompactView? = getDefaultCompactView()
set(value) {
binding.clockWidgetContainer.removeView(field as? View)
if (value == null) {
field = getDefaultCompactView()
} else {
field = value
}
(field as? View)?.let {
it.layoutParams = getCompactViewLayoutParams()
binding.clockWidgetContainer.addView(it)
}
field?.setTranslucent(translucent)
}
private fun getDefaultCompactView(): CompactView {
return DateCompactView(context)
}
private fun getCompactViewLayoutParams(): RelativeLayout.LayoutParams {
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.clockWidgetDivider)
params.marginStart = (16 * dp).toInt()
params.marginEnd = (16 * dp).toInt()
return params
}
}
class DateCompactView : TextClock, CompactView {
override fun setTranslucent(translucent: Boolean) {
if (translucent) {
val textColor = Color.argb(255, 255, 255, 255)
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)
setShadowLayer(shadowR, 0f, shadowY, shadowC)
setTextColor(textColor)
} else {
val textColor = ContextCompat.getColorStateList(context, R.color.text_color_primary)
setShadowLayer(0f, 0f, 0f, 0)
setTextColor(textColor)
}
}
override var goToParent: (() -> Unit)? = null
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(
context,
attrs,
defStyleRes
)
init {
isClickable = true
elevation = 2 * dp
isFocusable = true
setPadding(0, (16 * dp).toInt(), 0, (16 * dp).toInt())
textSize = 20f
setTextColor(ContextCompat.getColorStateList(context, R.color.text_color_primary))
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, 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)
format12Hour = dateFormat
format24Hour = dateFormat
val outValue = TypedValue()
context.theme.resolveAttribute(
android.R.attr.selectableItemBackgroundBorderless,
outValue,
true
)
foreground = context.getDrawable(outValue.resourceId)
}
} }

View File

@ -11,6 +11,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -34,8 +35,7 @@ fun ClockWidget(
val insets = LocalWindowInsets.current val insets = LocalWindowInsets.current
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth(),
.height((windowHeight - insets.systemBars.bottom).toDp()),
contentAlignment = Alignment.BottomCenter contentAlignment = Alignment.BottomCenter
) { ) {
val contentColor by animateColorAsState( val contentColor by animateColorAsState(

View File

@ -129,13 +129,10 @@
android:paddingTop="8dp" android:paddingTop="8dp"
android:orientation="vertical"> android:orientation="vertical">
<de.mm20.launcher2.view.ElevationImageView <Space
android:id="@+id/widgetSpacer" android:id="@+id/widgetSpacer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
android:elevation="@dimen/card_elevation"
android:src="@drawable/ic_arrow_up"
android:tint="#fff" />
<de.mm20.launcher2.ui.legacy.widget.ClockWidget <de.mm20.launcher2.ui.legacy.widget.ClockWidget
android:id="@+id/clockWidget" android:id="@+id/clockWidget"

View File

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clockWidgetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:clipChildren="false"
android:clipToPadding="false">
<FrameLayout
android:id="@+id/clockWidgetDivider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/dateTimeTimeView"
android:elevation="2dp">
<View
android:id="@+id/bottomPadding"
android:layout_width="1dp"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="@color/color_divider"/>
</FrameLayout>
<TextClock
android:id="@+id/dateTimeTimeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:clickable="true"
android:elevation="2dp"
android:focusable="true"
android:fontFamily="sans-serif-light"
android:foreground="?selectableItemBackgroundBorderless"
android:paddingStart="20dp"
android:textColor="?android:textColorPrimary"
android:textSize="36sp"/>
</RelativeLayout>