Make number of grid columns adjustable
This commit is contained in:
parent
dded695b81
commit
185e54bab2
@ -10,24 +10,32 @@
|
||||
app:title="@string/preference_theme" />
|
||||
|
||||
<ListPreference
|
||||
app:key="card_background"
|
||||
android:defaultValue="0"
|
||||
app:summary="%s"
|
||||
app:title="@string/preference_screen_colors"
|
||||
app:entries="@array/preference_card_background_entries"
|
||||
app:entryValues="@array/preference_card_background_values"
|
||||
/>
|
||||
app:key="card_background"
|
||||
app:summary="%s"
|
||||
app:title="@string/preference_screen_colors" />
|
||||
<Preference
|
||||
app:key="cards"
|
||||
app:summary="@string/preference_cards_summary"
|
||||
app:title="@string/preference_cards" />
|
||||
|
||||
<PreferenceCategory app:title="@string/preference_category_grid">
|
||||
<SeekBarPreference
|
||||
app:key="grid_column_count"
|
||||
app:title="@string/preference_grid_column_count"
|
||||
app:min="3"
|
||||
android:max="8"
|
||||
app:defaultValue="@integer/config_columnCount"
|
||||
app:showSeekBarValue="true" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory app:title="@string/preference_category_icons">
|
||||
<SwitchPreference
|
||||
app:key="themed_icons"
|
||||
android:defaultValue="false"
|
||||
app:title="@string/preference_themed_icons"
|
||||
app:key="themed_icons"
|
||||
app:summary="@string/preference_themed_icons_summary"
|
||||
/>
|
||||
app:title="@string/preference_themed_icons" />
|
||||
<ListPreference
|
||||
app:key="icon_pack"
|
||||
app:persistent="false"
|
||||
|
||||
@ -416,4 +416,7 @@
|
||||
<string name="preference_themed_icons">Eingefärbte Symbole</string>
|
||||
<string name="preference_themed_icons_summary">Symbole an das Farbschema der App anpassen</string>
|
||||
<string name="weather_no_data">Keine Wetterdaten verfügbar.</string>
|
||||
|
||||
<string name="preference_category_grid">Raster</string>
|
||||
<string name="preference_grid_column_count">Spaltenanzahl</string>
|
||||
</resources>
|
||||
@ -454,4 +454,7 @@
|
||||
<string name="feature_not_available">This feature is not available in this version of %1$s</string>
|
||||
<string name="preference_category_clock_widget">Clock</string>
|
||||
<string name="preference_clock_widget_style">Clock style</string>
|
||||
|
||||
<string name="preference_category_grid">Grid</string>
|
||||
<string name="preference_grid_column_count">Number of columns</string>
|
||||
</resources>
|
||||
|
||||
@ -66,6 +66,7 @@ dependencies {
|
||||
|
||||
implementation(project(":ktx"))
|
||||
implementation(project(":i18n"))
|
||||
implementation(project(":base"))
|
||||
implementation(project(":crashreporter"))
|
||||
|
||||
}
|
||||
@ -106,6 +106,8 @@ class LauncherPreferences(val context: Application, version: Int = 3) {
|
||||
|
||||
var easterEggEnabled by BooleanPreference("easter_egg", default = false)
|
||||
|
||||
var gridColumnCount by IntPreference("grid_column_count", default = context.resources.getInteger(R.integer.config_columnCount))
|
||||
|
||||
|
||||
fun doOnPreferenceChange(vararg keys: String, action: (String) -> Unit) {
|
||||
preferences.registerOnSharedPreferenceChangeListener { _, key ->
|
||||
|
||||
@ -332,8 +332,6 @@ class LauncherActivity : AppCompatActivity() {
|
||||
).apply {
|
||||
setMargins((8 * dp).toInt())
|
||||
}
|
||||
hiddenItemsGrid.columnCount =
|
||||
resources.getInteger(R.integer.config_columnCount)
|
||||
val hiddenItems = favoritesViewModel.hiddenItems
|
||||
hiddenItems.observe(this) {
|
||||
hiddenItemsGrid.submitItems(it)
|
||||
|
||||
@ -9,6 +9,7 @@ import android.widget.FrameLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.*
|
||||
import de.mm20.launcher2.favorites.FavoritesViewModel
|
||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.databinding.ViewFavoritesBinding
|
||||
@ -27,7 +28,7 @@ class FavoritesView : FrameLayout {
|
||||
|
||||
init {
|
||||
val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
favorites = viewModel.getFavorites(context.resources.getInteger(R.integer.config_columnCount))
|
||||
favorites = viewModel.getFavorites(LauncherPreferences.instance.gridColumnCount)
|
||||
favorites.observe(context as AppCompatActivity, Observer {
|
||||
visibility = if (it?.isEmpty() == true) View.GONE else View.VISIBLE
|
||||
binding.favoritesGrid.submitItems(it)
|
||||
|
||||
@ -12,6 +12,7 @@ import de.mm20.launcher2.ktx.ceilToInt
|
||||
import de.mm20.launcher2.ktx.lifecycleScope
|
||||
import de.mm20.launcher2.legacy.helper.ActivityStarter
|
||||
import de.mm20.launcher2.legacy.helper.ActivityStarterCallback
|
||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
@ -40,21 +41,22 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
|
||||
|
||||
@ObsoleteCoroutinesApi
|
||||
private val updateActor = lifecycleScope
|
||||
.actor<List<Searchable>>(Dispatchers.Main, capacity = Channel.CONFLATED) {
|
||||
for (newItems in channel) {
|
||||
val oldItems = currentItems
|
||||
val diffResult = withContext(Dispatchers.Default) {
|
||||
SearchDiffUtil.calculateDiff(oldItems, newItems)
|
||||
}
|
||||
currentItems = newItems
|
||||
applyDiff(diffResult)
|
||||
.actor<List<Searchable>>(Dispatchers.Main, capacity = Channel.CONFLATED) {
|
||||
for (newItems in channel) {
|
||||
val oldItems = currentItems
|
||||
val diffResult = withContext(Dispatchers.Default) {
|
||||
SearchDiffUtil.calculateDiff(oldItems, newItems)
|
||||
}
|
||||
currentItems = newItems
|
||||
applyDiff(diffResult)
|
||||
}
|
||||
}
|
||||
|
||||
@ObsoleteCoroutinesApi
|
||||
fun submitItems(items: List<Searchable>?) {
|
||||
if (items == null) return
|
||||
if (items.getOrNull(expandedItem)?.key != currentItems.getOrNull(expandedItem)?.key) expandedItem = -1
|
||||
if (items.getOrNull(expandedItem)?.key != currentItems.getOrNull(expandedItem)?.key) expandedItem =
|
||||
-1
|
||||
lifecycleScope.launch {
|
||||
updateActor.send(items)
|
||||
}
|
||||
@ -79,10 +81,14 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) {
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleRes
|
||||
) {
|
||||
attrs?.let {
|
||||
val ta = context.theme.obtainStyledAttributes(it, R.styleable.SearchGridView, 0, defStyleRes)
|
||||
columnCount = ta.getInt(R.styleable.SearchGridView_columnCount, 1)
|
||||
val ta =
|
||||
context.theme.obtainStyledAttributes(it, R.styleable.SearchGridView, 0, defStyleRes)
|
||||
rowHeight = ta.getDimensionPixelSize(R.styleable.SearchGridView_rowHeight, -1)
|
||||
ta.recycle()
|
||||
}
|
||||
@ -93,11 +99,16 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
|
||||
ActivityStarter.registerCallback(this)
|
||||
}
|
||||
|
||||
init {
|
||||
columnCount = LauncherPreferences.instance.gridColumnCount.takeIf { it > 1 }
|
||||
?: context.resources.getInteger(R.integer.config_columnCount)
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
val widthSpec = MeasureSpec.makeMeasureSpec(
|
||||
(MeasureSpec.getSize(widthMeasureSpec) - paddingLeft - paddingRight) / columnCount,
|
||||
MeasureSpec.EXACTLY
|
||||
(MeasureSpec.getSize(widthMeasureSpec) - paddingLeft - paddingRight) / columnCount,
|
||||
MeasureSpec.EXACTLY
|
||||
)
|
||||
val heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
|
||||
|
||||
@ -118,7 +129,10 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
|
||||
|
||||
val width = when (MeasureSpec.getMode(widthMeasureSpec)) {
|
||||
MeasureSpec.EXACTLY -> MeasureSpec.getSize(widthMeasureSpec)
|
||||
MeasureSpec.AT_MOST -> min(colWidth * columnCount + paddingLeft + paddingRight, MeasureSpec.getSize(widthMeasureSpec))
|
||||
MeasureSpec.AT_MOST -> min(
|
||||
colWidth * columnCount + paddingLeft + paddingRight,
|
||||
MeasureSpec.getSize(widthMeasureSpec)
|
||||
)
|
||||
MeasureSpec.UNSPECIFIED -> colWidth * columnCount + paddingLeft + paddingRight
|
||||
else -> colWidth * columnCount
|
||||
}
|
||||
@ -127,13 +141,16 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
|
||||
val visibleChildCount = children.count { it.visibility != View.GONE }
|
||||
val rowCount = (visibleChildCount / columnCount.toFloat()).ceilToInt()
|
||||
var height = rowHeight * rowCount + (getChildAt(expandedItem)?.measuredHeight
|
||||
?: 0) + paddingTop + paddingBottom
|
||||
?: 0) + paddingTop + paddingBottom
|
||||
|
||||
if (expandedItem == childCount - 1 && (childCount % columnCount == 1) || expandedItem != -1 && columnCount == 1) {
|
||||
height -= rowHeight
|
||||
}
|
||||
|
||||
setMeasuredDimension(View.resolveSize(width, widthMeasureSpec), View.resolveSize(height, heightMeasureSpec))
|
||||
setMeasuredDimension(
|
||||
View.resolveSize(width, widthMeasureSpec),
|
||||
View.resolveSize(height, heightMeasureSpec)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||
@ -190,7 +207,8 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
|
||||
postponedDiffs.push(diff)
|
||||
return
|
||||
}
|
||||
val representation = if (columnCount == 1) SearchableView.REPRESENTATION_LIST else SearchableView.REPRESENTATION_GRID
|
||||
val representation =
|
||||
if (columnCount == 1) SearchableView.REPRESENTATION_LIST else SearchableView.REPRESENTATION_GRID
|
||||
while (diff.isNotEmpty()) {
|
||||
val action = diff.poll() ?: continue
|
||||
if (action.action == DiffAction.ACTION_INSERT) {
|
||||
@ -241,7 +259,10 @@ class QueueUpdateCallback : ListUpdateCallback {
|
||||
|
||||
override fun onRemoved(position: Int, count: Int) {
|
||||
for (i in 1..count) {
|
||||
operations += DiffAction(action = DiffAction.ACTION_DELETE, position = position + (count - i))
|
||||
operations += DiffAction(
|
||||
action = DiffAction.ACTION_DELETE,
|
||||
position = position + (count - i)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,5 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
app:columnCount="@integer/config_columnCount"/>
|
||||
android:clipToPadding="false"/>
|
||||
</de.mm20.launcher2.ui.legacy.view.LauncherCardView>
|
||||
@ -16,6 +16,5 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:padding="8dp"
|
||||
app:columnCount="@integer/config_columnCount" />
|
||||
android:padding="8dp" />
|
||||
</de.mm20.launcher2.ui.legacy.view.LauncherCardView>
|
||||
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="SearchGridView">
|
||||
<attr name="columnCount" format="integer" />
|
||||
<attr name="rowHeight" format="dimension" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user