Is there a modifier that can affect the way a `Col...
# compose
m
Is there a modifier that can affect the way a
Column
lays out its items such that a predefined composable (
TextSelectionSeparator
) is inserted in between each one. Or perhaps modifying the
ColumnScope
somehow?
Copy code
SelectionContainer {
    Column {
        Text("111")
        TextSelectionSeparator()
        Text("222")
        TextSelectionSeparator()
        Text("333")
    }
}
For use case see: https://issuetracker.google.com/issues/285036739
m
To me, that does not sound like a job for a modifier
k
I’ve asked a similar question here, but unfortunately, I haven’t found a satisfying solution to this problem. If it’s only about texts, then I would recommend putting them into a list, iterating over them, and inserting a separator if
index != last index
s
Yeah I would definitely not expect a modifier to do this. Also found it simpler to add the item first before the real item only when the index isn't 0. It makes the code a bit easier to read, by a small margin 😅
g
> If it’s only about texts, then I would recommend putting them into a list You can do that with pretty much anything:
Copy code
val composables = buildList<@Composable () -> Unit> {
	if (whatever) {
		add(
		    {
		    	Text("Whatever")
		    }
		)
	}
	// ...
}

for (composable in composables) {
    // composable()
}
You can make it fancier and create a DSL similar to that of LazyList (which, not surprisingly, does something that resembles this)
m
Yes, I also wouldn’t expect the modifier to provide a solution here, but since I think the only possible candidates are
Modifier
and
ColumnScope
I thought it worth asking.
Just for fun:
Copy code
class SelectableColumnScope(columnScope: ColumnScope): ColumnScope by columnScope {
    internal val items = mutableListOf<@Composable ColumnScope.() -> Unit>()

    fun item(content: ColumnScope.() -> Unit) {
        items.add(content)
    }
}

@Composable
private fun TextSelectionSeparator(text: String = "\n") {
    Text(
        modifier = Modifier.sizeIn(maxWidth = 0.dp, maxHeight = 0.dp),
        text = text
    )
}

@Composable
fun SelectableColumn(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: SelectableColumnScope.() -> Unit, // intentionally don't make composable
) {
    SelectionContainer {
        Column(
            modifier = modifier,
            verticalArrangement = verticalArrangement,
            horizontalAlignment = horizontalAlignment,
        ) {
            SelectableColumnScope(this).apply {
                content()
                items.forEachIndexed { index, item ->
                    if (index > 0) {
                        TextSelectionSeparator()
                    }
                    item()
                }
            }
        }
    }
}

@Preview
@Composable
fun ExampleColumnPreview(modifier: Modifier = Modifier) {
    SelectableColumn {
        item {
            Text("111")
        }
        item {
            Text("222")
        }
        item {
            Text("333")
        }
    }
}
h
let me come in with a horrible hack around. 1. Add a string annotation to your text composables. Preferrably either spanning the entire text or just at the end. 2. Intercept
LocalClipboardManager
and provide your own. Keep a reference to the existing one since you are going to delegate to it. 3. When
ClipboardManager.setText
is called, find your annotations. Place the
\n
where required. Then route the request to the original Clipboard 4. ... 5. Profit?
awkward monkey 1
m
@Halil Ozercan doesn’t that only get called with the user selects Copy? What if (android) they used the overflow menu to jump straight to another app?
h
Right now there is no overflow menu in Compose but you are right. I was strictly looking at the copy use case mentioned in the original issue tracker link.
Btw both Selection API and Text Toolbar improvements are in our plans. Thanks for bringing this use case to our attention.
🙏 1