Post

Replies

Boosts

Views

Activity

How to combine contextMenu & RoundedRectangle?
I am trying to create a list of not rectangular elements, each of which has a context menu. However, I am encountering an issue with the corners when performing a long press. What is the correct way to use such a combination? I don't want to use List because of its default styling. The issue takes place only while animation is in progress. Here's a simplified code example that can be copied pasted and ran in one file. The video was recorded on the device with iOS 18.2 import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { TestView() } } } struct TestView: View { let items = ["Item 1", "Item 2", "Item 3"] var body: some View { VStack { ForEach(items, id: \.self) { item in HStack { Text(item) Spacer() Image(systemName: "star") } .padding() .background(.yellow) // tried all these in different combinations, none works .contentShape(RoundedRectangle(cornerRadius: 10)) .clipShape(RoundedRectangle(cornerRadius: 10)) .containerShape(RoundedRectangle(cornerRadius: 10)) .contextMenu { Button { print("Edit \(item)") } label: { Text("Edit"); Image(systemName: "pencil") } } } } .padding() } } #Preview { TestView() }
1
0
338
Dec ’24
How to connect SwiftUI state with UITable?
I use @Binding to sync data between SwiftUI component state and UITable state. my observations: while reordering @State variable of the TestView is updating, it can be checked by taping the button inside the table the data is not updating. 'log2' is always the same on reorder and which is more important the app crashes when I try to remove item. What to I missing? import SwiftUI import UIKit struct TestView: View { @State var items = ["item 1", "item 2", "item 3", "item 4", "item 5"] var body: some View { VStack { Button("Print Items") { print("log1", items) } ReorderableListView( items: $items ) { item in Text(item) } } } } private struct ReorderableListView<Content: View>: UIViewControllerRepresentable { @Binding var items: [String] let content: (String) -> Content class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate { var parent: ReorderableListView init(parent: ReorderableListView) { self.parent = parent } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { print("log2", parent.items) return parent.items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let hostingController = UIHostingController(rootView: parent.content(parent.items[indexPath.row])) hostingController.view.backgroundColor = .clear cell.contentView.subviews.forEach { $0.removeFromSuperview() } cell.contentView.addSubview(hostingController.view) cell.separatorInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) if indexPath.row == self.parent.items.count - 1 { cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: .greatestFiniteMagnitude) } hostingController.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ hostingController.view.topAnchor.constraint(equalTo: cell.contentView.topAnchor), hostingController.view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor), hostingController.view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor), hostingController.view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor) ]) return cell } func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { let movedObject = parent.items.remove(at: sourceIndexPath.row) parent.items.insert(movedObject, at: destinationIndexPath.row) } func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { return true } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { parent.items.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .automatic) } } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIViewController(context: Context) -> UITableViewController { let tableViewController = UITableViewController() tableViewController.tableView.dataSource = context.coordinator tableViewController.tableView.delegate = context.coordinator tableViewController.tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "Cell") tableViewController.tableView.isEditing = true return tableViewController } func updateUIViewController(_ uiViewController: UITableViewController, context: Context) { uiViewController.tableView.reloadData() } } private class CustomTableViewCell: UITableViewCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) } override func layoutSubviews() { super.layoutSubviews() superview?.subviews.filter({ "\(type(of: $0))" == "UIShadowView" }).forEach { (sv: UIView) in sv.removeFromSuperview() } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } #Preview { TestView() }
1
0
330
Oct ’24
what's wrong with `ToolbarItemGroup(placement: .keyboard)` inside `TavView`?
Why is there inconstancy of appearing the keyboard tool bar Item with tab view? Try to go to second tab and focus the field. Sometimes it does not appear (in my more complex project it does not appear >90% times). import SwiftUI struct MainTabView: View { var body: some View { TabView { FirstTabView() .tabItem { Label("Tab 1", systemImage: "house") } SecondTabView() .tabItem { Label("Tab 2", systemImage: "star") } } } } struct FirstTabView: View { @State private var text = "" var body: some View { NavigationStack { VStack { TextField("Enter something 1", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } .toolbar { ToolbarItemGroup(placement: .keyboard) { Button("Done") { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } } } } } struct SecondTabView: View { @State private var text = "" var body: some View { NavigationStack { VStack { TextField("Enter something 2", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } .toolbar { ToolbarItemGroup(placement: .keyboard) { Button("Done") { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } } } } } #Preview { MainTabView() }
0
2
299
Sep ’24
why ToolbarItemGroup appears only on the first tab?
// just check the below code. it's about simplest possible to // looks the same with simulator and real device with iOS 17.1+ import SwiftUI struct MainTabView: View { @FocusState private var focusedField: Bool var body: some View { TabView { TextField("test 1", text: .constant("test 1")) .focused($focusedField) .tabItem { Label("tab 1", systemImage: "number") } .toolbar { ToolbarItemGroup(placement: .keyboard) { Button("Done") { focusedField = false } } } Text("test 2") .tabItem { Label("Home", systemImage: "house") } TextField("test 3", text: .constant("test 3")) .focused($focusedField) .tabItem { Label("tab 3", systemImage: "number") } .toolbar { ToolbarItemGroup(placement: .keyboard) { Button("Done") { focusedField = false } } } } .tint(.primary) } } @main struct MainApp: App { var body: some Scene { WindowGroup { MainTabView() } } }
1
0
533
Aug ’24