Skip to content

Android/Fuse: conditional styling issue after tap selection #520

Description

@Rodrigue2g

Summary

On Android in native/Fuse mode, grid cells can show stale conditional styling after selection changes.

I am building a calendar which consists of a LazyVGrid of tappable day cells with a shared @State selectedDate. Each cell receives an isSelected boolean. Logs confirm that after each tap, exactly one cell renders with isSelected == true, but visually the newly selected cell and previously tapped cells intermittently blink together. This does not happen on iOS.

Environment

  • Android device: Samsung SM-G973F, Android 12
  • Build: release, minified
  • Mode: native / Skip Fuse
  • Reproduces with:
    • skip-fuse-ui 1.18.1
    • skip-ui 1.59.1
  • Last known working in our released app:
    • skip-fuse-ui 1.13.0
    • skip-ui 1.53.1

Minimal POC

import SwiftUI

struct CalendarBugRepro: View {
    @State var selectedDate = Date()
    private let calendar = Calendar(identifier: .gregorian)

    var body: some View {
        LazyVGrid(
            columns: Array(repeating: GridItem(.flexible(), spacing: 0), count: 7),
            spacing: 4
        ) {
            ForEach(days, id: \.self) { date in
                Button {
                    selectedDate = date
                } label: {
                    ReproDayCell(
                        day: calendar.component(.day, from: date),
                        isSelected: calendar.isDate(date, inSameDayAs: selectedDate)
                    )
                }
                .buttonStyle(.plain)
            }
        }
        .padding()
    }

    private var days: [Date] {
        let first = calendar.date(from: DateComponents(year: 2026, month: 9, day: 1))!
        return (0..<30).compactMap { calendar.date(byAdding: .day, value: $0, to: first) }
    }
}

struct ReproDayCell: View {
    let day: Int
    let isSelected: Bool

    var body: some View {
        Text("\(day)")
            .font(.system(size: 14, weight: isSelected ? .bold : .regular))
            .foregroundStyle(isSelected ? .white : .primary)
            .frame(width: 32, height: 32)
            .background(Circle().fill(isSelected ? Color.accentColor : .clear))
            .frame(height: 44)
    }
}

Expected

Only the selected day is highlighted.

Actual

Previously selected days blink together, even though only one cell has isSelected == true.

Workaround

Keeping the view tree stable and toggling opacity avoids the issue:

  .background {
      Circle()
          .fill(Color.accentColor)
          .opacity(isSelected ? 1 : 0)
  }

So the issue seems related to conditional styling like:

  .background(Circle().fill(isSelected ? Color.accentColor : .clear))
  .foregroundStyle(isSelected ? .white : .primary)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions