all: remove databinding
Remove databinding entirely. Databinding was a terrible idea for Auxio. I rarely leveraged it, and when I did, it produced messy code and bloated build times. Dumpster it for just viewbinding, which is good. This reduces building times by nearly 2/3, and generally makes the codebase more coherent and usable.
This commit is contained in:
parent
95057ec357
commit
d79592e029
61 changed files with 861 additions and 1307 deletions
|
@ -17,7 +17,7 @@ android {
|
|||
targetSdkVersion 32
|
||||
|
||||
buildFeatures {
|
||||
dataBinding true
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ import androidx.activity.viewModels
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import org.oxycblt.auxio.databinding.ActivityMainBinding
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.playback.system.PlaybackService
|
||||
|
@ -54,10 +52,9 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
setupTheme()
|
||||
|
||||
val binding =
|
||||
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
|
||||
|
||||
applyEdgeToEdgeWindow(binding)
|
||||
val binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
applyEdgeToEdgeWindow(binding.root)
|
||||
|
||||
logD("Activity created")
|
||||
}
|
||||
|
@ -114,7 +111,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun applyEdgeToEdgeWindow(binding: ViewBinding) {
|
||||
private fun applyEdgeToEdgeWindow(contentView: View) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
logD("Doing R+ edge-to-edge")
|
||||
|
||||
|
@ -124,7 +121,7 @@ class MainActivity : AppCompatActivity() {
|
|||
// the R+ SDK decides to make you specify the insets yourself with a barely
|
||||
// documented API that isn't even mentioned in any of the edge-to-edge
|
||||
// tutorials. Thanks android, very cool!
|
||||
binding.root.setOnApplyWindowInsetsListener { _, insets ->
|
||||
contentView.setOnApplyWindowInsetsListener { view, insets ->
|
||||
WindowInsets.Builder()
|
||||
.setInsets(
|
||||
WindowInsets.Type.systemBars(),
|
||||
|
@ -133,27 +130,25 @@ class MainActivity : AppCompatActivity() {
|
|||
WindowInsets.Type.systemGestures(),
|
||||
insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemGestures()))
|
||||
.build()
|
||||
.applyLeftRightInsets(binding)
|
||||
.applyLeftRightInsets(view)
|
||||
}
|
||||
} else {
|
||||
// Do old edge-to-edge otherwise.
|
||||
logD("Doing legacy edge-to-edge")
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
binding.root.apply {
|
||||
contentView.apply {
|
||||
systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
|
||||
setOnApplyWindowInsetsListener { _, insets -> insets.applyLeftRightInsets(binding) }
|
||||
setOnApplyWindowInsetsListener { view, insets -> insets.applyLeftRightInsets(view) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WindowInsets.applyLeftRightInsets(binding: ViewBinding): WindowInsets {
|
||||
private fun WindowInsets.applyLeftRightInsets(contentView: View): WindowInsets {
|
||||
val bars = systemBarInsetsCompat
|
||||
|
||||
binding.root.updatePadding(left = bars.left, right = bars.right)
|
||||
|
||||
contentView.updatePadding(left = bars.left, right = bars.right)
|
||||
return replaceSystemBarInsetsCompat(0, bars.top, 0, bars.bottom)
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.widget.ImageView
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.databinding.BindingAdapter
|
||||
import coil.dispose
|
||||
import coil.imageLoader
|
||||
import coil.load
|
||||
|
@ -39,28 +38,25 @@ import org.oxycblt.auxio.music.Song
|
|||
// --- BINDING ADAPTERS ---
|
||||
|
||||
/** Bind the album cover for a [song]. */
|
||||
@BindingAdapter("albumArt")
|
||||
fun ImageView.bindAlbumCover(song: Song?) =
|
||||
fun ImageView.applyAlbumCover(song: Song?) =
|
||||
load(song, R.drawable.ic_album, R.string.desc_album_cover)
|
||||
|
||||
/** Bind the album cover for an [album]. */
|
||||
@BindingAdapter("albumArt")
|
||||
fun ImageView.bindAlbumCover(album: Album?) =
|
||||
fun ImageView.applyAlbumCover(album: Album?) =
|
||||
load(album, R.drawable.ic_album, R.string.desc_album_cover)
|
||||
|
||||
/** Bind the image for an [artist] */
|
||||
@BindingAdapter("artistImage")
|
||||
fun ImageView.bindArtistImage(artist: Artist?) =
|
||||
fun ImageView.applyArtistImage(artist: Artist?) =
|
||||
load(artist, R.drawable.ic_artist, R.string.desc_artist_image)
|
||||
|
||||
/** Bind the image for a [genre] */
|
||||
@BindingAdapter("genreImage")
|
||||
fun ImageView.bindGenreImage(genre: Genre?) =
|
||||
fun ImageView.applyGenreImage(genre: Genre?) =
|
||||
load(genre, R.drawable.ic_genre, R.string.desc_genre_image)
|
||||
|
||||
fun <T : Music> ImageView.load(music: T?, @DrawableRes error: Int, @StringRes desc: Int) {
|
||||
contentDescription = context.getString(desc, music?.resolvedName)
|
||||
dispose()
|
||||
scaleType = ImageView.ScaleType.FIT_CENTER
|
||||
load(music) {
|
||||
error(error)
|
||||
transformations(SquareFrameTransform.INSTANCE)
|
||||
|
|
|
@ -24,7 +24,7 @@ import androidx.recyclerview.widget.ListAdapter
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
|
||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
|
@ -32,12 +32,14 @@ import org.oxycblt.auxio.music.ActionHeader
|
|||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Item
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.toDuration
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.ActionHeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.util.getPluralSafe
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* An adapter for displaying the details and [Song]s of an [Album]
|
||||
|
@ -127,14 +129,14 @@ class AlbumDetailAdapter(
|
|||
|
||||
override fun onBind(data: Album) {
|
||||
binding.detailCover.apply {
|
||||
bindAlbumCover(data)
|
||||
applyAlbumCover(data)
|
||||
contentDescription = context.getString(R.string.desc_album_cover, data.resolvedName)
|
||||
}
|
||||
|
||||
binding.detailName.text = data.resolvedName
|
||||
binding.detailName.textSafe = data.resolvedName
|
||||
|
||||
binding.detailSubhead.apply {
|
||||
text = data.artist.resolvedName
|
||||
textSafe = data.artist.resolvedName
|
||||
setOnClickListener { detailModel.navToItem(data.artist) }
|
||||
}
|
||||
|
||||
|
@ -157,14 +159,25 @@ class AlbumDetailAdapter(
|
|||
private val binding: ItemAlbumSongBinding,
|
||||
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable {
|
||||
override fun onBind(data: Song) {
|
||||
binding.song = data
|
||||
binding.songName.requestLayout()
|
||||
// Hide the track number view if the song does not have a track.
|
||||
if (data.track != null) {
|
||||
binding.songTrack.apply {
|
||||
textSafe = context.getString(R.string.fmt_number, data.track)
|
||||
isInvisible = false
|
||||
}
|
||||
|
||||
// Hide the track number view if the track is zero, as generally a track number of
|
||||
// zero implies that the song does not have a track number.
|
||||
val usePlaceholder = data.track == null
|
||||
binding.songTrack.isInvisible = usePlaceholder
|
||||
binding.songTrackPlaceholder.isInvisible = !usePlaceholder
|
||||
binding.songTrackPlaceholder.isInvisible = true
|
||||
} else {
|
||||
binding.songTrack.apply {
|
||||
textSafe = ""
|
||||
isInvisible = true
|
||||
}
|
||||
|
||||
binding.songTrackPlaceholder.isInvisible = false
|
||||
}
|
||||
|
||||
binding.songName.textSafe = data.resolvedName
|
||||
binding.songDuration.textSafe = data.seconds.toDuration(false)
|
||||
}
|
||||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
|
|
|
@ -23,23 +23,26 @@ import androidx.recyclerview.widget.ListAdapter
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindArtistImage
|
||||
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
|
||||
import org.oxycblt.auxio.databinding.ItemArtistSongBinding
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.coil.applyArtistImage
|
||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||
import org.oxycblt.auxio.databinding.ItemParentBinding
|
||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||
import org.oxycblt.auxio.music.ActionHeader
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Item
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.bindArtistInfo
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.ActionHeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.ui.HeaderViewHolder
|
||||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.getPluralSafe
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* An adapter for displaying the [Album]s and [Song]s of an artist.
|
||||
|
@ -73,9 +76,9 @@ class ArtistDetailAdapter(
|
|||
IntegerTable.ITEM_TYPE_ARTIST_DETAIL ->
|
||||
ArtistDetailViewHolder(ItemDetailBinding.inflate(parent.context.inflater))
|
||||
IntegerTable.ITEM_TYPE_ARTIST_ALBUM ->
|
||||
ArtistAlbumViewHolder(ItemArtistAlbumBinding.inflate(parent.context.inflater))
|
||||
ArtistAlbumViewHolder(ItemParentBinding.inflate(parent.context.inflater))
|
||||
IntegerTable.ITEM_TYPE_ARTIST_SONG ->
|
||||
ArtistSongViewHolder(ItemArtistSongBinding.inflate(parent.context.inflater))
|
||||
ArtistSongViewHolder(ItemSongBinding.inflate(parent.context.inflater))
|
||||
IntegerTable.ITEM_TYPE_HEADER -> HeaderViewHolder.from(parent.context)
|
||||
IntegerTable.ITEM_TYPE_ACTION_HEADER -> ActionHeaderViewHolder.from(parent.context)
|
||||
else -> error("Invalid ViewHolder item type $viewType")
|
||||
|
@ -173,16 +176,16 @@ class ArtistDetailAdapter(
|
|||
val context = binding.root.context
|
||||
|
||||
binding.detailCover.apply {
|
||||
bindArtistImage(data)
|
||||
applyArtistImage(data)
|
||||
contentDescription =
|
||||
context.getString(R.string.desc_artist_image, data.resolvedName)
|
||||
}
|
||||
|
||||
binding.detailName.text = data.resolvedName
|
||||
binding.detailName.textSafe = data.resolvedName
|
||||
|
||||
// Get the genre that corresponds to the most songs in this artist, which would be
|
||||
// the most "Prominent" genre.
|
||||
binding.detailSubhead.text =
|
||||
binding.detailSubhead.textSafe =
|
||||
data.songs
|
||||
.groupBy { it.genre.resolvedName }
|
||||
.entries
|
||||
|
@ -190,7 +193,11 @@ class ArtistDetailAdapter(
|
|||
?.key
|
||||
?: context.getString(R.string.def_genre)
|
||||
|
||||
binding.detailInfo.bindArtistInfo(data)
|
||||
binding.detailInfo.textSafe =
|
||||
binding.context.getString(
|
||||
R.string.fmt_two,
|
||||
binding.context.getPluralSafe(R.plurals.fmt_album_count, data.albums.size),
|
||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size))
|
||||
|
||||
binding.detailPlayButton.setOnClickListener { playbackModel.playArtist(data, false) }
|
||||
|
||||
|
@ -199,24 +206,26 @@ class ArtistDetailAdapter(
|
|||
}
|
||||
|
||||
inner class ArtistAlbumViewHolder(
|
||||
private val binding: ItemArtistAlbumBinding,
|
||||
private val binding: ItemParentBinding,
|
||||
) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick), Highlightable {
|
||||
override fun onBind(data: Album) {
|
||||
binding.album = data
|
||||
binding.albumName.requestLayout()
|
||||
binding.parentImage.applyAlbumCover(data)
|
||||
binding.parentName.textSafe = data.resolvedName
|
||||
binding.parentInfo.textSafe = binding.context.getString(R.string.fmt_number, data.year)
|
||||
}
|
||||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
binding.albumName.isActivated = isHighlighted
|
||||
binding.parentName.isActivated = isHighlighted
|
||||
}
|
||||
}
|
||||
|
||||
inner class ArtistSongViewHolder(
|
||||
private val binding: ItemArtistSongBinding,
|
||||
private val binding: ItemSongBinding,
|
||||
) : BaseViewHolder<Song>(binding, doOnSongClick, doOnLongClick), Highlightable {
|
||||
override fun onBind(data: Song) {
|
||||
binding.song = data
|
||||
binding.songName.requestLayout()
|
||||
binding.songAlbumCover.applyAlbumCover(data)
|
||||
binding.songName.textSafe = data.resolvedName
|
||||
binding.songInfo.textSafe = data.resolvedAlbumName
|
||||
}
|
||||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
|
|
|
@ -23,19 +23,22 @@ import androidx.recyclerview.widget.ListAdapter
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindGenreImage
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.coil.applyGenreImage
|
||||
import org.oxycblt.auxio.databinding.ItemDetailBinding
|
||||
import org.oxycblt.auxio.databinding.ItemGenreSongBinding
|
||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||
import org.oxycblt.auxio.music.ActionHeader
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Item
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.bindGenreInfo
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.ActionHeaderViewHolder
|
||||
import org.oxycblt.auxio.ui.BaseViewHolder
|
||||
import org.oxycblt.auxio.ui.DiffCallback
|
||||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.getPluralSafe
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* An adapter for displaying the [Song]s of a genre.
|
||||
|
@ -64,9 +67,7 @@ class GenreDetailAdapter(
|
|||
GenreDetailViewHolder(ItemDetailBinding.inflate(parent.context.inflater))
|
||||
IntegerTable.ITEM_TYPE_ACTION_HEADER -> ActionHeaderViewHolder.from(parent.context)
|
||||
IntegerTable.ITEM_TYPE_GENRE_SONG ->
|
||||
GenreSongViewHolder(
|
||||
ItemGenreSongBinding.inflate(parent.context.inflater),
|
||||
)
|
||||
GenreSongViewHolder(ItemSongBinding.inflate(parent.context.inflater))
|
||||
else -> error("Bad ViewHolder item type $viewType")
|
||||
}
|
||||
}
|
||||
|
@ -127,13 +128,14 @@ class GenreDetailAdapter(
|
|||
val context = binding.root.context
|
||||
|
||||
binding.detailCover.apply {
|
||||
bindGenreImage(data)
|
||||
applyGenreImage(data)
|
||||
contentDescription = context.getString(R.string.desc_genre_image, data.resolvedName)
|
||||
}
|
||||
|
||||
binding.detailName.text = data.resolvedName
|
||||
binding.detailSubhead.bindGenreInfo(data)
|
||||
binding.detailInfo.text = data.totalDuration
|
||||
binding.detailName.textSafe = data.resolvedName
|
||||
binding.detailSubhead.textSafe =
|
||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size)
|
||||
binding.detailInfo.textSafe = data.totalDuration
|
||||
|
||||
binding.detailPlayButton.setOnClickListener { playbackModel.playGenre(data, false) }
|
||||
|
||||
|
@ -141,14 +143,16 @@ class GenreDetailAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
inner class GenreSongViewHolder(
|
||||
private val binding: ItemGenreSongBinding,
|
||||
/** The Shared ViewHolder for a [Song]. Instantiation should be done with [from]. */
|
||||
inner class GenreSongViewHolder
|
||||
constructor(
|
||||
private val binding: ItemSongBinding,
|
||||
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable {
|
||||
override fun onBind(data: Song) {
|
||||
binding.song = data
|
||||
|
||||
binding.songName.requestLayout()
|
||||
binding.songInfo.requestLayout()
|
||||
override fun onBind(data: Song) {
|
||||
binding.songAlbumCover.applyAlbumCover(data)
|
||||
binding.songName.textSafe = data.resolvedName
|
||||
binding.songInfo.textSafe = data.resolvedArtistName
|
||||
}
|
||||
|
||||
override fun setHighlighted(isHighlighted: Boolean) {
|
||||
|
|
|
@ -186,6 +186,8 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
|||
// --- RECYCLERVIEW EVENT MANAGEMENT ---
|
||||
|
||||
private fun onPreDraw() {
|
||||
// FIXME: Make the way we lay out views less of a hacky mess. Perhaps consider
|
||||
// overlaying views or turning this into a ViewGroup.
|
||||
updateScrollbarState()
|
||||
|
||||
thumbView.layoutDirection = layoutDirection
|
||||
|
|
|
@ -18,12 +18,7 @@
|
|||
package org.oxycblt.auxio.music
|
||||
|
||||
import android.text.format.DateUtils
|
||||
import android.widget.TextView
|
||||
import androidx.databinding.BindingAdapter
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.util.getPluralSafe
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logW
|
||||
|
||||
// --- EXTENSION FUNCTIONS ---
|
||||
|
||||
|
@ -47,53 +42,3 @@ fun Long.toDuration(isElapsed: Boolean): String {
|
|||
|
||||
return durationString
|
||||
}
|
||||
|
||||
// --- BINDING ADAPTERS ---
|
||||
|
||||
@BindingAdapter("songInfo")
|
||||
fun TextView.bindSongInfo(song: Song?) {
|
||||
if (song == null) {
|
||||
logW("Song was null, not applying info")
|
||||
return
|
||||
}
|
||||
|
||||
text = context.getString(R.string.fmt_two, song.resolvedArtistName, song.resolvedAlbumName)
|
||||
}
|
||||
|
||||
@BindingAdapter("albumInfo")
|
||||
fun TextView.bindAlbumInfo(album: Album?) {
|
||||
if (album == null) {
|
||||
logW("Album was null, not applying info")
|
||||
return
|
||||
}
|
||||
|
||||
text =
|
||||
context.getString(
|
||||
R.string.fmt_two,
|
||||
album.resolvedArtistName,
|
||||
context.getPluralSafe(R.plurals.fmt_song_count, album.songs.size))
|
||||
}
|
||||
|
||||
@BindingAdapter("artistInfo")
|
||||
fun TextView.bindArtistInfo(artist: Artist?) {
|
||||
if (artist == null) {
|
||||
logW("Artist was null, not applying info")
|
||||
return
|
||||
}
|
||||
|
||||
text =
|
||||
context.getString(
|
||||
R.string.fmt_two,
|
||||
context.getPluralSafe(R.plurals.fmt_album_count, artist.albums.size),
|
||||
context.getPluralSafe(R.plurals.fmt_song_count, artist.songs.size))
|
||||
}
|
||||
|
||||
@BindingAdapter("genreInfo")
|
||||
fun TextView.bindGenreInfo(genre: Genre?) {
|
||||
if (genre == null) {
|
||||
logW("Genre was null, not applying info")
|
||||
return
|
||||
}
|
||||
|
||||
text = context.getPluralSafe(R.plurals.fmt_song_count, genre.songs.size)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.view.ViewGroup
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ItemExcludedDirBinding
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* Adapter that shows the excluded directories and their "Clear" button.
|
||||
|
@ -56,8 +57,7 @@ class ExcludedEntryAdapter(private val onClear: (String) -> Unit) :
|
|||
}
|
||||
|
||||
fun bind(path: String) {
|
||||
binding.excludedPath.text = path
|
||||
binding.excludedPath.requestLayout()
|
||||
binding.excludedPath.textSafe = path
|
||||
binding.excludedClear.setOnClickListener { onClear(path) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ import androidx.core.view.updatePadding
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.music.bindSongInfo
|
||||
import org.oxycblt.auxio.ui.BottomSheetLayout
|
||||
import org.oxycblt.auxio.ui.ViewBindingFragment
|
||||
import org.oxycblt.auxio.util.getAttrColorSafe
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
@ -99,9 +99,10 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
|
|||
|
||||
playbackModel.song.observe(viewLifecycleOwner) { song ->
|
||||
if (song != null) {
|
||||
binding.playbackCover.bindAlbumCover(song)
|
||||
binding.playbackSong.text = song.resolvedName
|
||||
binding.playbackInfo.bindSongInfo(song)
|
||||
binding.playbackCover.applyAlbumCover(song)
|
||||
binding.playbackSong.textSafe = song.resolvedName
|
||||
binding.playbackInfo.textSafe =
|
||||
getString(R.string.fmt_two, song.resolvedArtistName, song.resolvedAlbumName)
|
||||
binding.playbackProgressBar.max = song.seconds.toInt()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import com.google.android.material.slider.Slider
|
|||
import kotlin.math.max
|
||||
import org.oxycblt.auxio.MainFragmentDirections
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.bindAlbumCover
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
|
@ -42,6 +42,7 @@ import org.oxycblt.auxio.util.getAttrColorSafe
|
|||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.stateList
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* A [Fragment] that displays more information about the song, along with more media controls.
|
||||
|
@ -166,7 +167,7 @@ class PlaybackPanelFragment :
|
|||
|
||||
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||
if (fromUser) {
|
||||
requireBinding().playbackPosition.text = value.toLong().toDuration(true)
|
||||
requireBinding().playbackPosition.textSafe = value.toLong().toDuration(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,14 +175,14 @@ class PlaybackPanelFragment :
|
|||
if (song == null) return
|
||||
|
||||
val binding = requireBinding()
|
||||
binding.playbackCover.bindAlbumCover(song)
|
||||
binding.playbackSong.text = song.resolvedName
|
||||
binding.playbackArtist.text = song.resolvedArtistName
|
||||
binding.playbackAlbum.text = song.resolvedAlbumName
|
||||
binding.playbackCover.applyAlbumCover(song)
|
||||
binding.playbackSong.textSafe = song.resolvedName
|
||||
binding.playbackArtist.textSafe = song.resolvedArtistName
|
||||
binding.playbackAlbum.textSafe = song.resolvedAlbumName
|
||||
|
||||
// Normally if a song had a duration
|
||||
val seconds = song.seconds
|
||||
binding.playbackDuration.text = seconds.toDuration(false)
|
||||
binding.playbackDuration.textSafe = seconds.toDuration(false)
|
||||
binding.playbackSeekBar.apply {
|
||||
valueTo = max(seconds, 1L).toFloat()
|
||||
isEnabled = seconds > 0L
|
||||
|
@ -199,7 +200,7 @@ class PlaybackPanelFragment :
|
|||
val binding = requireBinding()
|
||||
if (!binding.playbackPosition.isActivated) {
|
||||
binding.playbackSeekBar.value = position.toFloat()
|
||||
binding.playbackPosition.text = position.toDuration(true)
|
||||
binding.playbackPosition.textSafe = position.toDuration(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
|||
private val mMode = MutableLiveData(PlaybackMode.ALL_SONGS)
|
||||
|
||||
// Other
|
||||
// TODO: Move URI management to PlaybackService (more capable of taking commands)
|
||||
private var mIntentUri: Uri? = null
|
||||
|
||||
/** The current song. */
|
||||
|
|
|
@ -28,6 +28,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.databinding.ItemQueueSongBinding
|
||||
import org.oxycblt.auxio.music.ActionHeader
|
||||
import org.oxycblt.auxio.music.Header
|
||||
|
@ -41,6 +42,7 @@ import org.oxycblt.auxio.util.disableDropShadowCompat
|
|||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.logE
|
||||
import org.oxycblt.auxio.util.stateList
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* The single adapter for both the Next Queue and the User Queue.
|
||||
|
@ -125,7 +127,9 @@ class QueueAdapter(private val touchHelper: ItemTouchHelper) :
|
|||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onBind(data: Song) {
|
||||
binding.song = data
|
||||
binding.songAlbumCover.applyAlbumCover(data)
|
||||
binding.songName.textSafe = data.resolvedName
|
||||
binding.songInfo.textSafe = data.resolvedArtistName
|
||||
|
||||
binding.background.isInvisible = true
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.oxycblt.auxio.ui.ViewBindingFragment
|
|||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* A [BottomSheetDialogFragment] that shows Auxio's about screen.
|
||||
|
@ -54,13 +55,13 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
|
|||
|
||||
binding.aboutToolbar.setNavigationOnClickListener { findNavController().navigateUp() }
|
||||
|
||||
binding.aboutVersion.text = BuildConfig.VERSION_NAME
|
||||
binding.aboutVersion.textSafe = BuildConfig.VERSION_NAME
|
||||
binding.aboutCode.setOnClickListener { openLinkInBrowser(LINK_CODEBASE) }
|
||||
binding.aboutFaq.setOnClickListener { openLinkInBrowser(LINK_FAQ) }
|
||||
binding.aboutLicenses.setOnClickListener { openLinkInBrowser(LINK_LICENSES) }
|
||||
|
||||
homeModel.songs.observe(viewLifecycleOwner) { songs ->
|
||||
binding.aboutSongCount.text = getString(R.string.fmt_songs_loaded, songs.size)
|
||||
binding.aboutSongCount.textSafe = getString(R.string.fmt_songs_loaded, songs.size)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -249,11 +249,11 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
|
|||
barView = getChildAt(1) // Child 2 is assumed to be the bar used when collapsed
|
||||
panelView = getChildAt(2) // Child 3 is assumed to be the panel used when expanded
|
||||
|
||||
// We actually move the bar and panel views into a container so that they have consistent
|
||||
// behavior when be manipulate layouts later.
|
||||
removeView(barView)
|
||||
removeView(panelView)
|
||||
|
||||
// We actually move the bar and panel views into a container so that they have consistent
|
||||
// behavior when be manipulate layouts later.
|
||||
containerView.apply {
|
||||
addView(
|
||||
barView,
|
||||
|
|
|
@ -20,13 +20,15 @@ package org.oxycblt.auxio.ui
|
|||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.coil.applyAlbumCover
|
||||
import org.oxycblt.auxio.coil.applyArtistImage
|
||||
import org.oxycblt.auxio.coil.applyGenreImage
|
||||
import org.oxycblt.auxio.databinding.ItemActionHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
||||
import org.oxycblt.auxio.databinding.ItemHeaderBinding
|
||||
import org.oxycblt.auxio.databinding.ItemParentBinding
|
||||
import org.oxycblt.auxio.databinding.ItemSongBinding
|
||||
import org.oxycblt.auxio.music.ActionHeader
|
||||
import org.oxycblt.auxio.music.Album
|
||||
|
@ -35,7 +37,10 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.music.Header
|
||||
import org.oxycblt.auxio.music.Item
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.util.context
|
||||
import org.oxycblt.auxio.util.getPluralSafe
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
import org.oxycblt.auxio.util.textSafe
|
||||
|
||||
/**
|
||||
* A [RecyclerView.ViewHolder] that streamlines a lot of the common things across all viewholders.
|
||||
|
@ -46,7 +51,7 @@ import org.oxycblt.auxio.util.inflater
|
|||
* @author OxygenCobalt
|
||||
*/
|
||||
abstract class BaseViewHolder<T : Item>(
|
||||
private val binding: ViewDataBinding,
|
||||
private val binding: ViewBinding,
|
||||
private val doOnClick: ((data: T) -> Unit)? = null,
|
||||
private val doOnLongClick: ((view: View, data: T) -> Unit)? = null
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
@ -73,8 +78,6 @@ abstract class BaseViewHolder<T : Item>(
|
|||
}
|
||||
|
||||
onBind(data)
|
||||
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,10 +96,9 @@ private constructor(
|
|||
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick) {
|
||||
|
||||
override fun onBind(data: Song) {
|
||||
binding.song = data
|
||||
|
||||
binding.songName.requestLayout()
|
||||
binding.songInfo.requestLayout()
|
||||
binding.songAlbumCover.applyAlbumCover(data)
|
||||
binding.songName.textSafe = data.resolvedName
|
||||
binding.songInfo.textSafe = data.resolvedArtistName
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -115,14 +117,19 @@ private constructor(
|
|||
/** The Shared ViewHolder for a [Album]. Instantiation should be done with [from]. */
|
||||
class AlbumViewHolder
|
||||
private constructor(
|
||||
private val binding: ItemAlbumBinding,
|
||||
private val binding: ItemParentBinding,
|
||||
doOnClick: (data: Album) -> Unit,
|
||||
doOnLongClick: (view: View, data: Album) -> Unit
|
||||
) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick) {
|
||||
|
||||
override fun onBind(data: Album) {
|
||||
binding.album = data
|
||||
binding.albumName.requestLayout()
|
||||
binding.parentImage.applyAlbumCover(data)
|
||||
binding.parentName.textSafe = data.resolvedName
|
||||
binding.parentInfo.textSafe =
|
||||
binding.context.getString(
|
||||
R.string.fmt_two,
|
||||
data.resolvedArtistName,
|
||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -133,7 +140,7 @@ private constructor(
|
|||
doOnLongClick: (view: View, data: Album) -> Unit
|
||||
): AlbumViewHolder {
|
||||
return AlbumViewHolder(
|
||||
ItemAlbumBinding.inflate(context.inflater), doOnClick, doOnLongClick)
|
||||
ItemParentBinding.inflate(context.inflater), doOnClick, doOnLongClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,14 +148,19 @@ private constructor(
|
|||
/** The Shared ViewHolder for a [Artist]. Instantiation should be done with [from]. */
|
||||
class ArtistViewHolder
|
||||
private constructor(
|
||||
private val binding: ItemArtistBinding,
|
||||
private val binding: ItemParentBinding,
|
||||
doOnClick: (Artist) -> Unit,
|
||||
doOnLongClick: (view: View, data: Artist) -> Unit
|
||||
) : BaseViewHolder<Artist>(binding, doOnClick, doOnLongClick) {
|
||||
|
||||
override fun onBind(data: Artist) {
|
||||
binding.artist = data
|
||||
binding.artistName.requestLayout()
|
||||
binding.parentImage.applyArtistImage(data)
|
||||
binding.parentName.textSafe = data.resolvedName
|
||||
binding.parentInfo.textSafe =
|
||||
binding.context.getString(
|
||||
R.string.fmt_two,
|
||||
binding.context.getPluralSafe(R.plurals.fmt_album_count, data.albums.size),
|
||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -159,7 +171,7 @@ private constructor(
|
|||
doOnLongClick: (view: View, data: Artist) -> Unit
|
||||
): ArtistViewHolder {
|
||||
return ArtistViewHolder(
|
||||
ItemArtistBinding.inflate(context.inflater), doOnClick, doOnLongClick)
|
||||
ItemParentBinding.inflate(context.inflater), doOnClick, doOnLongClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,14 +179,16 @@ private constructor(
|
|||
/** The Shared ViewHolder for a [Genre]. Instantiation should be done with [from]. */
|
||||
class GenreViewHolder
|
||||
private constructor(
|
||||
private val binding: ItemGenreBinding,
|
||||
private val binding: ItemParentBinding,
|
||||
doOnClick: (Genre) -> Unit,
|
||||
doOnLongClick: (view: View, data: Genre) -> Unit
|
||||
) : BaseViewHolder<Genre>(binding, doOnClick, doOnLongClick) {
|
||||
|
||||
override fun onBind(data: Genre) {
|
||||
binding.genre = data
|
||||
binding.genreName.requestLayout()
|
||||
binding.parentImage.applyGenreImage(data)
|
||||
binding.parentName.textSafe = data.resolvedName
|
||||
binding.parentInfo.textSafe =
|
||||
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -185,7 +199,7 @@ private constructor(
|
|||
doOnLongClick: (view: View, data: Genre) -> Unit
|
||||
): GenreViewHolder {
|
||||
return GenreViewHolder(
|
||||
ItemGenreBinding.inflate(context.inflater), doOnClick, doOnLongClick)
|
||||
ItemParentBinding.inflate(context.inflater), doOnClick, doOnLongClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +209,7 @@ class HeaderViewHolder private constructor(private val binding: ItemHeaderBindin
|
|||
BaseViewHolder<Header>(binding) {
|
||||
|
||||
override fun onBind(data: Header) {
|
||||
binding.header = data
|
||||
binding.title.textSafe = binding.context.getString(data.string)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -211,13 +225,11 @@ class ActionHeaderViewHolder private constructor(private val binding: ItemAction
|
|||
BaseViewHolder<ActionHeader>(binding) {
|
||||
|
||||
override fun onBind(data: ActionHeader) {
|
||||
binding.header = data
|
||||
|
||||
binding.executePendingBindings()
|
||||
|
||||
binding.headerTitle.textSafe = binding.context.getString(data.string)
|
||||
binding.headerButton.apply {
|
||||
setImageResource(data.icon)
|
||||
contentDescription = context.getString(data.desc)
|
||||
TooltipCompat.setTooltipText(this, contentDescription)
|
||||
|
||||
setOnClickListener(data.onClick)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.oxycblt.auxio.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Insets
|
||||
import android.graphics.Rect
|
||||
|
@ -24,44 +25,14 @@ import android.graphics.drawable.Drawable
|
|||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import org.oxycblt.auxio.R
|
||||
|
||||
/** Converts this color to a single-color [ColorStateList]. */
|
||||
val @receiver:ColorRes Int.stateList
|
||||
get() = ColorStateList.valueOf(this)
|
||||
|
||||
/**
|
||||
* Apply the recommended spans for a [RecyclerView].
|
||||
*
|
||||
* @param shouldBeFullWidth Optional callback for determining whether an item should be full-width,
|
||||
* regardless of spans
|
||||
*/
|
||||
fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) {
|
||||
val spans = resources.getInteger(R.integer.recycler_spans)
|
||||
|
||||
if (spans > 1) {
|
||||
val mgr = GridLayoutManager(context, spans)
|
||||
|
||||
if (shouldBeFullWidth != null) {
|
||||
mgr.spanSizeLookup =
|
||||
object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (shouldBeFullWidth(position)) spans else 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layoutManager = mgr
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether a recyclerview can scroll. */
|
||||
fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height
|
||||
|
||||
/**
|
||||
* Disables drop shadows on a view programmatically in a version-compatible manner. This only works
|
||||
* on Android 9 and above. Below that version, shadows will remain visible.
|
||||
|
@ -113,9 +84,52 @@ private fun isUnderImpl(
|
|||
|
||||
val View.isRtl: Boolean
|
||||
get() = layoutDirection == View.LAYOUT_DIRECTION_RTL
|
||||
|
||||
val Drawable.isRtl: Boolean
|
||||
get() = DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL
|
||||
|
||||
val ViewBinding.context: Context
|
||||
get() = root.context
|
||||
|
||||
var TextView.textSafe
|
||||
get() = text
|
||||
set(value) {
|
||||
text = value
|
||||
requestLayout()
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the recommended spans for a [RecyclerView].
|
||||
*
|
||||
* @param shouldBeFullWidth Optional callback for determining whether an item should be full-width,
|
||||
* regardless of spans
|
||||
*/
|
||||
fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) {
|
||||
val spans = resources.getInteger(R.integer.recycler_spans)
|
||||
|
||||
if (spans > 1) {
|
||||
val mgr = GridLayoutManager(context, spans)
|
||||
|
||||
if (shouldBeFullWidth != null) {
|
||||
mgr.spanSizeLookup =
|
||||
object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (shouldBeFullWidth(position)) spans else 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layoutManager = mgr
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether a recyclerview can scroll. */
|
||||
fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height
|
||||
|
||||
/** Converts this color to a single-color [ColorStateList]. */
|
||||
val @receiver:ColorRes Int.stateList
|
||||
get() = ColorStateList.valueOf(this)
|
||||
|
||||
/**
|
||||
* Resolve system bar insets in a version-aware manner. This can be used to apply padding to a view
|
||||
* that properly follows all the frustrating changes that were made between 8-11.
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
@ -75,4 +71,3 @@
|
|||
app:layout_constraintStart_toEndOf="@+id/detail_play_button"
|
||||
app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -85,11 +82,11 @@
|
|||
android:id="@+id/playback_seek_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
app:haloRadius="@dimen/slider_halo_radius"
|
||||
app:labelBehavior="gone"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song_container"
|
||||
|
@ -101,8 +98,8 @@
|
|||
android:id="@+id/playback_position"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginTop="@dimen/spacing_small_inv"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -125,10 +122,10 @@
|
|||
android:id="@+id/playback_loop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_change_loop"
|
||||
android:src="@drawable/ic_loop"
|
||||
app:hasIndicator="true"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
|
||||
|
@ -149,12 +146,12 @@
|
|||
style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_play_pause"
|
||||
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"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
tools:src="@drawable/ic_play" />
|
||||
|
||||
<org.oxycblt.auxio.playback.PlaybackButton
|
||||
|
@ -172,14 +169,13 @@
|
|||
android:id="@+id/playback_shuffle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_shuffle"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
app:hasIndicator="true"
|
||||
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>
|
||||
</layout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
@ -88,4 +84,3 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -181,4 +178,3 @@
|
|||
app:tint="@color/sel_accented" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -168,6 +166,4 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
|
||||
app:tint="@color/sel_accented" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,13 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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">
|
||||
|
||||
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
|
@ -92,4 +89,3 @@
|
|||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackBarView">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
@ -96,4 +93,3 @@
|
|||
tools:progress="70" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,11 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
|
@ -86,4 +84,3 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,11 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -184,4 +181,3 @@
|
|||
app:tint="@color/sel_accented" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackBarView">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
@ -95,4 +92,3 @@
|
|||
tools:progress="70" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.fragment.app.FragmentContainerView 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"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -12,4 +9,3 @@
|
|||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_main"
|
||||
tools:layout="@layout/fragment_main" />
|
||||
</layout>
|
|
@ -1,9 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.recyclerview.widget.RecyclerView 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">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/accent_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -17,5 +15,3 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/accent_header"
|
||||
tools:itemCount="18"
|
||||
tools:listitem="@layout/item_accent" />
|
||||
|
||||
</layout>
|
|
@ -1,14 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout 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">
|
||||
|
||||
<LinearLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/spacing_small">
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/excluded_recycler"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -30,5 +29,4 @@
|
|||
android:textAppearance="@style/TextAppearance.Auxio.TitleMidLarge"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
</LinearLayout>
|
|
@ -1,9 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.recyclerview.widget.RecyclerView 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">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/tab_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -14,5 +12,3 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/accent_header"
|
||||
tools:itemCount="5"
|
||||
tools:listitem="@layout/item_tab" />
|
||||
|
||||
</layout>
|
|
@ -1,14 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout 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"
|
||||
tools:context=".settings.AboutFragment">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
tools:context=".settings.AboutFragment">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeAppBarLayout
|
||||
android:id="@+id/about_appbar"
|
||||
|
@ -158,11 +156,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:drawableStartCompat="@drawable/ic_album"
|
||||
app:drawableTint="?attr/colorControlNormal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_licenses"
|
||||
tools:text="Songs Loaded: 1616"
|
||||
app:drawableTint="?attr/colorControlNormal" />
|
||||
tools:text="Songs Loaded: 1616" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_author"
|
||||
|
@ -170,8 +168,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/lbl_author"
|
||||
app:drawableTint="?attr/colorControlNormal"
|
||||
app:drawableStartCompat="@drawable/ic_artist"
|
||||
app:drawableTint="?attr/colorControlNormal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_song_count" />
|
||||
|
@ -179,5 +177,4 @@
|
|||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
||||
</layout>
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.DetailFragment">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -34,5 +31,4 @@
|
|||
tools:listitem="@layout/item_detail" />
|
||||
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
||||
</FrameLayout>
|
||||
</layout>
|
||||
</FrameLayout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout 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"
|
||||
tools:context=".home.HomeFragment">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
|
||||
android:id="@+id/main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -59,4 +56,3 @@
|
|||
</org.oxycblt.auxio.home.EdgeFabContainer>
|
||||
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
||||
</layout>
|
|
@ -1,9 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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">
|
||||
|
||||
<org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView
|
||||
<org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/home_recycler"
|
||||
style="@style/Widget.Auxio.RecyclerView.WithAdaptiveFab"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -11,4 +10,3 @@
|
|||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||
tools:listitem="@layout/item_artist" />
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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:tools="http://schemas.android.com/tools"
|
||||
tools:context=".MainFragment">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
@ -63,5 +60,3 @@
|
|||
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
</layout>
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackBarView">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
@ -68,4 +65,3 @@
|
|||
tools:progress="70" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.PlaybackPanelFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/playback_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -170,4 +167,3 @@
|
|||
app:tint="@color/sel_accented" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout 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"
|
||||
tools:context=".playback.queue.QueueFragment">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
|
||||
android:id="@+id/queue_coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -36,4 +33,3 @@
|
|||
tools:listitem="@layout/item_queue_song" />
|
||||
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
||||
</layout>
|
|
@ -1,9 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout 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">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
@ -55,4 +53,3 @@
|
|||
tools:listitem="@layout/item_song" />
|
||||
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
||||
</layout>
|
|
@ -1,10 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
tools:context=".settings.SettingsFragment">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
|
||||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/settings_coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -33,4 +30,3 @@
|
|||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
|
||||
|
||||
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
|
||||
</layout>
|
|
@ -1,9 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".settings.pref.AccentAdapter.ViewHolder">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/spacing_small"
|
||||
|
@ -22,5 +19,4 @@
|
|||
tools:backgroundTint="?attr/colorPrimary"
|
||||
tools:ignore="ContentDescription, SpeakableTextPresentCheck" />
|
||||
|
||||
</FrameLayout>
|
||||
</layout>
|
||||
</FrameLayout>
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".ui.HeaderViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="header"
|
||||
type="org.oxycblt.auxio.music.ActionHeader" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
@ -20,7 +11,6 @@
|
|||
style="@style/Widget.Auxio.TextView.Header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{context.getString(header.string)}"
|
||||
app:layout_constraintBottom_toTopOf="@id/header_divider"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -31,16 +21,15 @@
|
|||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@{context.getString(header.desc)}"
|
||||
android:minWidth="@dimen/size_btn_small"
|
||||
android:minHeight="@dimen/size_btn_small"
|
||||
android:background="@drawable/ui_unbounded_ripple"
|
||||
android:paddingStart="@dimen/spacing_medium"
|
||||
android:paddingEnd="@dimen/spacing_medium"
|
||||
android:src="@{context.getDrawable(header.icon)}"
|
||||
app:layout_constraintBottom_toTopOf="@id/header_divider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/ic_sort" />
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
|
@ -50,4 +39,3 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,51 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
tools:context=".ui.AlbumViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="album"
|
||||
type="org.oxycblt.auxio.music.Album" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_album_cover(album.resolvedName)}"
|
||||
app:albumArt="@{album}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_album" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{album.rawName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/album_info"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Album Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_info"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:albumInfo="@{album}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/album_name"
|
||||
tools:text="Artist / 10 Songs" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,25 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".detail.recycler.AlbumDetailAdapter.AlbumSongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/song_track_placeholder"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/def_track"
|
||||
android:src="@drawable/ic_song"
|
||||
android:visibility="gone"
|
||||
android:visibility="invisible"
|
||||
app:tint="@color/sel_accented"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_track"
|
||||
app:layout_constraintEnd_toEndOf="@+id/song_track"
|
||||
|
@ -31,33 +24,30 @@
|
|||
android:id="@+id/song_track"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@{@string/desc_track_number(song.track)}"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:minWidth="@dimen/size_track_number"
|
||||
android:text="@{@string/fmt_track(song.track)}"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
android:textSize="@dimen/text_size_ext_title_mid_larger"
|
||||
android:textSize="@dimen/text_size_ext_title_mid_large"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_name"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="1" />
|
||||
tools:text="16" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{song.resolvedName}"
|
||||
android:textColor="@color/sel_accented_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/song_duration"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_track"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/song_track"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Song Name" />
|
||||
|
||||
|
@ -66,13 +56,11 @@
|
|||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{song.formattedDuration}"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_track"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_track"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
||||
tools:text="16:16" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,23 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".ui.ArtistViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="artist"
|
||||
type="org.oxycblt.auxio.music.Artist" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/artist_image"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_artist_image(artist.resolvedName)}"
|
||||
app:artistImage="@{artist}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -28,8 +18,7 @@
|
|||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{artist.resolvedName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/artist_details"
|
||||
app:layout_constraintBottom_toTopOf="@+id/artist_info"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/artist_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -37,11 +26,10 @@
|
|||
tools:text="Artist Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/artist_details"
|
||||
android:id="@+id/artist_info"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:artistInfo="@{artist}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/artist_image"
|
||||
|
@ -49,4 +37,3 @@
|
|||
tools:text="2 Albums, 20 Songs" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
tools:context=".detail.recycler.ArtistDetailAdapter.ArtistAlbumViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="album"
|
||||
type="org.oxycblt.auxio.music.Album" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_album_cover(album.resolvedName)}"
|
||||
app:albumArt="@{album}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_album" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{album.resolvedName}"
|
||||
android:textColor="@color/sel_accented_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/album_year"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Album Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_year"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{album.year != 0 ? String.valueOf(album.year) : @string/def_date}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/album_name"
|
||||
tools:text="2020" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,69 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
tools:context=".ui.SongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_album" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:text="@{song.resolvedName}"
|
||||
android:textColor="@color/sel_accented_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/song_info"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_duration"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Song Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_info"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:text="@{song.resolvedAlbumName}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_duration"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
||||
tools:text="Album" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_duration"
|
||||
style="@style/Widget.Auxio.TextView.Item.Tertiary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="none"
|
||||
android:gravity="end"
|
||||
android:text="@{song.formattedDuration}"
|
||||
android:textAlignment="viewEnd"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="16:16" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,11 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/spacing_medium">
|
||||
|
@ -75,4 +72,3 @@
|
|||
app:layout_constraintStart_toEndOf="@+id/detail_play_button"
|
||||
app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,14 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
style="@style/Widget.Auxio.ItemLayout"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/Widget.Auxio.ItemLayout"
|
||||
android:padding="0dp">
|
||||
|
||||
<TextView
|
||||
|
@ -42,4 +41,3 @@
|
|||
app:tint="?attr/colorControlNormal" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
tools:context=".ui.GenreViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="genre"
|
||||
type="org.oxycblt.auxio.music.Genre" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/genre_image"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
android:contentDescription="@{@string/desc_genre_image(genre.resolvedName)}"
|
||||
app:genreImage="@{genre}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_genre" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genre_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{genre.resolvedName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/genre_count"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/genre_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Genre Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genre_count"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:genreInfo="@{genre}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/genre_image"
|
||||
app:layout_constraintTop_toBottomOf="@+id/genre_name"
|
||||
tools:text="40 Songs" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,69 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
tools:context=".detail.recycler.GenreDetailAdapter.GenreSongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_album" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:text="@{song.resolvedName}"
|
||||
android:textColor="@color/sel_accented_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/song_info"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_duration"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Song Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_info"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
app:songInfo="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_duration"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
||||
tools:text="Artist / Album" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_duration"
|
||||
style="@style/Widget.Auxio.TextView.Item.Tertiary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="none"
|
||||
android:gravity="end"
|
||||
android:text="@{song.formattedDuration}"
|
||||
android:textAlignment="viewEnd"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="16:16" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,17 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".ui.HeaderViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="header"
|
||||
type="org.oxycblt.auxio.music.Header" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
@ -20,7 +10,6 @@
|
|||
style="@style/Widget.Auxio.TextView.Header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{context.getString(header.string)}"
|
||||
app:layout_constraintBottom_toTopOf="@id/header_divider"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -33,4 +22,3 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
38
app/src/main/res/layout/item_parent.xml
Normal file
38
app/src/main/res/layout/item_parent.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/parent_image"
|
||||
style="@style/Widget.Auxio.Image.Medium"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_artist" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/parent_name"
|
||||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/sel_accented_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/parent_info"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/parent_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Artist" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/parent_info"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/parent_image"
|
||||
app:layout_constraintTop_toBottomOf="@+id/parent_name"
|
||||
tools:text="Info" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,17 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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:tools="http://schemas.android.com/tools"
|
||||
tools:context=".playback.queue.QueueAdapter.QueueSongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
</data>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface">
|
||||
|
@ -39,11 +30,9 @@
|
|||
android:background="?attr/colorSurface">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
android:id="@+id/song_album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:layout_margin="@dimen/spacing_medium"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -55,10 +44,9 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
android:text="@{song.resolvedName}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/song_info"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_drag_handle"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_album_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Song Name" />
|
||||
|
@ -69,10 +57,9 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
app:songInfo="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/song_drag_handle"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
||||
tools:text="Artist / Album" />
|
||||
|
||||
|
@ -89,10 +76,9 @@
|
|||
android:paddingEnd="@dimen/spacing_medium"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_handle"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/album_cover"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_album_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/album_cover" />
|
||||
app:layout_constraintTop_toTopOf="@+id/song_album_cover" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
</layout>
|
|
@ -1,23 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".ui.SongViewHolder">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="song"
|
||||
type="org.oxycblt.auxio.music.Song" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/Widget.Auxio.ItemLayout">
|
||||
|
||||
<org.oxycblt.auxio.coil.RoundableImageView
|
||||
android:id="@+id/album_cover"
|
||||
android:id="@+id/song_album_cover"
|
||||
style="@style/Widget.Auxio.Image.Small"
|
||||
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
|
||||
app:albumArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
@ -28,25 +17,23 @@
|
|||
style="@style/Widget.Auxio.TextView.Item.Primary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{song.resolvedName}"
|
||||
android:textColor="@color/sel_accented_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/song_info"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_album_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Song Name" />
|
||||
tools:text="Song" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_info"
|
||||
style="@style/Widget.Auxio.TextView.Item.Secondary"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:songInfo="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_album_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/song_name"
|
||||
tools:text="Artist / Album" />
|
||||
tools:text="Info" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,12 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
style="@style/Widget.Auxio.ItemLayout"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/Widget.Auxio.ItemLayout"
|
||||
android:padding="0dp">
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
|
@ -47,4 +46,3 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/tab_icon" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,9 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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">
|
||||
|
||||
<merge
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:layout_height="wrap_content"
|
||||
tools:layout_width="match_parent"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
@ -50,4 +48,3 @@
|
|||
tools:text="16:16" />
|
||||
|
||||
</merge>
|
||||
</layout>
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
<dimen name="text_size_ext_label_larger">16sp</dimen>
|
||||
<dimen name="text_size_ext_title_mid_large">18sp</dimen>
|
||||
<dimen name="text_size_ext_title_mid_larger">20sp</dimen>
|
||||
|
||||
<!-- Misc -->
|
||||
<dimen name="elevation_small">2dp</dimen>
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
<!-- Format Namespace | Value formatting/plurals -->
|
||||
<string name="fmt_two" translatable="false">%1$s • %2$s</string>
|
||||
<string name="fmt_three" translatable="false">%1$s • %2$s • %3$s</string>
|
||||
<string name="fmt_track" translatable="false">%d</string>
|
||||
<string name="fmt_number" translatable="false">%d</string>
|
||||
</resources>
|
|
@ -44,16 +44,16 @@ should be added as a new `Fragment` implementation and added to one of the two n
|
|||
- `nav_main`: Navigation *from* `MainFragment`
|
||||
- `nav_explore`: Navigation *in* `MainFragment`
|
||||
|
||||
Fragments themselves are organized in order of lifecycle. So the first override would be `onCreate`, followed by
|
||||
`onCreateView`, and so on. `onCreateView` is where all view instantiation and configuration takes place, and
|
||||
is separated into three phases:
|
||||
Fragments themselves are based off a super class called `ViewBindingFragment` that takes a view-binding and then
|
||||
leverages it within the fragment lifecycle.
|
||||
|
||||
- Create variables [Bindings, Adapters, etc]
|
||||
- Set up the UI
|
||||
- Set up ViewModel instances and LiveData observers
|
||||
|
||||
`findViewById` is to **only** be used when interfacing with non-Auxio views. Otherwise, view-binding should be
|
||||
used in all cases. Avoid usages of databinding outside of the `onCreateView` step unless absolutely necessary.
|
||||
used in all cases. Code that involves retrieving the binding should be isolated into its own function, with
|
||||
the binding being obtained by calling `requireBinding`.
|
||||
|
||||
At times it may be more appropriate to use a `View` instead of a full blown fragment. This is okay as long as
|
||||
view-binding is still used.
|
||||
|
@ -62,11 +62,6 @@ When creating a ViewHolder for a `RecyclerView`, one should use `BaseViewHolder`
|
|||
and automate some code shared across all ViewHolders. The only exceptions to this case are for ViewHolders that
|
||||
correspond to non-`BaseModel` data, in which a normal ViewHolder can be used instead.
|
||||
|
||||
Data is often bound using Binding Adapters, which are XML attributes assigned in layout files that can automatically
|
||||
display data, usually written as `app:bindingAdapterName="@{data}"`. Its recommended to use these instead of applying
|
||||
the attributes directly unless absolutely necessary. Usually it's okay to apply data programmatically if you begin
|
||||
to duplicate layouts simply because they apply to different data objects, such as the detail UIs.
|
||||
|
||||
#### Object communication
|
||||
Auxio's codebase is mostly centered around 4 different types of code that communicates with each-other.
|
||||
|
||||
|
|
Loading…
Reference in a new issue