界面: 歌曲列表行高自适应铺满屏幕(消除投影/高分屏底部空白)
- SongListAdapter: 新增 rowHeightPx/fitRowHeight/rowsPerPage, 分页列表(2列目录5行/排行6行) 按 ListView 实际可视高度均分行高(clamp 52-160dp), 内容垂直居中, 背景整行铺满 - 滚动型列表(已点/下载/已唱)保持自然行高 - MainActivity.renderSongList: 布局完成后 post fitRowHeight
This commit is contained in:
@@ -9091,6 +9091,13 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
val pageOffset = if (mode == "rank") browsePage * browsePageSize() else 0
|
||||
val existing = modernSongAdapter?.takeIf { it.matches(mode, pageOffset) && list.adapter === it }
|
||||
// 分页网格/排行列表: 行高自适应铺满屏幕(2列目录每页5行, 排行单列每页6行);
|
||||
// 可滚动的队列/下载/已唱列表保持自然行高(rowsPerPage=0)。
|
||||
val rowsPerPage = when (mode) {
|
||||
"catalog" -> 5
|
||||
"rank" -> 6
|
||||
else -> 0
|
||||
}
|
||||
val listAdapter = existing ?: SongListAdapter(
|
||||
this,
|
||||
visibleSongs,
|
||||
@@ -9109,11 +9116,17 @@ class MainActivity : AppCompatActivity() {
|
||||
},
|
||||
onPauseResume = { song -> toggleDownloadPause(song) },
|
||||
),
|
||||
initialRowHeightPx = 0,
|
||||
rowsPerPage = rowsPerPage,
|
||||
).also {
|
||||
modernSongAdapter = it
|
||||
list.adapter = it
|
||||
}
|
||||
if (existing != null) listAdapter.notifyDataSetChanged()
|
||||
// 布局完成后按实际可视高度拉满各行, 消除投影/高分屏底部空白。
|
||||
if (rowsPerPage > 0) {
|
||||
list.post { if (list.adapter === listAdapter) listAdapter.fitRowHeight(list.height) }
|
||||
}
|
||||
|
||||
val targetPosition = focusedMarker?.let(listAdapter::adapterPositionFor)
|
||||
?: oldSelectedPosition.takeIf { it >= 0 }
|
||||
|
||||
@@ -42,11 +42,32 @@ class SongListAdapter(
|
||||
private val nextPageFocusId: Int,
|
||||
private val stateFor: (Song) -> SongRowState,
|
||||
private val callbacks: SongListCallbacks,
|
||||
private val initialRowHeightPx: Int = 0,
|
||||
private val rowsPerPage: Int = 0,
|
||||
) : BaseAdapter() {
|
||||
private val density = context.resources.displayMetrics.density
|
||||
private val columns = if (mode in SINGLE_COLUMN_MODES) 1 else 2
|
||||
private val cardIds = HashMap<String, Int>()
|
||||
|
||||
/** 当前行高(px)。0 = 保持内容自然高度(滚动列表用)。 */
|
||||
var rowHeightPx: Int = initialRowHeightPx
|
||||
private set
|
||||
|
||||
/**
|
||||
* 让行高铺满可用高度: 把列表可视高度按每页行数均分(分页列表专用)。
|
||||
* 超出 min/max 范围时收敛, 避免过小/过大。滚动列表(rowsPerPage<=0)忽略。
|
||||
*/
|
||||
fun fitRowHeight(availableHeightPx: Int) {
|
||||
if (rowsPerPage <= 0 || availableHeightPx <= 0) return
|
||||
val minPx = dp(52)
|
||||
val maxPx = dp(160)
|
||||
val fitted = (availableHeightPx / rowsPerPage).coerceIn(minPx, maxPx)
|
||||
if (fitted != rowHeightPx) {
|
||||
rowHeightPx = fitted
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private fun cardId(index: Int): Int = cardIds.getOrPut(songKey(songs[index])) { View.generateViewId() }
|
||||
|
||||
override fun getCount(): Int = ceil(songs.size / columns.toDouble()).toInt()
|
||||
@@ -64,27 +85,34 @@ class SongListAdapter(
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
if (columns == 1) {
|
||||
return createSingleRow(songs[position], position).apply {
|
||||
val view = if (columns == 1) {
|
||||
createSingleRow(songs[position], position).apply {
|
||||
if (position == count - 1) nextFocusDownId = previousPageFocusId
|
||||
}
|
||||
}
|
||||
return LinearLayout(context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
val cells = mutableListOf<View>()
|
||||
repeat(2) { column ->
|
||||
val index = position * 2 + column
|
||||
val cell = songs.getOrNull(index)?.let {
|
||||
createCatalogCell(it, index, column, position == count - 1)
|
||||
} ?: View(context)
|
||||
cells += cell
|
||||
addView(
|
||||
cell,
|
||||
LinearLayout.LayoutParams(0, dp(60), 1f),
|
||||
)
|
||||
} else {
|
||||
LinearLayout(context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
repeat(2) { column ->
|
||||
val index = position * 2 + column
|
||||
val cell = songs.getOrNull(index)?.let {
|
||||
createCatalogCell(it, index, column, position == count - 1)
|
||||
} ?: View(context)
|
||||
addView(
|
||||
cell,
|
||||
LinearLayout.LayoutParams(0, -1, 1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 分页列表: 让整行背景铺满均分行高; 滚动列表保持自然高度。
|
||||
if (rowHeightPx > 0) {
|
||||
view.layoutParams = android.widget.AbsListView.LayoutParams(
|
||||
android.widget.AbsListView.LayoutParams.MATCH_PARENT,
|
||||
rowHeightPx,
|
||||
)
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
private fun createSingleRow(song: Song, index: Int): View = when (mode) {
|
||||
|
||||
Reference in New Issue
Block a user