mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 11:46:32 +00:00
wearos adjustments
This commit is contained in:
parent
87cb30cae1
commit
609737e414
18 changed files with 641 additions and 36 deletions
|
|
@ -1,7 +1,9 @@
|
|||
Habitica is a free habit-building and productivity app that uses retro RPG elements to gamify your tasks and goals.
|
||||
Use Habitica to help with ADHD, self care, New Year’s resolutions, household chores, work tasks, creative projects, fitness goals, back-to-school routines, and more!
|
||||
|
||||
How it works:
|
||||
Create an avatar then add tasks, chores, or goals you’d like to work on. When you do something in real life, check it off in the app and receive gold, experience, and items that can be used in-game!
|
||||
|
||||
Features:
|
||||
• Automatically repeating tasks scheduled for your daily, weekly, or monthly routines
|
||||
• Flexible habit tracker for tasks you want to do multiple times a day or only once in awhile
|
||||
|
|
@ -17,8 +19,16 @@ Features:
|
|||
• Reminders and widgets to help keep you on track
|
||||
• Customizable color themes with dark and light mode
|
||||
• Syncing across devices
|
||||
• Brand new WearOS watch app available in version 4.0!
|
||||
|
||||
Want even more flexibility to take your tasks on the go? We have a Wear OS app on the watch!
|
||||
Wear OS features:
|
||||
• View, create, and complete Habites, Dailies, and To do’s
|
||||
• Receive rewards for your efforts with experience, food, eggs, and potions
|
||||
• Track your stats with dynamic progress bars
|
||||
• Show off your stunning pixel avatar on the watch face
|
||||
|
||||
—
|
||||
|
||||
Habitica is an open-source app run by a small team that’s made better by the work of volunteers who contribute pixel art, translations, bug fixes, and more. If you’d like to contribute, reach out!
|
||||
Community, privacy, and transparency are important to us. Your tasks are private and we don’t sell your personal data to third parties.
|
||||
If you have any questions, feel free to send feedback to admin@habitica.com! And if you enjoy our app, we would really appreciate it if you would leave us a review.
|
||||
If you have any questions, feel free to send feedback to admin@habitica.com! And if you enjoy our app, we would really appreciate it if you would leave us a review.
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
NAME=4.2.3
|
||||
CODE=6181
|
||||
CODE=6201
|
||||
|
|
@ -62,7 +62,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding, LoginViewModel>() {
|
|||
binding.loginButton.isVisible = true
|
||||
}
|
||||
}
|
||||
binding.root.smoothScrollTo(0, 0)
|
||||
binding.scrollView.smoothScrollTo(0, 0)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class MainActivity : BaseActivity<ActivityMainBinding, MainViewModel>() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
super.onCreate(savedInstanceState)
|
||||
binding.root.apply {
|
||||
binding.recyclerView.apply {
|
||||
layoutManager =
|
||||
WearableLinearLayoutManager(this@MainActivity, HabiticaScrollingLayoutCallback())
|
||||
adapter = this@MainActivity.adapter
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class SettingsActivity : BaseActivity<ActivitySettingsBinding, SettingsViewModel
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
binding = ActivitySettingsBinding.inflate(layoutInflater)
|
||||
super.onCreate(savedInstanceState)
|
||||
binding.root.apply {
|
||||
binding.recyclerView.apply {
|
||||
layoutManager =
|
||||
WearableLinearLayoutManager(this@SettingsActivity, HabiticaScrollingLayoutCallback())
|
||||
adapter = this@SettingsActivity.adapter
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.os.PersistableBundle
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.habitrpg.android.habitica.databinding.ActivitySplashBinding
|
||||
import com.habitrpg.wearos.habitica.ui.viewmodels.SplashViewModel
|
||||
|
|
@ -81,7 +80,6 @@ class SplashActivity : BaseActivity<ActivitySplashBinding, SplashViewModel>() {
|
|||
} else {
|
||||
stopAnimatingProgress()
|
||||
}
|
||||
binding.textView.isVisible = show
|
||||
delay(90.toDuration(DurationUnit.SECONDS))
|
||||
if (isActive) {
|
||||
// the sync attempt has timed out
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.wearable.timetext
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.wear.widget.CurvedTextView
|
||||
|
||||
/**
|
||||
* A wrapper around a [TextView] like object, that may not actually extend [TextView] (like a [CurvedTextView]).
|
||||
*/
|
||||
interface TextViewWrapper {
|
||||
val view: View
|
||||
var text: CharSequence?
|
||||
var textColor: Int
|
||||
}
|
||||
|
||||
/**
|
||||
* A [TextViewWrapper] wrapping a [CurvedTextView].
|
||||
*/
|
||||
class CurvedTextViewWrapper(
|
||||
override val view: CurvedTextView
|
||||
) : TextViewWrapper {
|
||||
override var text: CharSequence?
|
||||
get() = view.text
|
||||
set(value) {
|
||||
view.text = value?.toString().orEmpty()
|
||||
}
|
||||
|
||||
override var textColor: Int
|
||||
get() = view.textColor
|
||||
set(value) {
|
||||
view.textColor = value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A [TextViewWrapper] wrapping a [TextView].
|
||||
*/
|
||||
class NormalTextViewWrapper(
|
||||
override val view: TextView
|
||||
) : TextViewWrapper {
|
||||
override var text: CharSequence?
|
||||
get() = view.text
|
||||
set(value) {
|
||||
view.text = value
|
||||
}
|
||||
|
||||
override var textColor: Int
|
||||
get() = view.currentTextColor
|
||||
set(value) {
|
||||
view.setTextColor(value)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.habitrpg.wearos.habitica.ui.views
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.database.ContentObserver
|
||||
import android.graphics.Color
|
||||
import android.provider.Settings
|
||||
import android.text.format.DateFormat
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.content.res.use
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import androidx.core.view.isGone
|
||||
import com.example.android.wearable.timetext.CurvedTextViewWrapper
|
||||
import com.example.android.wearable.timetext.NormalTextViewWrapper
|
||||
import com.example.android.wearable.timetext.TextViewWrapper
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.CurvedTimeTextBinding
|
||||
import com.habitrpg.android.habitica.databinding.StraightTimeTextBinding
|
||||
import com.habitrpg.wearos.habitica.ui.views.TimeText.Clock
|
||||
import com.habitrpg.wearos.habitica.ui.views.TimeTextViewBinding.TimeTextCurvedViewBinding
|
||||
import com.habitrpg.wearos.habitica.ui.views.TimeTextViewBinding.TimeTextStraightViewBinding
|
||||
import java.util.Calendar
|
||||
|
||||
/**
|
||||
* The max sweep angle for the [TimeText] to occupy.
|
||||
*/
|
||||
private const val MAX_SWEEP_ANGLE = 90f
|
||||
|
||||
class TimeText @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
@AttrRes defStyleAttr: Int = 0,
|
||||
@StyleRes defStyleRes: Int = 0
|
||||
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
/**
|
||||
* The underlying [Calendar] instance for producing the time.
|
||||
*
|
||||
* This will be updated in [onTimeZoneChange] in response to any timezone updates.
|
||||
*/
|
||||
private var time = Calendar.getInstance()
|
||||
|
||||
/**
|
||||
* True if we should format the time in the 24 hour manner.
|
||||
*
|
||||
* This will be updated in [onTimeFormatChange] in response to any format updates.
|
||||
*/
|
||||
private var use24HourFormat = DateFormat.is24HourFormat(context)
|
||||
|
||||
/**
|
||||
* An [IntentFilter] for any time related broadcast.
|
||||
*/
|
||||
private val timeBroadcastReceiverFilter = IntentFilter().apply {
|
||||
addAction(Intent.ACTION_TIME_TICK)
|
||||
addAction(Intent.ACTION_TIME_CHANGED)
|
||||
addAction(Intent.ACTION_TIMEZONE_CHANGED)
|
||||
}
|
||||
|
||||
private val timeBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when (intent.action) {
|
||||
Intent.ACTION_TIMEZONE_CHANGED -> onTimeZoneChange()
|
||||
Intent.ACTION_TIME_TICK, Intent.ACTION_TIME_CHANGED -> onTimeChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The wrapped view binding for the inflated views.
|
||||
*/
|
||||
private val timeTextViewBinding: TimeTextViewBinding
|
||||
|
||||
/**
|
||||
* A non-clock portion of the time text to display.
|
||||
*/
|
||||
var title: CharSequence? = null
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
timeTextViewBinding.timeTextTitle.text = title
|
||||
|
||||
// Only show the title and divider if the title is non-empty
|
||||
val hideTitle = title.isNullOrEmpty()
|
||||
timeTextViewBinding.timeTextTitle.view.isGone = hideTitle
|
||||
timeTextViewBinding.timeTextDivider.view.isGone = hideTitle
|
||||
}
|
||||
|
||||
/**
|
||||
* The color of the non-clock portion of the time text.
|
||||
*/
|
||||
var titleTextColor: Int = Color.WHITE
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
timeTextViewBinding.timeTextTitle.textColor = titleTextColor
|
||||
}
|
||||
|
||||
/**
|
||||
* The backing [Clock] used to drive the time.
|
||||
*
|
||||
* Overridable for testing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
var clock: Clock = Clock(System::currentTimeMillis)
|
||||
set(value) {
|
||||
field = value
|
||||
onTimeChange()
|
||||
}
|
||||
|
||||
/**
|
||||
* The [ContentObserver] listening for a time format change.
|
||||
*
|
||||
* This is constructed lazily, since [getHandler] needs the view to be attached.
|
||||
*/
|
||||
private val timeContentObserver by lazy(LazyThreadSafetyMode.NONE) {
|
||||
object : ContentObserver(handler) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
super.onChange(selfChange)
|
||||
onTimeFormatChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val layoutInflater = LayoutInflater.from(context)
|
||||
|
||||
// Create the view structure based on whether the screen is round.
|
||||
// This will inflate one of two distinct layouts, which we abstract away in a TimeTextViewBinding
|
||||
timeTextViewBinding = if (resources.configuration.isScreenRound) {
|
||||
TimeTextCurvedViewBinding(CurvedTimeTextBinding.inflate(layoutInflater, this, true))
|
||||
} else {
|
||||
TimeTextStraightViewBinding(StraightTimeTextBinding.inflate(layoutInflater, this, true))
|
||||
}
|
||||
|
||||
// Set the divider text
|
||||
timeTextViewBinding.timeTextDivider.text = "·"
|
||||
|
||||
// Update based on the styled attributes.
|
||||
// Note that this runs the side-effects of setting those attributes.
|
||||
context.obtainStyledAttributes(attrs, R.styleable.TimeText, defStyleAttr, defStyleRes)
|
||||
.use { typedArray ->
|
||||
titleTextColor =
|
||||
typedArray.getColor(R.styleable.TimeText_android_titleTextColor, titleTextColor)
|
||||
title = typedArray.getString(R.styleable.TimeText_titleText)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restrict the total sweep angle on round screens to [MAX_SWEEP_ANGLE].
|
||||
*
|
||||
* We accomplish this with two measure passes:
|
||||
*
|
||||
* After the first, we measure to get the angle that the clock and divider occupy (together, these shouldn't ever
|
||||
* be more than [MAX_SWEEP_ANGLE].
|
||||
*
|
||||
* Then, we update the title's max sweep angle to the remaining angle, and measure again to apply the limit.
|
||||
*/
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
when (timeTextViewBinding) {
|
||||
is TimeTextCurvedViewBinding -> {
|
||||
// Reset the title sweep to ensure we get a true initial measurement
|
||||
timeTextViewBinding.timeTextTitle.view.setSweepRangeDegrees(0f, MAX_SWEEP_ANGLE)
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
|
||||
val clockSweepAngle =
|
||||
timeTextViewBinding.timeTextClock.view.sweepAngleDegrees.coerceAtLeast(0f)
|
||||
|
||||
// Avoid getting the divider sweep angle if it is gone, since it won't be accurate
|
||||
val dividerSweepAngle = if (timeTextViewBinding.timeTextDivider.view.isGone) {
|
||||
0f
|
||||
} else {
|
||||
timeTextViewBinding.timeTextDivider.view.sweepAngleDegrees.coerceAtLeast(0f)
|
||||
}
|
||||
|
||||
val maxTitleSweepAngle = MAX_SWEEP_ANGLE - clockSweepAngle - dividerSweepAngle
|
||||
|
||||
// Update the title max sweep angle to effectively get a total max sweep of MAX_SWEEP_ANGLE
|
||||
timeTextViewBinding.timeTextTitle.view.setSweepRangeDegrees(0f, maxTitleSweepAngle)
|
||||
|
||||
// Measure again, with the updated max sweep
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
}
|
||||
is TimeTextStraightViewBinding -> {
|
||||
// Need to do nothing special the for the straight view, just call through to super
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
|
||||
onTimeZoneChange()
|
||||
onTimeFormatChange()
|
||||
onTimeChange()
|
||||
|
||||
context.contentResolver.registerContentObserver(
|
||||
Settings.System.getUriFor(Settings.System.TIME_12_24),
|
||||
true,
|
||||
timeContentObserver
|
||||
)
|
||||
context.registerReceiver(timeBroadcastReceiver, timeBroadcastReceiverFilter)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
|
||||
context.contentResolver.unregisterContentObserver(timeContentObserver)
|
||||
context.unregisterReceiver(timeBroadcastReceiver)
|
||||
}
|
||||
|
||||
private fun onTimeChange() {
|
||||
val pattern = DateFormat.getBestDateTimePattern(
|
||||
ConfigurationCompat.getLocales(resources.configuration)[0],
|
||||
if (use24HourFormat) "Hm" else "hm"
|
||||
)
|
||||
// Remove the am/pm indicator (if any). This is locale safe.
|
||||
val patternWithoutAmPm = pattern.replace("a", "").trim()
|
||||
|
||||
time.timeInMillis = clock.getCurrentTimeMillis()
|
||||
timeTextViewBinding.timeTextClock.text = DateFormat.format(patternWithoutAmPm, time)
|
||||
}
|
||||
|
||||
private fun onTimeZoneChange() {
|
||||
time = Calendar.getInstance()
|
||||
onTimeChange()
|
||||
}
|
||||
|
||||
private fun onTimeFormatChange() {
|
||||
use24HourFormat = DateFormat.is24HourFormat(context)
|
||||
onTimeChange()
|
||||
}
|
||||
|
||||
/**
|
||||
* A provider of the current time.
|
||||
*/
|
||||
fun interface Clock {
|
||||
|
||||
/**
|
||||
* Returns the current time in milliseconds since the epoch.
|
||||
*/
|
||||
fun getCurrentTimeMillis(): Long
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstraction around the view binding, since we inflate two different layouts depending on the shape of the screen.
|
||||
*/
|
||||
private sealed class TimeTextViewBinding {
|
||||
|
||||
abstract val timeTextTitle: TextViewWrapper
|
||||
|
||||
abstract val timeTextDivider: TextViewWrapper
|
||||
|
||||
abstract val timeTextClock: TextViewWrapper
|
||||
|
||||
/**
|
||||
* The [TimeTextViewBinding] wrapping the [CurvedTimeTextBinding].
|
||||
*/
|
||||
class TimeTextCurvedViewBinding(
|
||||
timeTextBinding: CurvedTimeTextBinding
|
||||
) : TimeTextViewBinding() {
|
||||
override val timeTextTitle: CurvedTextViewWrapper =
|
||||
CurvedTextViewWrapper(timeTextBinding.timeTextTitle)
|
||||
override val timeTextDivider: CurvedTextViewWrapper =
|
||||
CurvedTextViewWrapper(timeTextBinding.timeTextDivider)
|
||||
override val timeTextClock: CurvedTextViewWrapper =
|
||||
CurvedTextViewWrapper(timeTextBinding.timeTextClock)
|
||||
}
|
||||
|
||||
/**
|
||||
* The [TimeTextViewBinding] wrapping the [StraightTimeTextBinding].
|
||||
*/
|
||||
class TimeTextStraightViewBinding(
|
||||
timeTextBinding: StraightTimeTextBinding
|
||||
) : TimeTextViewBinding() {
|
||||
override val timeTextTitle: NormalTextViewWrapper =
|
||||
NormalTextViewWrapper(timeTextBinding.timeTextTitle)
|
||||
override val timeTextDivider: NormalTextViewWrapper =
|
||||
NormalTextViewWrapper(timeTextBinding.timeTextDivider)
|
||||
override val timeTextClock: NormalTextViewWrapper =
|
||||
NormalTextViewWrapper(timeTextBinding.timeTextClock)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package com.habitrpg.wearos.habitica.util
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
class TopScrollAwayBehavior<V : View>(context: Context, attrs: AttributeSet) :
|
||||
CoordinatorLayout.Behavior<V>(context, attrs) {
|
||||
|
||||
override fun onStartNestedScroll(
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: V,
|
||||
directTargetChild: View,
|
||||
target: View,
|
||||
axes: Int,
|
||||
type: Int
|
||||
): Boolean {
|
||||
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
|
||||
}
|
||||
|
||||
override fun onNestedPreScroll(
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: V,
|
||||
target: View,
|
||||
dx: Int,
|
||||
dy: Int,
|
||||
consumed: IntArray,
|
||||
type: Int
|
||||
) {
|
||||
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
|
||||
child.translationY = min(0f, -min(child.height.toFloat(), -child.translationY + dy))
|
||||
}
|
||||
|
||||
override fun onStopNestedScroll(
|
||||
coordinatorLayout: CoordinatorLayout,
|
||||
child: V,
|
||||
target: View,
|
||||
type: Int
|
||||
) {
|
||||
super.onStopNestedScroll(coordinatorLayout, child, target, type)
|
||||
if (child.translationY != 0f && abs(child.translationY) != child.height.toFloat()) {
|
||||
if (abs(child.translationY) < (child.height.toFloat() / 2f) && abs(child.translationY) < 40) {
|
||||
child.translationY = 0f
|
||||
} else {
|
||||
child.translationY = if (child.top < child.bottom) -child.height.toFloat() else child.height.toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.habitrpg.wearos.habitica.ui.views.HabiticaScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.habitrpg.wearos.habitica.ui.views.HabiticaScrollView
|
||||
android:id="@+id/scroll_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
|
@ -15,7 +19,8 @@
|
|||
android:layout_height="16dp"
|
||||
android:src="@drawable/ic_gryphon_white"
|
||||
android:importantForAccessibility="no"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"/>
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:layout_marginTop="24dp"/>
|
||||
<TextView
|
||||
android:id="@+id/title_view"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -110,4 +115,11 @@
|
|||
android:textAlignment="center"
|
||||
style="@style/ChipButton.Purple"/>
|
||||
</LinearLayout>
|
||||
</com.habitrpg.wearos.habitica.ui.views.HabiticaScrollView>
|
||||
</com.habitrpg.wearos.habitica.ui.views.HabiticaScrollView>
|
||||
<com.habitrpg.wearos.habitica.ui.views.TimeText
|
||||
android:id="@+id/timeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:titleTextColor="@color/text_primary"
|
||||
app:layout_behavior="com.habitrpg.wearos.habitica.util.TopScrollAwayBehavior" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout tools:context="com.habitrpg.wearos.habitica.ui.activities.MainActivity"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.habitrpg.wearos.habitica.ui.activities.MainActivity"
|
||||
android:scrollbars="vertical"
|
||||
tools:deviceIds="wear">
|
||||
|
||||
</com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView>
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical"
|
||||
tools:deviceIds="wear">
|
||||
</com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView>
|
||||
<com.habitrpg.wearos.habitica.ui.views.TimeText
|
||||
android:id="@+id/timeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:titleTextColor="@color/text_primary"
|
||||
app:layout_behavior="com.habitrpg.wearos.habitica.util.TopScrollAwayBehavior" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout tools:context="com.habitrpg.wearos.habitica.ui.activities.MainActivity"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.habitrpg.wearos.habitica.ui.activities.SettingsActivity"
|
||||
tools:deviceIds="wear">
|
||||
|
||||
</com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView>
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical"
|
||||
tools:deviceIds="wear">
|
||||
</com.habitrpg.wearos.habitica.ui.views.HabiticaRecyclerView>
|
||||
<com.habitrpg.wearos.habitica.ui.views.TimeText
|
||||
android:id="@+id/timeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:titleTextColor="@color/text_primary"
|
||||
app:layout_behavior="com.habitrpg.wearos.habitica.util.TopScrollAwayBehavior"/>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
<TextView
|
||||
android:id="@+id/text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/syncing_account"
|
||||
android:layout_margin="@dimen/spacing_xlarge"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:gravity="center"/>
|
||||
</LinearLayout>
|
||||
<FrameLayout
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/circle"
|
||||
android:clipChildren="true"
|
||||
android:clipToOutline="true">
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
|
|
|||
|
|
@ -14,4 +14,10 @@
|
|||
android:layout_height="39dp"
|
||||
android:layout_gravity="center|bottom"
|
||||
app:layout_behavior="com.habitrpg.wearos.habitica.util.ScrollAwayBehavior"/>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
<com.habitrpg.wearos.habitica.ui.views.TimeText
|
||||
android:id="@+id/timeText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:titleTextColor="@color/text_primary"
|
||||
app:layout_behavior="com.habitrpg.wearos.habitica.util.TopScrollAwayBehavior" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
53
wearos/src/main/res/layout/curved_time_text.xml
Normal file
53
wearos/src/main/res/layout/curved_time_text.xml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<androidx.wear.widget.ArcLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/timeArcLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:anchorPosition="center">
|
||||
|
||||
<androidx.wear.widget.CurvedTextView
|
||||
android:id="@+id/timeTextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:paddingVertical="4dp"
|
||||
style="@style/TextTime"
|
||||
android:textAppearance="@style/TextAppearanceTime"
|
||||
tools:text="Text" />
|
||||
|
||||
<androidx.wear.widget.CurvedTextView
|
||||
android:id="@+id/timeTextDivider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="4dp"
|
||||
style="@style/TextTime"
|
||||
android:textAppearance="@style/TextAppearanceTime"
|
||||
tools:text="·" />
|
||||
|
||||
<androidx.wear.widget.CurvedTextView
|
||||
android:id="@+id/timeTextClock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="4dp"
|
||||
style="@style/TextTime"
|
||||
android:textAppearance="@style/TextAppearanceTime"
|
||||
tools:text="01:23" />
|
||||
|
||||
</androidx.wear.widget.ArcLayout>
|
||||
63
wearos/src/main/res/layout/straight_time_text.xml
Normal file
63
wearos/src/main/res/layout/straight_time_text.xml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginTop="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timeTextTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearanceTime"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/timeTextDivider"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
tools:text="ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timeTextDivider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="4dp"
|
||||
android:textAppearance="@style/TextAppearanceTime"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/timeTextClock"
|
||||
app:layout_constraintStart_toEndOf="@id/timeTextTitle"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="·" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timeTextClock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearanceTime"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/timeTextDivider"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="01:23" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -19,4 +19,8 @@
|
|||
<attr name="chipColor" format="color" />
|
||||
<attr name="chipTextColor" format="color" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
<declare-styleable name="TimeText">
|
||||
<attr name="android:titleTextColor" format="reference|color" />
|
||||
<attr name="titleText" format="string" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -105,4 +105,12 @@
|
|||
<item name="android:textColorHint">@color/watch_gray_200</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
<style name="TextAppearanceTime">
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:lineSpacingExtra">4sp</item>
|
||||
</style>
|
||||
<style name="TextTime">
|
||||
<item name="android:paddingHorizontal">4dp</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in a new issue