asperi-demo / 4swiftui Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Hey man, this solution is really clean and works for me, however, I need it to grow from the bottom of the shape up, not in both up and down directions from the centre. What would you recommend I do to achieve that?
this modifier is doing nothing, if the there is any center alignment, it will return the very same alignment. So what is the propose of using that modifier ?
I have a custom tab view, How I can get focus on top menu items, when remote MENU is pressed, The List is scrolling to top as expected but not getting focus on the custom top menu.
@ViewBuilder
private var tabView: some View {
TabView(selection: $viewModel.currentTab) {
HomeView()
.tag(MenuTab.home)
DummyView()
.tag(MenuTab.teams)
Color.green
.tag(MenuTab.games)
Color.blue
.tag(MenuTab.search)
}
.tabViewStyle(.automatic)
.introspectTabBarController { tabBarController in
tabBarController.tabBar.isHidden = true
}
}
Can you make a custom refresh scroll indicator ?
First of all, I wanted to thank you for the code for the lazy loading of a list.
I'm trying to use it in a ForEach that works with a heavy view (a lot of UIViewRepresentables of UITextViews and UIScrollViews) so I set the block size 1. Now it only loads the first view.
I'm trying to create a modal popup system working similarly to .fullScreenCover, looking something like this:
My requirements are:
Here's a functional code snippet that satisfies those two conditions, you can run it:
struct Screen: View {
@StateObject private var model = Model()
var body: some View {
Navigation {
VStack {
Text("model.number: \(model.number)").opacity(0.5)
ChildComponent(number: $model.number)
Spacer()
}
.padding(.vertical, 30)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.purple.opacity(0.4))
}
}
}
struct ChildComponent: View {
@EnvironmentObject var navigator: Navigator
@Binding var number: Int
@State private var isFullScreenPresented = false
var body: some View {
VStack(spacing: 20) {
Text("\(number)").bold()
Button("Change (custom)", action: presentCustom).foregroundColor(.black)
Button("Change (full screen)", action: presentFullScreen).foregroundColor(.black)
}
.padding(30)
.background(Color.black.opacity(0.1))
.modalBottom(id: "childModal") {
NumberModalView(number: $number)
}
.fullScreenCover(isPresented: $isFullScreenPresented) {
NumberModalView(number: $number).environment(\.dismissModal, { isFullScreenPresented = false })
}
}
func presentCustom() {
navigator.presentModalBottom(id: "childModal")
}
func presentFullScreen() {
isFullScreenPresented = true
}
}
struct ModalView<Content:View>: View {
@Environment(\.dismissModal) var dismissCallback
@ViewBuilder var content: () -> Content
var body: some View {
VStack(spacing: 30) {
Button("Dismiss", action: { dismissCallback() }).foregroundColor(.black)
content()
}
.padding(30)
.frame(maxWidth: .infinity)
.background(Color.purple.opacity(0.8))
.frame(maxHeight: .infinity, alignment: .bottom)
}
}
struct NumberModalView: View {
@Binding var number: Int
var body: some View {
ModalView {
HStack(spacing: 20) {
Button(action: { number -= 1 }) { Image(systemName: "minus.circle").resizable().foregroundColor(.black).frame(width: 30, height: 30) }
Text("\(number)").bold()
Button(action: { number += 1 }) { Image(systemName: "plus.circle").resizable().foregroundColor(.black).frame(width: 30, height: 30) }
}
}
}
}
// MARK: - Navigation
struct Navigation<Content:View>: View {
@ViewBuilder var content: () -> Content
@StateObject private var navigator = Navigator()
@State private var modalPresentations: [String:ModalData] = [:]
var body: some View {
ZStack {
content()
if let modalID = navigator.currentModalBottom, let modal = modalPresentations[modalID] {
modal.content().environment(\.dismissModal, navigator.dismissModalBottom)
}
}
.environmentObject(navigator)
.onPreferenceChange(ModalPresentationKey.self) { modalPresentations in
self.modalPresentations = modalPresentations
}
}
}
// MARK: - Model
class Model: ObservableObject {
@Published var number: Int = 0
}
struct ModalData: Hashable {
var id: String
var content: () -> AnyView
static func == (lhs: ModalData, rhs: ModalData) -> Bool { lhs.id == rhs.id }
func hash(into hasher: inout Hasher) { hasher.combine(id) }
}
class Navigator: ObservableObject {
@Published var currentModalBottom: String?
func presentModalBottom(id: String) {
currentModalBottom = id
}
func dismissModalBottom() {
currentModalBottom = nil
}
}
// MARK: - Dismiss (Environment key)
private struct ModalDismissKey: EnvironmentKey {
static let defaultValue: () -> Void = {}
}
extension EnvironmentValues {
var dismissModal: () -> Void {
get { self[ModalDismissKey.self] }
set { self[ModalDismissKey.self] = newValue }
}
}
// MARK: - Present (Preference key)
struct ModalPresentationKey: PreferenceKey {
static var defaultValue: [String:ModalData] = [:]
static func reduce(value: inout [String:ModalData], nextValue: () -> [String:ModalData]) {
for (k,v) in nextValue() { value[k] = v }
}
}
extension View {
func modalBottom<V:View>(id: String, @ViewBuilder content: @escaping () -> V) -> some View {
preference(key: ModalPresentationKey.self, value: [
id: ModalData(id: id, content: { AnyView(content()) })
])
}
}
// MARK: - Preview
struct ParentView_Previews: PreviewProvider {
static var previews: some View {
ZStack {
Screen()
}
}
}
Now the problem: while the parent view value gets updated, the modal view value is not updated. If you try with the default full screen, you'll see that it works normally.
I'm guessing it's a problem with data flow and the fact that the modal is not a child of the component.
Since I've already spent weeks on this problem, here are some surprising things I found:
@Environment(\.dismissModal) var dismissCallback
, it works. This seems crazy to me, I don't see what role the navigator is playing in the modal data flow.How to make the modal view react to model changes while keeping my requirements above?
Source:
https://stackoverflow.com/questions/74149682/view-not-updating-in-modal-hierarchy
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.