Jetpack Compose Desktop: Scrollable Column/LazyColumn - kotlin

I'm creating a program in Jetpack Compose Desktop version 1.0.0-beta5 and I can't figure out how to make Column/LazyColumn scrollable. At the same time, it seems to me that a lot of the classes listed in the documentation for Android are missing and can not work from their examples.
val lazyListState = rememberLazyListState()
val scrollState = rememberScrollState()
LazyColumn(
state = lazyListState,
modifier = Modifier.verticalScroll(scrollState)
) {
items(ArrayList<String>()){ item ->
Column(modifier = Modifier.padding(8.dp)) {
Text(item)
}
}
}
This code is currently producing an error.
To be precise, the empty list used can be seen in the example, but this is just an adjustment, in fact I draw a lot of items.

I know this question is very old, but you can take a look at Desktop Compoments
Jetpack compose is for the android framework,
Compose desktop is a flavor of Jetpack compose, it uses Skia and Swing under the hood

Related

Jetpack Compose Desktop: getting your display's height and width

I am looking for a way to get your display's height and width in Jetpack Compose for Desktop, but despite the fact that I've found some questions on SO (Screen width and height in Jetpack Compose), it's not very helpful, because there are no values (and other stuff) such as LocalConfiguration, only - LocalViewConfiguration, which is a different thing.
So, some words about my initial goal: I want to be able to automatically change the size of font used in my application: textStyle = TextStyle(fontFamily = FontFamily.Monospace, fontSize = calculateRelativeFontSize()), where: #Composable fun calculateRelativeFontSize(): TextUnit { val height = ...; val width = ...; ...}
Finally, I'm sorry if I'm missing something, because I'm not really a Kotlin or (honestly) Jetpack Compose programmer, just was asked to do some stuff...
P.S. I'm working under Linux, so... maybe somehow (really don't believe in that)... (you got the point)
You have to remember that JetBrains Compose is built upon Skia and Java's AWT libraries. You can use their native functions relating to screen info. For instance using AWT:
// CloudsAnimation.kt
import org.jetbrains.skia.RuntimeEffect
import java.awt.Toolkit
#Composable
fun CloudsAnimation(
modifier: Modifier = Modifier
) {
val screenSize = Toolkit.getDefaultToolkit().screenSize
val screenHeight = screenSize.height
val screenWidth = screenSize.width
println("Width: $screenWidth ; Height: $screenHeight")
// ... composables below etc
}
Running this on my 13 inch MacBook Pro :
Width: 1440 ; Height: 900

Why scrollable modifier doesn't scroll view content?

I am trying to get scrolling to work on a Column where the number of entries may exceed the height of the window.
I'm currently using Compose 1.1.0-rc03 and at the moment I'm only trying to get it working on desktop.
I reduced the problem to this:
#Composable
fun App() {
val optionsScrollState = rememberScrollState()
Row(modifier = Modifier.fillMaxSize()) {
// Left column
Column(
modifier = Modifier
.scrollable(optionsScrollState, Orientation.Vertical)
.width(240.dp)
.fillMaxHeight()
) {
(1..100).forEach { i -> Text("Row $i") }
}
}
}
But this doesn't scroll, or at least, not with the mousewheel. Maybe there's another way to scroll that isn't immediately apparent to me.
How do I make this work?
The docs on scrollable say that I might have to manage the state myself. So is using rememberScrollState() not enough?
I found some existing questions about disabling scrolling on columns, but they were always talking about LazyColumn which I'm not using here.
You're using a wrong modifier. From documentation:
The scrollable modifier differs from the scroll modifiers in that scrollable detects the scroll gestures, but does not offset its contents.
If you're interested how Modifier.scrollable should be used, you can find an example in the same documentation chapter.
You can use Modifier.verticalScroll instead, which will give you the expected behavior.
Also consider switching to LazyColumn, which already has built-in scrolling as well as lazy cell loading.

BigTextStyle doesn't work when used with BigPictureStyle in notification (Kotlin)

When I use BigTextStyle and BigPictureStyle together, only setContentText and BigPictureStyle are shown in the notification drawar. I mean if the text is long, it won't show the full text (BigTextStyle doesn't seem to work at all)
It shows the same on my phone (Android 11),
Does anyone know how I can solve this problem?
private fun sendNotification() {
val intent = Intent(this, MainActivity::class.java)
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val bitmap = BitmapFactory.decodeResource(applicationContext.resources, R.drawable.wallet)
val bitmapLargeImage = BitmapFactory.decodeResource(applicationContext.resources, R.drawable.sell)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_baseline_attach_money_24)
.setContentTitle("Purchase")
.setContentText("This is the text I want to show to my users in the notification bar, but it is not fully shown.")
.setContentIntent(pendingIntent)
.setStyle(NotificationCompat.BigTextStyle().bigText("This is the text I want to show to my users in the notification bar, but it is not fully shown."))
.setStyle(NotificationCompat.BigPictureStyle().bigPicture(bitmapLargeImage))
.setLargeIcon(bitmap)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
with(NotificationManagerCompat.from(this)) {
notify(notificationID, builder.build())
}
}
Wanted to post a comment but don't have enough reputation.
As far as I know you cannot use BigTextStyle with BigPictureStyle, by default.
To do that, you need to create a Custom View for your notification
See the documentation on how to create a Custom View for a notification: https://developer.android.com/training/notify-user/custom-notification
Maybe this similar stackoverflow question can help: How to use both BigTextStyle and BigPictureStyle in setStyle Notification?
While this may not be a problem for you, for apps that target Android 12 some behaviours for fully custom notifications change - See https://developer.android.com/about/versions/12/behavior-changes-12#custom-notifications

Jetpack Compose Desktop – MaterialTheme.colors.background Not Working

Setting MaterialTheme.colors
I'm trying to make a very basic window in Jetpack Compose for Desktop (not mobile), but I'm having some difficulties with changing the colors of the window. I've looked at some tutorials and examples, but maybe I don't quite understand how color themes are correctly implemented.
The code that I wrote should create a window with a dark background, but the window when the program runs is white.
Please provide any insights you can as to what I am doing wrong.
Code (Kotlin)
import androidx.compose.desktop.*
import androidx.compose.material.*
import androidx.compose.ui.unit.*
fun main() = Window(
title = "Window",
resizable = false,
size = IntSize(1200, 800),
) {
MaterialTheme(colors = darkColors()) {
}
}
Window
Other Info
macOS Big Sur
IntelliJ 2021.2
Jetpack Compose 0.4.0
The MaterialTheme only provides colors for all views inside the container, it does not create or render the view.
Most Material components will use these colors as default values, but you can also use these colors in your views using, for example, MaterialTheme.colors.background.
You need to put some view inside, size it and apply some background color, for example:
MaterialTheme(colors = darkColors()) {
Box(Modifier.fillMaxSize().background(MaterialTheme.colors.background))
}
You can use Scaffold to see changes.
In your example:
...
MaterialTheme(colors = darkColors()) {
Scaffold {
// your content
}
}
...
You can read about it:
https://developer.android.com/jetpack/compose/layouts/material
or here:
https://metanit.com/kotlin/jetpack/4.11.php

Espresso swipe gesture test fails on android emulator but passes on real device

I have been using my phone to run instrumented android tests for a long time. Today I thought I would switch to the emulator, but I found that some tests that pass on my phone do not pass on the emulator -- because the swipe gesture does not do the same thing on the emulator as it does on my phone (Xperia Z5 Compact, Android 7.1.1). I am also running the same version of Android in the emulator.
When run on the emulator the ViewActions.swipeLeft() method seems to start the swipe too far to the right and cause that little wavy animation that happens when you drag from the very edge of the screen at an end of a ViewPager. The swipe works totally fine on the phone and emulator when done manually. Hence, I think it must be something to do with Espresso. I can imagine how perhaps the issue could be the swipe listener in a RecyclerView inside a swipe-able ViewPager. But it works fine on the emulator and phone and tests pass on my phone.
This is my swipe handling code, which is added to a RecyclerView inside a ViewPager tab (on the last tab).
fun attachSingleSwipeActionToRecyclerView(
direction: Int = ItemTouchHelper.LEFT,
recyclerView: RecyclerView,
swipeAction: RecyclerView.ViewHolder.() -> Unit
): ItemTouchHelper {
val simpleCallback = object : ItemTouchHelper.SimpleCallback(0, direction) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
swipeAction(viewHolder)
}
}
val itemTouchHelper = ItemTouchHelper(simpleCallback)
itemTouchHelper.attachToRecyclerView(recyclerView)
return itemTouchHelper
}
In my test I am simply calling ViewActions.swipeLeft() on the first RecyclerView item on the screen.
I have tried creating my own start point for the Espresso swipe, even when I made it start at the very center, rather than far right side, nothing changed, including the end of ViewPager wave animation
GeneralSwipeAction(
Swipe.FAST,
GeneralLocation.CENTER,
GeneralLocation.CENTER_LEFT,
Press.FINGER
)
What could be different about the emulator that causes the espresso swipe to act differently than on a real device?
At times, GeneralSwipeAction can become unreliable because of its calculation varies on different screen size or density, so it may not be suitable for ViewPager in your case. Instead, you could try to scroll with ViewPagerActions:
// Moves ViewPager to the right be one page.
onView(your_view_pager).perform(ViewPagerActions.scrollRight());
// Moves ViewPager to a specific page.
onView(your_view_pager).perform(ViewPagerActions.scrollToPage(page_number));