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()
} else binding.searchBar.drop()
if (scrollY == 0) {
binding.clockWidget.translucent = true
binding.clockWidget.transparentBackground = true
if (!searchVisibility) binding.searchBar.hide()
} else {
binding.clockWidget.translucent = false
binding.clockWidget.transparentBackground = false
binding.searchBar.show()
}
@ -660,22 +660,8 @@ class LauncherActivity : AppCompatActivity() {
for (widget in binding.widgetList.iterator()) {
if (widget is WidgetView) {
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?) {

View File

@ -3,33 +3,33 @@ package de.mm20.launcher2.ui.legacy.widget
import android.animation.AnimatorSet
import android.animation.LayoutTransition
import android.animation.ObjectAnimator
import android.content.ActivityNotFoundException
import android.content.ContentUris
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.provider.AlarmClock
import android.provider.CalendarContract
import android.text.format.DateFormat
import android.util.AttributeSet
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
import android.widget.RelativeLayout
import android.widget.FrameLayout
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.view.postDelayed
import androidx.lifecycle.MutableLiveData
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.legacy.helper.ActivityStarter
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.databinding.ViewDateTimeBinding
import de.mm20.launcher2.ui.legacy.view.LauncherCardView
import java.util.*
class ClockWidget : LauncherCardView {
class ClockWidget : FrameLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
@ -39,186 +39,31 @@ class ClockWidget : LauncherCardView {
defStyleRes
)
private val binding = ViewDateTimeBinding.inflate(LayoutInflater.from(context), this, true)
val view = ComposeView(context)
init {
clipToPadding = false
clipChildren = false
layoutTransition = LayoutTransition()
binding.dateTimeTimeView.format12Hour = "hh:mm"
binding.dateTimeTimeView.format24Hour = "HH:mm"
val composeView = ComposeView(context)
addView(composeView)
composeView.layoutParams =
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
binding.dateTimeTimeView.setOnClickListener {
try {
val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
ActivityStarter.start(context, this, intent = intent)
} catch (_: ActivityNotFoundException) {
// Ignore
composeView.setContent {
val transparentBg by transparentBackgroundState.observeAsState(true)
LegacyLauncherTheme {
ClockWidget(transparentBackground = transparentBg)
}
}
postDelayed(1) {
translucent = true
}
}
private val translucentDisableRunnable = Runnable@{
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 transparentBackgroundState = MutableLiveData<Boolean>()
private val translucentEnableRunnable = Runnable@{
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)
}
var transparentBackground: Boolean = true
}

View File

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

View File

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