Commit 95171022 authored by Nicolas Pomepuy's avatar Nicolas Pomepuy

Change the video tracks UI to prevent a crash

See https://issuetracker.google.com/issues/175488703
parent 9d398a9e
......@@ -23,8 +23,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="45dp"
android:height="45dp"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="45dp"
android:height="45dp"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
......
<!--
~ *************************************************************************
~ ic_collapse_arrow.xml
~ **************************************************************************
~ Copyright © 2021 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.
~ ***************************************************************************
~
~
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/player_icon_color"
android:pathData="M8.71,11.71l2.59,2.59c0.39,0.39 1.02,0.39 1.41,0l2.59,-2.59c0.63,-0.63 0.18,-1.71 -0.71,-1.71H9.41c-0.89,0 -1.33,1.08 -0.7,1.71z"/>
</vector>
......@@ -23,8 +23,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="45dp"
android:height="45dp"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
......
......@@ -23,8 +23,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="45dp"
android:height="45dp"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
......
......@@ -47,7 +47,7 @@
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/track_title"
app:layout_constraintTop_toBottomOf="@+id/options_container"
tools:visibility="visible" />
<TextView
......@@ -74,16 +74,29 @@
app:layout_constraintBottom_toBottomOf="@id/track_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/track_title"
app:srcCompat="@drawable/ic_track_more" />
app:srcCompat="@drawable/ic_collapse_arrow" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:id="@+id/options_container"
app:layout_constraintTop_toBottomOf="@+id/track_title">
<org.videolan.vlc.gui.view.CollapsibleLinearLayout
android:id="@+id/options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/track_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/track_title" />
app:layout_constraintTop_toBottomOf="@+id/options_container" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
~ *************************************************************************
~ player_overlay_track_track.xml
~ **************************************************************************
~ Copyright © 2020 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.
~ ***************************************************************************
~
~
-->
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:id="@+id/option_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/option_title"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/option_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/option_icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -57,6 +57,8 @@
android:id="@+id/tracks_separator_2"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@color/white_transparent_10"
android:focusable="false"
app:layout_constraintBottom_toTopOf="@+id/subtitle_tracks"
......@@ -80,6 +82,8 @@
android:id="@+id/tracks_separator_3"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@color/white_transparent_10"
android:focusable="false"
app:layout_constraintBottom_toTopOf="@+id/video_tracks"
......
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/audio_track_delay"
android:title="@string/audio_delay" />
</menu>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/subtitle_track_delay"
android:title="@string/spu_delay" />
<item
android:id="@+id/subtitle_track_file"
android:title="@string/subtitle_select" />
<item
android:id="@+id/subtitle_track_download"
android:title="@string/download_subtitles"/>
</menu>
\ No newline at end of file
......@@ -25,8 +25,12 @@
package org.videolan.vlc.gui.dialogs
import android.os.Bundle
import android.view.*
import androidx.appcompat.widget.PopupMenu
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
import kotlinx.coroutines.ExperimentalCoroutinesApi
......@@ -35,14 +39,12 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.videolan.libvlc.MediaPlayer
import org.videolan.tools.CoroutineContextProvider
import org.videolan.tools.DependencyProvider
import org.videolan.tools.setGone
import org.videolan.tools.setVisible
import org.videolan.tools.*
import org.videolan.vlc.PlaybackService
import org.videolan.vlc.R
import org.videolan.vlc.databinding.PlayerOverlayTracksBinding
import org.videolan.vlc.gui.dialogs.adapters.TrackAdapter
import org.videolan.vlc.gui.view.VideoTrackOption
@ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi
......@@ -57,8 +59,8 @@ class VideoTracksDialog : VLCBottomSheetDialogFragment() {
override fun initialFocusedView(): View = binding.subtitleTracks.emptyView
lateinit var menuItemListener:(Int) -> Unit
lateinit var trackSelectionListener:(Int, TrackType) -> Unit
lateinit var menuItemListener: (VideoTrackOption) -> Unit
lateinit var trackSelectionListener: (Int, TrackType) -> Unit
init {
VideoTracksDialog.registerCreator { CoroutineContextProvider() }
......@@ -127,30 +129,56 @@ class VideoTracksDialog : VLCBottomSheetDialogFragment() {
binding.tracksSeparator3.isEnabled = false
binding.tracksSeparator2.isEnabled = false
binding.audioTracks.options.addView(generateSeparator())
binding.audioTracks.options.addView(generateOptionItem(getString(R.string.audio_delay), R.drawable.ic_audiodelay, VideoTrackOption.AUDIO_DELAY))
binding.audioTracks.options.addView(generateSeparator(true))
binding.audioTracks.options.setAnimationUpdateListener {
binding.audioTracks.trackMore.rotation = if (binding.audioTracks.options.isCollapsed) 180F - (180F * it) else 180F * it
}
binding.subtitleTracks.options.addView(generateSeparator())
binding.subtitleTracks.options.addView(generateOptionItem(getString(R.string.spu_delay), R.drawable.ic_subtitledelay, VideoTrackOption.SUB_DELAY))
binding.subtitleTracks.options.addView(generateOptionItem(getString(R.string.subtitle_select), R.drawable.ic_subtitle_open_w, VideoTrackOption.SUB_PICK))
binding.subtitleTracks.options.addView(generateOptionItem(getString(R.string.download_subtitles), R.drawable.ic_am_downsub, VideoTrackOption.SUB_DOWNLOAD))
binding.subtitleTracks.options.addView(generateSeparator(true))
binding.subtitleTracks.options.setAnimationUpdateListener {
binding.subtitleTracks.trackMore.rotation = if (binding.subtitleTracks.options.isCollapsed) 180F - (180F * it) else 180F * it
}
binding.audioTracks.trackMore.setOnClickListener {
val popup = PopupMenu(requireActivity(), binding.audioTracks.trackMore)
popup.menuInflater.inflate(R.menu.audio_track_menu, popup.menu)
popup.show()
popup.setOnMenuItemClickListener {
menuItemListener.invoke(it.itemId)
dismiss()
true
}
binding.audioTracks.options.toggle()
binding.subtitleTracks.options.collapse()
}
binding.subtitleTracks.trackMore.setOnClickListener {
val popup = PopupMenu(requireActivity(), binding.subtitleTracks.trackMore, Gravity.END)
popup.menuInflater.inflate(R.menu.subtitle_track_menu, popup.menu)
popup.show()
popup.setOnMenuItemClickListener {
menuItemListener.invoke(it.itemId)
dismiss()
true
}
binding.subtitleTracks.options.toggle()
binding.audioTracks.options.collapse()
}
super.onViewCreated(view, savedInstanceState)
}
private fun generateSeparator(margin: Boolean = false) = View(context).apply {
setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white_transparent_50))
val lp = LinearLayout.LayoutParams(-1, 1.dp)
lp.marginStart = if (margin) 56.dp else 16.dp
lp.marginEnd = 16.dp
lp.topMargin = 8.dp
lp.bottomMargin = 8.dp
layoutParams = lp
}
private fun generateOptionItem(title: String, @DrawableRes icon: Int, optionId: VideoTrackOption) = VideoTrackOption(requireContext()).apply {
setIcon(icon)
setTitle(title)
setOnClickListener {
menuItemListener.invoke(optionId)
dismiss()
}
}
companion object : DependencyProvider<Any>() {
val TAG = "VLC/SavePlaylistDialog"
......@@ -159,5 +187,9 @@ class VideoTracksDialog : VLCBottomSheetDialogFragment() {
enum class TrackType {
VIDEO, AUDIO, SPU
}
enum class VideoTrackOption {
SUB_DELAY, SUB_PICK, SUB_DOWNLOAD, AUDIO_DELAY
}
}
......@@ -382,7 +382,7 @@ object UiTools {
addToGroupDialog.newGroupListener = newGroupListener
}
fun FragmentActivity.showVideoTrack(menuListener:(Int) -> Unit, trackSelectionListener:(Int, VideoTracksDialog.TrackType) -> Unit) {
fun FragmentActivity.showVideoTrack(menuListener:(VideoTracksDialog.VideoTrackOption) -> Unit, trackSelectionListener:(Int, VideoTracksDialog.TrackType) -> Unit) {
if (!isStarted()) return
val videoTracksDialog = VideoTracksDialog()
videoTracksDialog.arguments = bundleOf()
......
......@@ -127,10 +127,10 @@ class VideoPlayerOverlayDelegate (private val player: VideoPlayerActivity) {
player.showVideoTrack(
{
when (it) {
R.id.audio_track_delay -> player.delayDelegate.showAudioDelaySetting()
R.id.subtitle_track_delay -> player.delayDelegate.showSubsDelaySetting()
R.id.subtitle_track_download -> downloadSubtitles()
R.id.subtitle_track_file -> pickSubtitles()
VideoTracksDialog.VideoTrackOption.AUDIO_DELAY -> player.delayDelegate.showAudioDelaySetting()
VideoTracksDialog.VideoTrackOption.SUB_DELAY -> player.delayDelegate.showSubsDelaySetting()
VideoTracksDialog.VideoTrackOption.SUB_DOWNLOAD -> downloadSubtitles()
VideoTracksDialog.VideoTrackOption.SUB_PICK -> pickSubtitles()
}
}, { trackID: Int, trackType: VideoTracksDialog.TrackType ->
when (trackType) {
......
/*
* ************************************************************************
* CollapsibleLinearLayout.kt
* *************************************************************************
* Copyright © 2021 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.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.view.animation.AccelerateInterpolator
import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout
class CollapsibleLinearLayout : LinearLayout {
var isCollapsed = true
private var animationUpdateListener: ((Float) -> Unit)? = null
private var maxHeight: Int = -1
private val animator by lazy {
ValueAnimator().apply {
interpolator = AccelerateInterpolator()
duration = 300
addUpdateListener { animator ->
layoutParams.height = animator.animatedValue as Int
requestLayout()
animationUpdateListener?.invoke(animator.animatedFraction)
}
}
}
fun setAnimationUpdateListener(listener: (Float) -> Unit) {
this.animationUpdateListener = listener
}
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()
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
initialize()
}
private fun initialize() {
if (layoutParams is ConstraintLayout.LayoutParams) throw IllegalStateException("The parent should not be a ConstraintLayout to prevent height issues (when set to 0)")
viewTreeObserver.addOnGlobalLayoutListener(
object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
maxHeight = height
viewTreeObserver.removeOnGlobalLayoutListener(this)
layoutParams.height = 0
requestLayout()
}
})
}
fun toggle() {
val fromHeight = if (!isCollapsed) maxHeight else 0
val toHeight = if (!isCollapsed) 0 else maxHeight
isCollapsed = !isCollapsed
animator.setIntValues(fromHeight, toHeight)
animator.start()
}
fun collapse() {
if (!isCollapsed) toggle()
}
}
\ No newline at end of file
/*
* ************************************************************************
* TitleListView.kt
* *************************************************************************
* Copyright © 2020 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.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.constraintlayout.widget.ConstraintLayout
import org.videolan.vlc.R
import org.videolan.vlc.gui.helpers.getBitmapFromDrawable
class VideoTrackOption : ConstraintLayout {
private val titleView: TextView by lazy {
findViewById(R.id.option_title)
}
private val iconView: ImageView by lazy {
findViewById(R.id.option_icon)
}
fun setIcon(@DrawableRes icon:Int) {
iconView.setImageBitmap(context.getBitmapFromDrawable(icon))
}
fun setTitle(title:String) {
titleView.text = title
}
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() {
LayoutInflater.from(context).inflate(R.layout.player_overlay_track_option_item, this, true)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment