最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - Difference in Spacer behavior between systemSmall and systemMedium in iOS Widget development - Stack Overflow

programmeradmin5浏览0评论

I’m developing an iOS widget and encountered an issue where the layout behaves differently between systemSmall and systemMedium sizes.

As shown in the attached image, the top and bottom elements that are visible in the systemSmall widget do not appear in the systemMedium version. However, the code is the almost same for both sizes, and I can’t find any layout-related conditions that would affect this behavior.

Here’s some context on the widget structure:

  • The root layout uses a ZStack to place a background behind the content.
  • The content is built with a VStack, containing three sections: top, middle, and bottom.
  • I use Spacer() between each section to distribute them vertically.
  • There doesn’t seem to be any conditional logic affecting the layout based on the widget size.

Here is the relevant code snippet:

import Foundation
import SwiftUI
import WidgetKit

struct TodayQuestionProvider: TimelineProvider {
  func placeholder(in context: Context) -> TodayQuestionEntry {
    TodayQuestionEntry(date: Date(), question: "Today Question")
  }

  func getSnapshot(in context: Context, completion: @escaping (TodayQuestionEntry) -> Void) {
    let entry: TodayQuestionEntry
    if context.isPreview {
      entry = placeholder(in: context)
    } else {
      let question = "Today Question"
      entry = TodayQuestionEntry(date: Date(), question: question)
    }
    completion(entry)
  }

  func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
    getSnapshot(in: context) { (entry) in
      let timeline = Timeline(entries: [entry], policy: .atEnd)
      completion(timeline)
    }
  }
}

struct TodayQuestionEntry: TimelineEntry {
  let date: Date
  let question: String
}

struct TodayQuestionWidgetEntryView: View {
  var entry: TodayQuestionProvider.Entry

  @Environment(\.colorScheme) var colorScheme
  @Environment(\.widgetFamily) var family

  private func formattedDate() -> String {
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "ko_KR")
    formatter.dateFormat = "EEEE" 
    return formatter.string(from: entry.date)
  }

  var body: some View {
    ZStack {
      Rectangle()
        .foregroundColor(.clear)
        .background(
          colorScheme == .dark
            ? LinearGradient(
              stops: [
                Gradient.Stop(color: Color(red: 0.27, green: 0.27, blue: 0.27), location: 0.00),
                Gradient.Stop(color: .black, location: 0.67),
              ],
              startPoint: UnitPoint(x: 0.5, y: 0),
              endPoint: UnitPoint(x: 0.5, y: 1)
            )
            : LinearGradient(
              stops: [
                Gradient.Stop(color: .white, location: 0.20),
                Gradient.Stop(color: Color(red: 0.91, green: 0.91, blue: 0.91), location: 1.00),
              ],
              startPoint: UnitPoint(x: 0.5, y: 0),
              endPoint: UnitPoint(x: 0.5, y: 1)
            )
        )
        .scaledToFill()

      VStack(spacing: 0) {
        HStack {
          Text(formattedDate())
            .font(Font.custom("Pretendard", size: 13).weight(.medium))
            .foregroundColor(Color(red: 0.6, green: 0.6, blue: 0.6))
            .padding(.leading, 16)

          Spacer()
        }
        .padding(.top, 12)
        .frame(maxHeight: family == .systemMedium ? 24 : nil)

        Spacer(minLength: 2)

        // ISSUE: Shown only this text when systemMedium
        Text(entry.question)
          .font(
            Font.custom(
              "Pretendard",
              size: family == .systemSmall ? 16 : 20
            ).weight(family == .systemSmall ? .semibold : .bold)
          )
          .foregroundColor(
            colorScheme == .dark
              ? Color(red: 0.73, green: 0.73, blue: 0.73)
              : .black
          )
          .frame(maxWidth: .infinity, alignment: .leading)
          .padding(.horizontal, 16)
          .frame(maxHeight: family == .systemMedium ? 79 : nil)

        Spacer(minLength: 2)

        HStack(spacing: 7) {
          ZStack {
            RoundedRectangle(cornerRadius: 30)
              .fill(colorScheme == .dark ? .white : .black)

            HStack(spacing: 2) {
              Image("Plus")
                .resizable()
                .frame(width: 20, height: 20)
              Text("Post")
                .font(Font.custom("Pretendard", size: 14).weight(.semibold))
                .foregroundColor(colorScheme == .dark ? .black : .white)
            }
          }
          .frame(height: 32)
          .frame(maxWidth: .infinity)

          ZStack {
            RoundedRectangle(cornerRadius: 30)
              .fill(colorScheme == .dark ? .white : .black)

            HStack(spacing: 2) {
              Image("Refresh")
                .resizable()
                .frame(width: 20, height: 20)
              if family == .systemMedium {
                Text("Refresh")
                  .font(Font.custom("Pretendard", size: 14).weight(.semibold))
                  .foregroundColor(colorScheme == .dark ? .black : .white)
              }
            }
          }
          .frame(height: 32)
          .frame(width: family == .systemSmall ? 32 : nil)
          .frame(maxWidth: family == .systemSmall ? nil : .infinity)
        }
        .padding(.horizontal, 8)
        .padding(.bottom, 7)
        .frame(maxHeight: family == .systemMedium ? 32 : nil)
      }
    }
  }
}

struct TodayQuestionWidget: Widget {
  let kind: String = "TodayQuestionWidget"

  var body: some WidgetConfiguration {
    let configuration = StaticConfiguration(kind: kind, provider: TodayQuestionProvider()) {
      entry in
      if #available(iOS 17.0, *) {
        TodayQuestionWidgetEntryView(entry: entry)
          .containerBackground(.fill.tertiary, for: .widget)
      } else {
        TodayQuestionWidgetEntryView(entry: entry)
      }
    }
    .configurationDisplayName("Today Question")
    .description("Check today's question and write a log")
    .supportedFamilies([.systemSmall, .systemMedium])

    if #available(iOS 15.0, *) {
      return configuration.contentMarginsDisabled()
    }
    return configuration
  }
}

#Preview(as: .systemMedium) {
// #Preview(as: .systemSmall) {
  TodayQuestionWidget()
} timeline: {
  TodayQuestionEntry(date: .now, question: "Text on widget, text on widget, text on widget")
}

I’m wondering what might be causing this discrepancy in layout rendering. Is there something about how Spacer behaves differently in systemSmall vs. systemMedium?

Any help would be appreciated!

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论