playback: force LTR on timeline controls

Force LTR on timeline controls, as per the Material Design guidelines.

The guidelines state that while "directional" UIs should be LTR/RTL
depending on locale, "timeline" UIs should always by LTR, as the
direction of time is universal. Auxio did not do this, and so the
timeline controls would be RTL on other elements. Fix this by forcing
LTR on the UI elements that correspond to timelines.

Now, this is not the best system. To ensure that the rest of the layout
remains sane, much of the directional views have to be wrapped in a
redundant layout, which is somewhat in-efficient. However, the impact
seems to be at least negligable.
This commit is contained in:
OxygenCobalt 2022-06-22 12:31:52 -06:00
parent 55f9d4c819
commit 630950ea5d
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
26 changed files with 710 additions and 390 deletions

View file

@ -6,6 +6,9 @@
- Added a shuffle shortcut - Added a shuffle shortcut
- You can now customize what occurs when a song is played from an album/artist/genre [#164] - You can now customize what occurs when a song is played from an album/artist/genre [#164]
#### What's Improved
- Made "timeline" elements (like playback controls) always left-to-right
#### What's Fixed #### What's Fixed
- Fixed broken tablet layouts - Fixed broken tablet layouts
- Fixed seam that would appear on some album covers - Fixed seam that would appear on some album covers

View file

@ -43,8 +43,6 @@ import org.oxycblt.auxio.util.logD
* *
* TODO: Custom language support * TODO: Custom language support
* *
* TODO: Rework padding ethos
*
* TODO: Add multi-select * TODO: Add multi-select
* *
* @author OxygenCobalt * @author OxygenCobalt

View file

@ -144,15 +144,15 @@ class AlbumDetailFragment :
override fun onShowSortMenu(anchor: View) { override fun onShowSortMenu(anchor: View) {
menu(anchor, R.menu.menu_album_sort) { menu(anchor, R.menu.menu_album_sort) {
val sort = detailModel.albumSort val sort = detailModel.albumSort
requireNotNull(menu.findItem(sort.mode.itemId)).isChecked = true unlikelyToBeNull(menu.findItem(sort.mode.itemId)).isChecked = true
requireNotNull(menu.findItem(R.id.option_sort_asc)).isChecked = sort.isAscending unlikelyToBeNull(menu.findItem(R.id.option_sort_asc)).isChecked = sort.isAscending
setOnMenuItemClickListener { item -> setOnMenuItemClickListener { item ->
item.isChecked = !item.isChecked item.isChecked = !item.isChecked
detailModel.albumSort = detailModel.albumSort =
if (item.itemId == R.id.option_sort_asc) { if (item.itemId == R.id.option_sort_asc) {
sort.withAscending(item.isChecked) sort.withAscending(item.isChecked)
} else { } else {
sort.withMode(requireNotNull(Sort.Mode.fromItemId(item.itemId))) sort.withMode(unlikelyToBeNull(Sort.Mode.fromItemId(item.itemId)))
} }
true true
} }

View file

@ -139,8 +139,8 @@ class ArtistDetailFragment :
override fun onShowSortMenu(anchor: View) { override fun onShowSortMenu(anchor: View) {
menu(anchor, R.menu.menu_artist_sort) { menu(anchor, R.menu.menu_artist_sort) {
val sort = detailModel.artistSort val sort = detailModel.artistSort
requireNotNull(menu.findItem(sort.mode.itemId)).isChecked = true unlikelyToBeNull(menu.findItem(sort.mode.itemId)).isChecked = true
requireNotNull(menu.findItem(R.id.option_sort_asc)).isChecked = sort.isAscending unlikelyToBeNull(menu.findItem(R.id.option_sort_asc)).isChecked = sort.isAscending
setOnMenuItemClickListener { item -> setOnMenuItemClickListener { item ->
item.isChecked = !item.isChecked item.isChecked = !item.isChecked
@ -148,7 +148,7 @@ class ArtistDetailFragment :
if (item.itemId == R.id.option_sort_asc) { if (item.itemId == R.id.option_sort_asc) {
sort.withAscending(item.isChecked) sort.withAscending(item.isChecked)
} else { } else {
sort.withMode(requireNotNull(Sort.Mode.fromItemId(item.itemId))) sort.withMode(unlikelyToBeNull(Sort.Mode.fromItemId(item.itemId)))
} }
true true

View file

@ -140,15 +140,15 @@ class GenreDetailFragment :
override fun onShowSortMenu(anchor: View) { override fun onShowSortMenu(anchor: View) {
menu(anchor, R.menu.menu_genre_sort) { menu(anchor, R.menu.menu_genre_sort) {
val sort = detailModel.genreSort val sort = detailModel.genreSort
requireNotNull(menu.findItem(sort.mode.itemId)).isChecked = true unlikelyToBeNull(menu.findItem(sort.mode.itemId)).isChecked = true
requireNotNull(menu.findItem(R.id.option_sort_asc)).isChecked = sort.isAscending unlikelyToBeNull(menu.findItem(R.id.option_sort_asc)).isChecked = sort.isAscending
setOnMenuItemClickListener { item -> setOnMenuItemClickListener { item ->
item.isChecked = !item.isChecked item.isChecked = !item.isChecked
detailModel.genreSort = detailModel.genreSort =
if (item.itemId == R.id.option_sort_asc) { if (item.itemId == R.id.option_sort_asc) {
sort.withAscending(item.isChecked) sort.withAscending(item.isChecked)
} else { } else {
sort.withMode(requireNotNull(Sort.Mode.fromItemId(item.itemId))) sort.withMode(unlikelyToBeNull(Sort.Mode.fromItemId(item.itemId)))
} }
true true
} }

View file

@ -27,8 +27,8 @@ import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.ui.Item import org.oxycblt.auxio.ui.Item
import org.oxycblt.auxio.ui.MenuItemListener import org.oxycblt.auxio.ui.MenuItemListener
import org.oxycblt.auxio.ui.MonoAdapter import org.oxycblt.auxio.ui.MonoAdapter
import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.ui.SongViewHolder import org.oxycblt.auxio.ui.SongViewHolder
import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.ui.SyncBackingData import org.oxycblt.auxio.ui.SyncBackingData
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.context

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2022 Auxio Project
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.playback
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
/**
* A class that programmatically overrides the child layout to a left-to-right (LTR) layout
* direction.
*
* The Material Design guidelines state that any components that represent a "Timeline" should
* always be LTR. In Auxio, this applies to most of the playback components. This layout in
* particular overrides the layout direction in a way that will not disrupt how other views are laid
* out.
*/
open class NoRtlFrameLayout
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : FrameLayout(context, attrs, defStyleAttr) {
override fun onFinishInflate() {
super.onFinishInflate()
check(childCount == 1) { "This view should only contain one child" }
getChildAt(0).layoutDirection = View.LAYOUT_DIRECTION_LTR
}
}

View file

@ -73,10 +73,9 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
// Load the track color in manually as it's unclear whether the track actually supports // Load the track color in manually as it's unclear whether the track actually supports
// using a ColorStateList in the resources // using a ColorStateList in the resources
binding.playbackProgressBar.trackColor = binding.playbackProgressBar.apply {
requireContext().getColorStateListSafe(R.color.sel_track).defaultColor trackColor = requireContext().getColorStateListSafe(R.color.sel_track).defaultColor
}
binding.playbackProgressBar.progress = 0
binding.playbackPlayPause.setOnClickListener { playbackModel.invertPlaying() } binding.playbackPlayPause.setOnClickListener { playbackModel.invertPlaying() }

View file

@ -46,8 +46,6 @@ import org.oxycblt.auxio.util.textSafe
* Instantiation is done by the navigation component, **do not instantiate this fragment manually.** * Instantiation is done by the navigation component, **do not instantiate this fragment manually.**
* @author OxygenCobalt * @author OxygenCobalt
* *
* TODO: Handle RTL correctly in the playback buttons
*
* TODO: Make seek thumb grow when selected * TODO: Make seek thumb grow when selected
*/ */
class PlaybackPanelFragment : class PlaybackPanelFragment :

View file

@ -19,7 +19,6 @@ package org.oxycblt.auxio.playback
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.FrameLayout
import com.google.android.material.slider.Slider import com.google.android.material.slider.Slider
import kotlin.math.max import kotlin.math.max
import org.oxycblt.auxio.databinding.ViewSeekBarBinding import org.oxycblt.auxio.databinding.ViewSeekBarBinding
@ -52,12 +51,14 @@ constructor(
attrs: AttributeSet? = null, attrs: AttributeSet? = null,
defStyleAttr: Int = 0, defStyleAttr: Int = 0,
) : ) :
FrameLayout(context, attrs, defStyleAttr), NoRtlFrameLayout(context, attrs, defStyleAttr),
Slider.OnSliderTouchListener, Slider.OnSliderTouchListener,
Slider.OnChangeListener { Slider.OnChangeListener {
private val binding = ViewSeekBarBinding.inflate(context.inflater, this) private val binding = ViewSeekBarBinding.inflate(context.inflater, this, true)
init { init {
// As per the Material Design guidelines, timeline elements like SeekBars and Controls
// should always be LTR.
binding.seekBarSlider.addOnSliderTouchListener(this) binding.seekBarSlider.addOnSliderTouchListener(this)
binding.seekBarSlider.addOnChangeListener(this) binding.seekBarSlider.addOnChangeListener(this)
} }

View file

@ -18,6 +18,7 @@
package org.oxycblt.auxio.widgets package org.oxycblt.auxio.widgets
import android.content.Context import android.content.Context
import android.view.View
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
@ -114,6 +115,9 @@ private fun RemoteViews.applyPlayPauseControls(
R.id.widget_play_pause, R.id.widget_play_pause,
context.newBroadcastPendingIntent(PlaybackService.ACTION_PLAY_PAUSE)) context.newBroadcastPendingIntent(PlaybackService.ACTION_PLAY_PAUSE))
// Controls are timeline elements, override the layout direction to RTL
setInt(R.id.widget_controls, "setLayoutDirection", View.LAYOUT_DIRECTION_LTR)
setImageViewResource( setImageViewResource(
R.id.widget_play_pause, R.id.widget_play_pause,
if (state.isPlaying) { if (state.isPlaying) {

View file

@ -81,73 +81,91 @@
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"
app:layout_constraintEnd_toEndOf="@+id/playback_song_container" app:layout_constraintEnd_toEndOf="@+id/playback_song_container"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_repeat" android:id="@+id/playback_controls_container"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_medium" android:layout_marginBottom="@dimen/spacing_medium"
android:contentDescription="@string/desc_play_pause" android:layout_marginStart="@dimen/spacing_medium"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
tools:src="@drawable/ic_play" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium" android:layout_marginEnd="@dimen/spacing_medium"
android:contentDescription="@string/desc_shuffle" app:layout_constraintBottom_toBottomOf="parent"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" app:layout_constraintStart_toStartOf="parent">
app:tint="@color/sel_accented" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_repeat"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_play" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -78,75 +78,92 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="-16dp" android:layout_marginStart="-16dp"
android:layout_marginEnd="-16dp" android:layout_marginEnd="-16dp"
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"
app:layout_constraintEnd_toEndOf="@+id/playback_album" app:layout_constraintEnd_toEndOf="@+id/playback_album"
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/playback_album" app:layout_constraintStart_toStartOf="@+id/playback_album"
app:layout_constraintTop_toBottomOf="@+id/playback_album" /> app:layout_constraintTop_toBottomOf="@+id/playback_album" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_repeat" android:id="@+id/playback_controls_container"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar" app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar" app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar" app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar">
tools:src="@drawable/ic_pause" />
<Button <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_skip_next" android:layout_width="match_parent"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_height="match_parent">
android:layout_width="wrap_content"
android:layout_height="wrap_content" <org.oxycblt.auxio.playback.IndicatorMaterialButton
android:layout_marginStart="@dimen/spacing_large" android:id="@+id/playback_repeat"
android:contentDescription="@string/desc_skip_next" style="@style/Widget.Auxio.Button.Icon.Large"
app:icon="@drawable/ic_skip_next" android:layout_width="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause" android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause" android:layout_marginEnd="@dimen/spacing_large"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" /> android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_pause" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -10,7 +10,7 @@
android:id="@+id/playback_cover" android:id="@+id/playback_cover"
style="@style/Widget.Auxio.Image.Medium" style="@style/Widget.Auxio.Image.Medium"
android:layout_margin="@dimen/spacing_small" android:layout_margin="@dimen/spacing_small"
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar" app:layout_constraintBottom_toTopOf="@+id/playback_progress_container"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:staticIcon="@drawable/ic_album" /> tools:staticIcon="@drawable/ic_album" />
@ -22,9 +22,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_small" android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small" android:layout_marginEnd="@dimen/spacing_small"
android:textAppearance="@style/TextAppearance.Auxio.LabelLarge"
app:layout_constraintBottom_toTopOf="@+id/playback_info" app:layout_constraintBottom_toTopOf="@+id/playback_info"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause" app:layout_constraintEnd_toStartOf="@+id/playback_controls_wrapper"
app:layout_constraintStart_toEndOf="@+id/playback_cover" app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toTopOf="@+id/playback_cover" app:layout_constraintTop_toTopOf="@+id/playback_cover"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
@ -38,45 +37,61 @@
android:layout_marginStart="@dimen/spacing_small" android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small" android:layout_marginEnd="@dimen/spacing_small"
android:ellipsize="end" android:ellipsize="end"
android:textAppearance="@style/TextAppearance.Auxio.LabelMedium"
app:layout_constraintBottom_toBottomOf="@+id/playback_cover" app:layout_constraintBottom_toBottomOf="@+id/playback_cover"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause" app:layout_constraintEnd_toStartOf="@+id/playback_controls_wrapper"
app:layout_constraintStart_toEndOf="@+id/playback_cover" app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toBottomOf="@+id/playback_song" app:layout_constraintTop_toBottomOf="@+id/playback_song"
tools:text="Artist Name / Album Name" /> tools:text="Artist Name / Album Name" />
<Button <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_play_pause" android:id="@+id/playback_controls_wrapper"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
app:icon="@drawable/sel_playing_state"
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_tiny" android:layout_marginEnd="@dimen/spacing_tiny"
android:contentDescription="@string/desc_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_progress_container"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.progressindicator.LinearProgressIndicator <LinearLayout
android:id="@+id/playback_progress_bar" android:id="@+id/playback_controls_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
app:icon="@drawable/sel_playing_state" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
app:icon="@drawable/ic_skip_next" />
</LinearLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
<org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_progress_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent">
tools:progress="70" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/playback_progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small"
tools:progress="70" />
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -68,74 +68,90 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium" android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium" android:layout_marginEnd="@dimen/spacing_medium"
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_repeat" android:id="@+id/playback_controls_container"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_mid_large"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_mid_large"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_mid_large" android:layout_marginBottom="@dimen/spacing_mid_large"
android:contentDescription="@string/desc_play_pause" app:layout_constraintBottom_toBottomOf="parent">
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
tools:src="@drawable/ic_pause" />
<Button <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_skip_next" android:layout_width="match_parent"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_height="match_parent">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_mid_large"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton <org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle" android:id="@+id/playback_repeat"
style="@style/Widget.Auxio.Button.Icon.Large" style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_mid_large" android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_shuffle" android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_shuffle" app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented" app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next" app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toEndOf="@+id/playback_skip_next" app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" app:layout_constraintHorizontal_chainStyle="packed"
app:tint="@color/sel_accented" /> app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_pause" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<merge 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="match_parent"
tools:parentTag="android.widget.FrameLayout">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_repeat"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_pause" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_large"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</merge>

View file

@ -81,76 +81,91 @@
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/playback_cover" app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toBottomOf="@+id/playback_album" /> app:layout_constraintTop_toBottomOf="@+id/playback_album"
app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"/>
<org.oxycblt.auxio.playback.IndicatorMaterialButton <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_repeat" android:id="@+id/playback_controls_container"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar" android:layout_marginStart="@dimen/spacing_medium"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
tools:src="@drawable/ic_pause" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium" android:layout_marginEnd="@dimen/spacing_medium"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar" app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
app:tint="@color/sel_accented" /> app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_repeat"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_play" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -10,7 +10,7 @@
android:id="@+id/playback_cover" android:id="@+id/playback_cover"
style="@style/Widget.Auxio.Image.Small" style="@style/Widget.Auxio.Image.Small"
android:layout_margin="@dimen/spacing_small" android:layout_margin="@dimen/spacing_small"
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar" app:layout_constraintBottom_toTopOf="@+id/playback_progress_container"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:staticIcon="@drawable/ic_album" /> tools:staticIcon="@drawable/ic_album" />
@ -23,7 +23,7 @@
android:layout_marginStart="@dimen/spacing_small" android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small" android:layout_marginEnd="@dimen/spacing_small"
app:layout_constraintBottom_toTopOf="@+id/playback_info" app:layout_constraintBottom_toTopOf="@+id/playback_info"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause" app:layout_constraintEnd_toStartOf="@+id/playback_controls_wrapper"
app:layout_constraintStart_toEndOf="@+id/playback_cover" app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toTopOf="@+id/playback_cover" app:layout_constraintTop_toTopOf="@+id/playback_cover"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
@ -38,43 +38,60 @@
android:layout_marginEnd="@dimen/spacing_small" android:layout_marginEnd="@dimen/spacing_small"
android:ellipsize="end" android:ellipsize="end"
app:layout_constraintBottom_toBottomOf="@+id/playback_cover" app:layout_constraintBottom_toBottomOf="@+id/playback_cover"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause" app:layout_constraintEnd_toStartOf="@+id/playback_controls_wrapper"
app:layout_constraintStart_toEndOf="@+id/playback_cover" app:layout_constraintStart_toEndOf="@+id/playback_cover"
app:layout_constraintTop_toBottomOf="@+id/playback_song" app:layout_constraintTop_toBottomOf="@+id/playback_song"
tools:text="Artist Name / Album Name" /> tools:text="Artist Name / Album Name" />
<Button <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_play_pause" android:id="@+id/playback_controls_wrapper"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
app:icon="@drawable/sel_playing_state"
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_tiny" android:layout_marginEnd="@dimen/spacing_tiny"
android:contentDescription="@string/desc_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_progress_container"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toTopOf="@+id/playback_progress_bar"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.progressindicator.LinearProgressIndicator <LinearLayout
android:id="@+id/playback_progress_bar" android:id="@+id/playback_controls_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
app:icon="@drawable/sel_playing_state" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
app:icon="@drawable/ic_skip_next" />
</LinearLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
<org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_progress_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent">
tools:progress="70" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/playback_progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_small"
android:layout_marginEnd="@dimen/spacing_small"
tools:progress="70" />
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -65,73 +65,89 @@
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_controls_container"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton <org.oxycblt.auxio.playback.NoRtlFrameLayout
android:id="@+id/playback_repeat" android:id="@+id/playback_controls_container"
style="@style/Widget.Auxio.Button.Icon.Large" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_medium" android:layout_marginBottom="@dimen/spacing_medium"
android:contentDescription="@string/desc_play_pause" android:layout_marginStart="@dimen/spacing_medium"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:src="@drawable/ic_play" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium" android:layout_marginEnd="@dimen/spacing_medium"
android:contentDescription="@string/desc_shuffle" app:layout_constraintBottom_toBottomOf="parent"
app:icon="@drawable/ic_shuffle" app:layout_constraintStart_toStartOf="parent">
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next" <androidx.constraintlayout.widget.ConstraintLayout
app:layout_constraintEnd_toEndOf="parent" android:layout_width="match_parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" android:layout_height="match_parent">
app:tint="@color/sel_accented" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_repeat"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_play" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</org.oxycblt.auxio.playback.NoRtlFrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<merge 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="match_parent"
tools:parentTag="android.widget.FrameLayout">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_repeat"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:contentDescription="@string/desc_change_repeat"
app:icon="@drawable/ic_repeat"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
<Button
android:id="@+id/playback_skip_prev"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_prev"
app:icon="@drawable/ic_skip_prev"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_play_pause"
app:layout_constraintStart_toEndOf="@+id/playback_repeat"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/playback_play_pause"
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_play" />
<Button
android:id="@+id/playback_skip_next"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
app:icon="@drawable/ic_skip_next"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toStartOf="@+id/playback_shuffle"
app:layout_constraintStart_toEndOf="@+id/playback_play_pause"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<org.oxycblt.auxio.playback.IndicatorMaterialButton
android:id="@+id/playback_shuffle"
style="@style/Widget.Auxio.Button.Icon.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
android:contentDescription="@string/desc_shuffle"
app:icon="@drawable/ic_shuffle"
app:iconTint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout>
</merge>

View file

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
tools:parentTag="android.widget.FrameLayout">
<com.google.android.material.slider.Slider <com.google.android.material.slider.Slider
android:id="@+id/seek_bar_slider" android:id="@+id/seek_bar_slider"
@ -42,4 +41,4 @@
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar" app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
tools:text="16:16" /> tools:text="16:16" />
</merge> </FrameLayout>

View file

@ -63,6 +63,7 @@
android:text="@string/def_widget_artist" /> android:text="@string/def_widget_artist" />
<android.widget.LinearLayout <android.widget.LinearLayout
android:id="@+id/widget_controls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small"> android:layout_marginTop="@dimen/spacing_small">

View file

@ -63,6 +63,7 @@
android:text="@string/def_widget_artist" /> android:text="@string/def_widget_artist" />
<android.widget.LinearLayout <android.widget.LinearLayout
android:id="@+id/widget_controls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small" android:layout_marginTop="@dimen/spacing_small"

View file

@ -22,7 +22,6 @@
android:id="@+id/widget_aspect_ratio" android:id="@+id/widget_aspect_ratio"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@+id/widget_panel"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
@ -49,7 +48,7 @@
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<android.widget.LinearLayout <android.widget.LinearLayout
android:id="@+id/widget_panel" android:id="@+id/widget_controls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"

View file

@ -99,7 +99,6 @@
android:minHeight="@dimen/size_btn" android:minHeight="@dimen/size_btn"
android:src="@drawable/ic_play" /> android:src="@drawable/ic_play" />
</android.widget.LinearLayout> </android.widget.LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -15,7 +15,6 @@
android:id="@+id/widget_aspect_ratio" android:id="@+id/widget_aspect_ratio"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@+id/widget_panel"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
@ -42,7 +41,7 @@
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<android.widget.LinearLayout <android.widget.LinearLayout
android:id="@+id/widget_panel" android:id="@+id/widget_controls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"