Conflicting 'on' color for a given background error in jetpack compose - kotlin

I'm making a theme for my app with jetpack compose and I have this:
#Composable
fun MyTheme(content: #Composable () -> Unit) {
val colors = lightColors(
primary = CustomColors.Custom1,
primaryVariant = CustomColors.Custom2,
onPrimary = Color.White,
background = Color.White,
secondary = CustomColors.Custom2
)
MaterialTheme(colors = colors, content = content)
}
object CustomColors{
val Custom1 = Color(0xEF119335)
val Custom2= Color(0xAA892335)
}
The problem is that when I add secondary = CustomColors.Custom2, I get an error in onPrimary = Color.White. The error is this:
Conflicting 'on' color for a given background error

Error description from Compose source code
Background colors with the same value should have the same 'on' color
In the Material color system background colors have a corresponding 'on' color which is used for the content color inside a component. For example, a button colored primary will have onPrimary text. Because of this, it is important that there is only one possible onColor for a given color value, otherwise there is no way to know which 'on' color should be used inside a component. To fix this either use the same 'on' color for identical background colors, or use a different background color for each 'on' color.
In your case, you have both primaryVariant and secondary set to CustomColors.Custom2, this means corresponding background colors should be the same too.
Default onSecondary color is Color.Black, and for onPrimary you've specified Color.White, that's why the compiler in unhappy.
You can solve this problem by specifying onSecondary = Color.White or by choosing different colors for primaryVariant and secondary.
If after this explanation you still wanna use these exact colors, you can silent this warning with #SuppressLint("ConflictingOnColor"): but some system or Material elements may not look good.

Related

Jetpack compose: Top App Bar pinnedScrollBehavior not changing color on scroll from text focus events

Okay, so this is a bit of a specific issue, but hopefully someone understands what's happening:
I'm using a Jetpack Compose Material 3 CenterAlignedTopAppBar, with TopAppBarDefaults.pinnedScrollBehavior to make it so that the color of the appbar changes when I scroll down on nested content.
It works! In most cases. However, one of my screens has a large text field, that when clicked causes the content to scroll down by itself (to focus on the text field)—and that seems to confuse the appbar, which doesn't change color. It will only change color if I manually scroll up and down.
Relevant code:
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
contentWindowInsets = EmptyWindowInsets,
modifier = Modifier
.fillMaxHeight()
.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
// just a wrapper around CenterAlignTopAppBar
StandardTopAppBar(scrollBehavior = scrollBehavior)
},
content = { innerPadding ->
// I've also tried with LazyColumn and see the same behavior
Column(
Modifier
.padding(innerPadding)
.padding(start = 10.dp, end = 10.dp)
.fillMaxHeight()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
tl;dr; manually scrolling changes the appbar color, but scrolling caused by clicking into a text field that scrolls into view does not. Any idea how I could fix this?
Probably not quite what you are looking for unfortunately, but I had a similar problem. My TopAppBar color was also stuck, but when navigating between different screens. I fixed it by assigning the TopAppBar a different scrollBehaviour depending on the screen.
val scrollBehavior1 = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val scrollBehavior2 = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
In TopAppBar arguments:
scrollBehavior =
when (currentRoute) {
Screens.ExampleScreen1.route -> scrollBehavior1
Screens.ExampleScreen2.route -> scrollBehavior2
else -> null
}
Hopefully this helps you in one way or another.

Jetpack Compose OutlinedTextField with the label on the inside and golden glow around the outline when selected

I'm trying to make a TextField like in the image using Jetpack Compose.
So far no luck in finding a easy way.
The label must stay inside the outline, if I use OutlinedTextField there is no way to customise that. If I use the TextField which has the label on the inside there is no outline when selected, just the line below the textfield.
Also I need to add a shadow/glow effect with a custom color, here seen in gold.
I'm stumped..
Any thoughts?
You can do this by creating a Row with a Modifier.drawBehind that uses native paint to draw blur with color as in this image, the one with pink background has blur with same background color for shadow for instance, you can check the code for drawing colored blur here.
val myColor = color
.copy(alpha = shadow.alpha)
.toArgb()
val transparent = color
.copy(alpha = 0f)
.toArgb()
frameworkPaint.color = transparent
frameworkPaint.setShadowLayer(
radius,
dx,
dy,
myColor
)
it.drawRoundRect(
//...
paint = paint
)
It draws a shape behind you can draw a shape with stroke.
For the label and input create a Column with Modifier.weight() to use space inside row other than space reserved for Icon with close image.
Instead of TextField you can use a BasicTextfield which doesn't have default padding, however you can achieve the same thing with TextField too, but you will need to set colors to transparent to remove indicator line, it has some default padding you might not want to have.
TextField(
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
)
)

Why did the border radius disappear for an RecyclerView item with a custom background?

I try to figure out Android development, and sometimes I have beginner question. For now I faced with issue creating the RecyclerView items with different background color. I created a simple
RecyclerView items list First I set one background (light green) for all items.
Then I decided to set a separate background for each item. Here's how I did it in adapter file:
override fun onBindViewHolder(holder: ChapterListAdapter.ViewHolder, position: Int) {
holder.chapter_item.text = chapter_titles[position]
holder.chapter_details.text = chapter_descrs[position]
holder.chapter_image.setImageResource(chapter_images[position])
when(position){
0 -> holder.chapter_card.setBackgroundColor(Color.parseColor("#ff5668"))
1 -> holder.chapter_card.setBackgroundColor(Color.parseColor("#41d5e2"))
2 -> holder.chapter_card.setBackgroundColor(Color.parseColor("#4d53e0"))
3 -> holder.chapter_card.setBackgroundColor(Color.parseColor("#ff8e36"))
}
}
And it works, it may not be the right way to do it, but it works. However, there is one problem. In the screenshot, you can see that the last item has a border radius. I set the cardCornerRadius value for the element in card_layout.xml And for some reason, when I assign a custom color for an item, this value disappears. This can be seen in the screenshot. The last element with a light green background has a border radius (I did not assign a custom background color value to this element) and the first four elements that have a custom color assigned do not have a border radius.
Please tell me why this is happening and how to fix it. I need to keep the border radius for all elements.
I really glad I fond the error by myself. For setting the item background color I used setBackgroundColor but it's not correct in my case. In my case I have to use setCardBackgroundColor because I setting background for the CardView. Now my code looks:
override fun onBindViewHolder(holder: ChapterListAdapter.ViewHolder, position: Int) {
holder.chapter_item.text = chapter_titles[position]
holder.chapter_details.text = chapter_descrs[position]
holder.chapter_image.setImageResource(chapter_images[position])
when(position){
0 -> {
holder.chapter_card.setCardBackgroundColor(Color.parseColor("#ff5668"))
}
1 -> {
holder.chapter_card.setCardBackgroundColor(Color.parseColor("#41d5e2"))
}
2 -> {
holder.chapter_card.setCardBackgroundColor(Color.parseColor("#4d53e0"))
}
3 -> {
holder.chapter_card.setCardBackgroundColor(Color.parseColor("#ff8e36"))
}
}
}
And it works well.

Clickable box makes its "non-clickable parent box" clickable as well?

Here is the code snippet:
Box(
Modifier
.size(48.dp, 48.dp)
.background(Color.Transparent)
.align(Alignment.CenterEnd)
)
{
Box(
Modifier
.size(height = 35.636363.dp, width = 41.818181.dp)
.align(Alignment.CenterEnd)
.clip(RoundedCornerShape(topStart = 20.dp, bottomStart = 20.dp))
.clickable(onClick = {showDialogFragment.value = true})
.background(Color.Red)
)
}
Whenever i click on parent box (the one which is transparent) it activates click event of its only child. Why so? Current behavior meets my needs, but i dont understand why it happens.
According to Material Guidelines, the minimum touch size is 48.dp.
Since 1.1.0-alpha03, when you add touch detection to a view with a size smaller than this value, tracking will work on the enlarged frame.
Added minimum touch target size to ViewConfiguration for use in semantics and pointer input to ensure accessibility.
Just out of curiosity, you can check the extended touch padding for the current view using pointerInput modifier, which lies under all touch processing in Compose:
.pointerInput(Unit) {
println("$extendedTouchPadding")
}

NSTextBlock backgroundColor is not drawn

I have an NSTextBlock subclass that has a specific backgroundColor set. Now when I add a custom paragraph style to a range of text like this
let block = MyTextBlock()
block.backgroundColor = myBackgroundColor
let pstyle = NSMutableParagraphStyle()
pstyle.textBlocks = [block]
attributedText.addAttribute(.paragraphStyle, value: pstyle, range: textRange)
// Append the attributed string to the text views textStorage ...
the text block is shown without a background color. I know that the text blocks works, because rectForLayout gets called, but when I try to override drawBackground it never gets called.
Do I have to do something else for NSTextBlocks to draw their background?
PS: Borders also seem to be ignored. I also tried to find a sample on Github, but that also doesn't draw any backgrounds, despite having a background color set.
After trying everything, I finally managed to get the background to show up, by setting
setValue(100, type: .percentageValueType, for: .width)
It seems that the drawing logic expects some value for the content size. Really nice documentation job there. This requirement is nowhere to be found.