[Android] Fix the focus/pressed states of the time and length text views in vidoe player

Nicolas Pomepuy git at videolan.org
Tue Aug 16 11:32:05 UTC 2022


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Fri Aug 12 11:31:32 2022 +0200| [203964193366a1d15101af45c4287d37d838e088] | committer: Duncan McNamara

Fix the focus/pressed states of the time and length text views in vidoe player

Fixes #2595

> https://code.videolan.org/videolan/vlc-android/commit/203964193366a1d15101af45c4287d37d838e088
---

 application/vlc-android/res/layout/player_hud.xml  |  12 ++-
 .../org/videolan/vlc/gui/view/FocusableTextView.kt | 108 +++++++++++++++++++++
 2 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/application/vlc-android/res/layout/player_hud.xml b/application/vlc-android/res/layout/player_hud.xml
index bfa06db98..a902c7e2a 100644
--- a/application/vlc-android/res/layout/player_hud.xml
+++ b/application/vlc-android/res/layout/player_hud.xml
@@ -184,14 +184,15 @@
                 vlc:layout_constraintTop_toTopOf="parent" />
 
 
-        <TextView
+        <org.videolan.vlc.gui.view.FocusableTextView
                 android:id="@+id/player_overlay_time"
                 style="@style/VLC.Player.TimeText"
                 android:layout_width="0dp"
-                android:importantForAccessibility="no"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="24dp"
-                android:background="?attr/selectableItemBackground"
+                android:clickable="true"
+                android:focusable="true"
+                android:importantForAccessibility="no"
                 android:nextFocusUp="@+id/ab_repeat_add_marker"
                 android:onClick="@{(v) -> player.toggleTimeDisplay()}"
                 android:text="@{Tools.millisToString(progress.time)}"
@@ -202,15 +203,16 @@
                 vlc:layout_constraintStart_toStartOf="parent" />
 
 
-        <TextView
+        <org.videolan.vlc.gui.view.FocusableTextView
                 android:id="@+id/player_overlay_length"
                 style="@style/VLC.Player.TimeText"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_marginEnd="24dp"
+                android:clickable="true"
+                android:focusable="true"
                 android:gravity="right"
                 android:importantForAccessibility="no"
-                android:background="?attr/selectableItemBackgroundBorderless"
                 android:nextFocusUp="@+id/ab_repeat_add_marker"
                 android:onClick="@{(v) -> player.toggleTimeDisplay()}"
                 tools:text="56:37"
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/view/FocusableTextView.kt b/application/vlc-android/src/org/videolan/vlc/gui/view/FocusableTextView.kt
new file mode 100644
index 000000000..ca9e0598c
--- /dev/null
+++ b/application/vlc-android/src/org/videolan/vlc/gui/view/FocusableTextView.kt
@@ -0,0 +1,108 @@
+/*
+ * ************************************************************************
+ *  FocusableTextView.kt
+ * *************************************************************************
+ * Copyright © 2022 VLC authors and VideoLAN
+ * Author: Nicolas POMEPUY
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * **************************************************************************
+ *
+ *
+ */
+
+package org.videolan.vlc.gui.view
+
+import android.content.Context
+import android.graphics.*
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.view.Gravity
+import androidx.core.content.ContextCompat
+import org.videolan.tools.dp
+import org.videolan.vlc.R
+
+/**
+ * TextView that display a custom focused/pressed state depending on the text bounds
+ * It's meant to be used when the TextView width is not set to wrap_content and we want a focus
+ * state
+ *
+ */
+open class FocusableTextView : androidx.appcompat.widget.AppCompatTextView {
+    val paint: Paint by lazy {
+        Paint().apply {
+            isAntiAlias = true
+            color = ContextCompat.getColor(context, R.color.orange500focus)
+            style = Paint.Style.FILL
+            textSize = this at FocusableTextView.textSize
+            typeface = this at FocusableTextView.typeface
+        }
+    }
+
+    constructor(context: Context) : super(context) {
+        initialize()
+    }
+
+    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
+        initialize()
+    }
+
+    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
+        initialize()
+    }
+
+    private fun initialize() {
+        background = FocusDrawable()
+    }
+
+    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
+        // do not call super to avoid displaying the ripple
+    }
+
+    /**
+     * Drawable responsible for drawing a pressed/focused state
+     * depending on the inner text size
+     */
+    inner class FocusDrawable : Drawable() {
+        override fun isStateful(): Boolean {
+            // always return true
+            return true
+        }
+
+        @Deprecated("Deprecated in Java", ReplaceWith("PixelFormat.OPAQUE", "android.graphics.PixelFormat"))
+        override fun getOpacity(): Int {
+            return PixelFormat.OPAQUE
+        }
+
+        override fun setColorFilter(colorFilter: ColorFilter?) {}
+        override fun setAlpha(i: Int) {}
+        var pressed = false
+        override fun onStateChange(states: IntArray): Boolean {
+            invalidateSelf()
+            return true
+        }
+
+        override fun draw(canvas: Canvas) {
+            // draw only when the view is pressed / focused
+            if (state.firstOrNull { it == android.R.attr.state_pressed || it == android.R.attr.state_focused } != null) {
+                val textBounds = Rect()
+                paint.getTextBounds(text.toString(), 0, text.length, textBounds)
+                if (gravity and Gravity.RIGHT != 1)
+                    canvas.drawRoundRect(width.toFloat() - (textBounds.width().toFloat() + paddingLeft + paddingRight), 0F, width.toFloat(), bounds.height().toFloat(), 4.dp.toFloat(), 4.dp.toFloat(), paint)
+                else
+                    canvas.drawRoundRect(textBounds.left.toFloat(), 0F, textBounds.right.toFloat() + paddingLeft + paddingRight, bounds.height().toFloat(), 4.dp.toFloat(), 4.dp.toFloat(), paint)
+            }
+        }
+    }
+}
\ No newline at end of file



More information about the Android mailing list