Skip to content

Commit

Permalink
Fixed scroll issue in ListPref and MultiSelectListPref (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamalMulla committed Jan 22, 2022
1 parent 2bb475e commit b897ac8
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 79 deletions.
12 changes: 6 additions & 6 deletions ComposePrefs/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
defaultConfig {
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0.1"
versionCode 2
versionName "1.0.2"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
Expand All @@ -35,13 +35,13 @@ android {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion "1.1.0-rc01"
kotlinCompilerExtensionVersion "1.2.0-alpha01"
}
}

dependencies {
implementation "androidx.compose.ui:ui:1.1.0-rc01"
implementation "androidx.compose.material:material:1.1.0-rc01"
implementation "androidx.compose.ui:ui:1.2.0-alpha01"
implementation "androidx.compose.material:material:1.2.0-alpha01"
implementation "androidx.datastore:datastore-preferences:1.0.0"
}

Expand All @@ -54,7 +54,7 @@ afterEvaluate {

groupId = 'com.github.jamalmulla'
artifactId = 'ComposePrefs'
version = '1.0.1'
version = '1.0.2'
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.jamal.composeprefs.ui.prefs

import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.selectable
import androidx.compose.material.*
import androidx.compose.runtime.*
Expand All @@ -12,6 +14,7 @@ import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
Expand Down Expand Up @@ -49,26 +52,27 @@ fun ListPref(
contentColor: Color = contentColorFor(dialogBackgroundColor),
textColor: Color = MaterialTheme.colors.onBackground,
enabled: Boolean = true,
entries: Map<String, String> = mapOf()
entries: Map<String, String> = mapOf(), //TODO: Change to List?
) {

val entryList = entries.toList()
var showDialog by rememberSaveable { mutableStateOf(false) }
val selectionKey = stringPreferencesKey(key)
val scope = rememberCoroutineScope()

// need to observe state with some sort of flow maybe? this also works
val datastore = LocalPrefsDataStore.current
val prefs by remember { datastore.data }.collectAsState(initial = null)

var selected = defaultValue
prefs?.get(selectionKey)?.also { selected = it } // starting value if it exists in datastore

fun edit(current: Map.Entry<String, String>) = run {
fun edit(current: Pair<String, String>) = run {
scope.launch {
try {
datastore.edit { preferences ->
preferences[selectionKey] = current.key
preferences[selectionKey] = current.first
}
onValueChange?.invoke(current.key)
onValueChange?.invoke(current.first)
showDialog = false
} catch (e: Exception) {
Log.e("ListPref", "Could not write pref $key to database. ${e.printStackTrace()}")
Expand All @@ -92,33 +96,36 @@ fun ListPref(
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text(text = title) },
text = {
Column {
entries.forEach { current ->
val isSelected = selected == current.key
val onSelected = {
edit(current)
}
Row(
modifier = Modifier
.fillMaxWidth()
.selectable(
Column() {
Text(modifier = Modifier.padding(vertical = 16.dp), text = title)
LazyColumn {
items(entryList) { current ->

val isSelected = selected == current.first
val onSelected = {
edit(current)
}
Row(
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = isSelected,
onClick = { if (!isSelected) onSelected() }
),
verticalAlignment = CenterVertically,
) {
RadioButton(
selected = isSelected,
onClick = { if (!isSelected) onSelected() }
),
verticalAlignment = CenterVertically,
) {
RadioButton(
selected = isSelected,
onClick = { if (!isSelected) onSelected() },
colors = RadioButtonDefaults.colors(selectedColor = MaterialTheme.colors.primary)
)
Text(
text = current.value,
style = MaterialTheme.typography.body2,
color = textColor
)
onClick = { if (!isSelected) onSelected() },
colors = RadioButtonDefaults.colors(selectedColor = MaterialTheme.colors.primary)
)
Text(
text = current.second,
style = MaterialTheme.typography.body2,
color = textColor
)
}
}
}
}
Expand All @@ -138,6 +145,4 @@ fun ListPref(
),
)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.selectable
import androidx.compose.material.*
import androidx.compose.runtime.*
Expand All @@ -12,6 +15,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringSetPreferencesKey
Expand Down Expand Up @@ -46,8 +50,10 @@ fun MultiSelectListPref(
dialogBackgroundColor: Color = MaterialTheme.colors.surface,
textColor: Color = MaterialTheme.colors.onBackground,
enabled: Boolean = true,
entries: Map<String, String> = mapOf()
entries: Map<String, String> = mapOf() //TODO: Change to List?
) {

val entryList = entries.toList()
var showDialog by rememberSaveable { mutableStateOf(false) }
val selectionKey = stringSetPreferencesKey(key)
val scope = rememberCoroutineScope()
Expand All @@ -58,13 +64,12 @@ fun MultiSelectListPref(
var selected = defaultValue
prefs?.get(selectionKey)?.also { selected = it } // starting value if it exists in datastore

fun edit(isSelected: Boolean, current: Map.Entry<String, String>) = run {
fun edit(isSelected: Boolean, current: Pair<String, String>) = run {
scope.launch {
try {
//todo improve by handling errors
val result = when (!isSelected) {
true -> selected + current.key
false -> selected - current.key
true -> selected + current.first
false -> selected - current.first
}
datastore.edit { preferences ->
preferences[selectionKey] = result
Expand Down Expand Up @@ -92,36 +97,37 @@ fun MultiSelectListPref(
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text(text = title) },
text = {
Column {
entries.forEach { current ->
val isSelected = selected.contains(current.key)
val onSelectionChanged = {
edit(isSelected, current)
}
Row(
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = isSelected,
onClick = { onSelectionChanged() }
),
verticalAlignment = Alignment.CenterVertically,
) {
Checkbox(
checked = isSelected,
onCheckedChange = { onSelectionChanged() },
colors = CheckboxDefaults.colors(checkedColor = MaterialTheme.colors.primary)
)
Text(
text = current.value,
style = MaterialTheme.typography.body2,
color = textColor
)
Text(modifier = Modifier.padding(vertical = 16.dp), text = title)
LazyColumn {
items(entryList) { current ->
val isSelected = selected.contains(current.first)
val onSelectionChanged = {
edit(isSelected, current)
}
Row(
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = isSelected,
onClick = { onSelectionChanged() }
),
verticalAlignment = Alignment.CenterVertically,
) {
Checkbox(
checked = isSelected,
onCheckedChange = { onSelectionChanged() },
colors = CheckboxDefaults.colors(checkedColor = MaterialTheme.colors.primary)
)
Text(
text = current.second,
style = MaterialTheme.typography.body2,
color = textColor
)
}
}
}

}
},
confirmButton = {
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,7 @@ MultiSelectListPref(

And that's it! You can create your whole preference screen in this way, and you can modify the
individual parameters of each preference composable to achieve the functionality you require. If
something is missing, please create an Issue so we can discuss possible solutions. After all, this
is still version 1.0.0 and there are bound to be bugs and missing features.
something is missing, please create an Issue so we can discuss possible solutions.

# Download

Expand All @@ -218,7 +217,7 @@ maven { url "https://jitpack.io" }
and in your module `build.gradle` file add the dependencies

``` groovy
implementation "com.github.JamalMulla:ComposePrefs:<version>" // Current is 1.0.1
implementation "com.github.JamalMulla:ComposePrefs:<version>" // Current is 1.0.2
implementation "androidx.datastore:datastore-preferences:1.0.0"
```

Expand Down
46 changes: 44 additions & 2 deletions app/src/main/java/com/jamal/composeprefssample/SettingsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,20 @@ fun SettingsScreen() {
"1" to "Entry 2",
"2" to "Entry 3",
"3" to "Entry 4",
"4" to "Entry 5"
"4" to "Entry 5",
"5" to "Entry 6",
"6" to "Entry 7",
"7" to "Entry 8",
"8" to "Entry 9",
"9" to "Entry 10",
"10" to "Entry 11",
"11" to "Entry 12",
"12" to "Entry 13",
"13" to "Entry 14",
"14" to "Entry 15",
"15" to "Entry 16",
"16" to "Entry 17",
"17" to "Entry 18"
)
)
}
Expand Down Expand Up @@ -222,7 +235,36 @@ fun SettingsScreen() {
"1" to "Entry 2",
"2" to "Entry 3",
"3" to "Entry 4",
"4" to "Entry 5"
"4" to "Entry 5",
"5" to "Entry 6"
)
)
}

prefsItem {
MultiSelectListPref(
key = "msl2",
title = "MultiSelectListPref",
summary = "Pick multiple entries at once from a long list",
entries = mapOf(
"0" to "Entry 1",
"1" to "Entry 2",
"2" to "Entry 3",
"3" to "Entry 4",
"4" to "Entry 5",
"5" to "Entry 6",
"6" to "Entry 7",
"7" to "Entry 8",
"8" to "Entry 9",
"9" to "Entry 10",
"10" to "Entry 11",
"11" to "Entry 12",
"12" to "Entry 13",
"13" to "Entry 14",
"14" to "Entry 15",
"15" to "Entry 16",
"16" to "Entry 17",
"17" to "Entry 18"
)
)
}
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
compose_version = '1.1.0-rc01'
compose_version = '1.2.0-alpha01'
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.4"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down

0 comments on commit b897ac8

Please sign in to comment.