Use fancier Story progress bars

This commit is contained in:
Matthieu 2023-12-21 13:47:22 +01:00
parent f2c1ae3942
commit 3fdb7762b6
4 changed files with 92 additions and 32 deletions

View File

@ -39,6 +39,8 @@ class StoriesActivity: BaseActivity() {
private lateinit var binding: ActivityStoriesBinding
private lateinit var storyProgress: StoryProgress
private lateinit var model: StoriesViewModel
override fun onCreate(savedInstanceState: Bundle?) {
@ -58,6 +60,9 @@ class StoriesActivity: BaseActivity() {
}
model = _model
storyProgress = StoryProgress(model.uiState.value.imageList.size)
binding.storyProgressImage.setImageDrawable(storyProgress)
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
model.uiState.collect { uiState ->
@ -91,8 +96,7 @@ class StoriesActivity: BaseActivity() {
binding.storyAuthor.text = uiState.username
binding.carouselProgress.text = getString(R.string.storyProgress)
.format(uiState.currentImage + 1, uiState.imageList.size)
storyProgress.currentStory = uiState.currentImage
uiState.imageList.getOrNull(uiState.currentImage)?.let {
Glide.with(binding.storyImage)
@ -156,13 +160,8 @@ class StoriesActivity: BaseActivity() {
model.count.observe(this) { state ->
// Render state in UI
model.uiState.value.durationList.getOrNull(model.uiState.value.currentImage)?.let {
val percent = 100 - ((state/it.toFloat())*100).toInt()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
binding.progressBarStory.setProgress(percent, true)
} else {
binding.progressBarStory.progress = percent
}
storyProgress.progress = 1 - (state/it.toFloat())
binding.storyProgressImage.postInvalidate()
}
}

View File

@ -0,0 +1,72 @@
package org.pixeldroid.app.stories
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
/**
* Copied & adapted from AntennaPod's EchoProgress class because it looked great and is very simple
* AntennaPod/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoProgress.java
*/
class StoryProgress(private val numStories: Int) : Drawable() {
private val paint: Paint = Paint().apply {
flags = Paint.ANTI_ALIAS_FLAG
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
color = -0x1
}
var progress = 0f
var currentStory: Int = 0
override fun draw(canvas: Canvas) {
paint.strokeWidth = 0.5f * bounds.height()
val y = 0.5f * bounds.height()
val sectionWidth = 1.0f * bounds.width() / numStories
val sectionPadding = 0.03f * sectionWidth
// Iterate over stories
for (i in 0 until numStories) {
if (i < currentStory) {
// If current drawing position is smaller than current story, the paint we will use
// should be opaque: this story is already "seen"
paint.alpha = 255
} else {
// Otherwise it should be somewhat transparent, denoting it is not yet seen
paint.alpha = 100
}
// Draw an entire line with the paint, for now ignoring partial progress within the
// current story
canvas.drawLine(
i * sectionWidth + sectionPadding,
y,
(i + 1) * sectionWidth - sectionPadding,
y,
paint
)
// If current position is equal to progress, we are drawing the current story. Thus we
// should account for partial progress and paint the beginning of the line opaquely
if (i == currentStory) {
paint.alpha = 255
canvas.drawLine(
currentStory * sectionWidth + sectionPadding,
y,
currentStory * sectionWidth + sectionPadding + progress * (sectionWidth - 2 * sectionPadding),
y,
paint
)
}
}
}
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int {
return PixelFormat.TRANSLUCENT
}
override fun setAlpha(alpha: Int) {}
override fun setColorFilter(cf: ColorFilter?) {}
}

View File

@ -58,7 +58,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBarStory"
app:layout_constraintTop_toBottomOf="@id/story_progress_image"
app:layout_constraintVertical_bias="1.0"
tools:scaleType="centerCrop"
tools:srcCompat="@tools:sample/backgrounds/scenic[10]" />
@ -73,21 +73,21 @@
android:src="@drawable/play_pause"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/carouselProgress"
app:layout_constraintTop_toTopOf="@+id/storyAge"
tools:visibility="visible" />
<ProgressBar
android:id="@+id/progressBarStory"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
<ImageView
android:id="@+id/story_progress_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
android:visibility="visible"
android:layout_height="4dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:importantForAccessibility="no"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:progress="56" />
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/storyAuthorProfilePicture"
@ -96,7 +96,7 @@
android:layout_margin="12dp"
android:contentDescription="@string/profile_picture"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBarStory"
app:layout_constraintTop_toBottomOf="@id/story_progress_image"
tools:srcCompat="@tools:sample/avatars" />
<TextView
@ -135,16 +135,6 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/carouselProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
app:layout_constraintBottom_toBottomOf="@+id/storyAuthor"
app:layout_constraintEnd_toStartOf="@+id/pause"
app:layout_constraintTop_toTopOf="@+id/storyAge"
tools:text="2/3" />
<View
android:id="@+id/viewRight"
android:layout_width="0dp"

View File

@ -332,7 +332,6 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="summary_always_show_nsfw">NSFW/CW posts will not be blurred, and will be shown by default.</string>
<string name="story_image">Story image</string>
<string name="replyToStory">Reply to %1$s</string>
<string name="storyProgress">%1$s / %2$s</string>
<string name="story_reply_error">Something went wrong sending reply</string>
<string name="error_fetch_story">Something went wrong fetching the carousel</string>
<string name="sent_reply_story">Sent reply</string>