Use compose clock widget
This commit is contained in:
parent
5ff244dd1b
commit
cb49908bdc
@ -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?) {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
Loading…
x
Reference in New Issue
Block a user