Swiftui складные шкуры заголовка после выпуска жестаIOS

Программируем под IOS
Ответить
Anonymous
 Swiftui складные шкуры заголовка после выпуска жеста

Сообщение Anonymous »

Я пытаюсь реализовать складной заголовок в Swiftui, который рушится, когда пользователь прокручивается и расширяется, когда пользователь прокручивает вверх. Пользователь перетаскивает представление сверху (притягивает к стилю обновления), а затем выпускается, заголовок исчезает /неожиданно скрывается.public struct CollapsibleHeaderList: View {
// MARK: - Private Vars
private let items = Array(0.. Bool {
guard let lastAnimationDate else {
return true
}

return abs(lastAnimationDate.timeIntervalSinceNow) > animationDuration
}
}

public enum HeaderState {
case initial
case collapse
case expand
}
public class CollapsibleHeaderViewModel: ObservableObject {
@Published private(set) public var state: HeaderState
private var indexSubject = PassthroughSubject()
private var cancellables = Set()

init() {
self.state = .initial
setupCollapsibleHeaderListener()
}

public func onCellAppear(index: Int) {
indexSubject.send(index)
}

private func setupCollapsibleHeaderListener() {
indexSubject
.throttle(for: .seconds(0.5), scheduler: DispatchQueue.main, latest: true)
.withPrevious()
.map { (previous, current) in
if let previous, previous < current {
return .collapse
} else {
return .expand
}
}
.removeDuplicates()
.sink { [weak self] headerState in
self?.state = headerState
}.store(in: &cancellables)
}
}

extension Publisher {
/// Includes the current element as well as the previous element from the upstream publisher in a tuple where the previous element is optional.
/// The first time the upstream publisher emits an element, the previous element will be `nil`.
/// This code was copied from https://stackoverflow.com/questions/639 ... ng-combine
///
/// let range = (1...5)
/// cancellable = range.publisher
/// .withPrevious()
/// .sink { print ("(\($0.previous), \($0.current))", terminator: " ") }
/// // Prints: "(nil, 1) (Optional(1), 2) (Optional(2), 3) (Optional(3), 4) (Optional(4), 5) ".
///
/// - Returns: A publisher of a tuple of the previous and current elements from the upstream publisher.
public func withPrevious() -> AnyPublisher {
scan(Optional.none) { ($0?.1, $1) }
.compactMap { $0 }
.eraseToAnyPublisher()
}
}

Вопрос:
Как я могу предотвратить скрытие заголовка, когда пользователь снимается с вершины? Кроме того, когда представление появляется в первый раз, заголовок не виден - он немедленно исчезает. < /P>
Вот запись экрана: запись экрана 2 < /p>
Вот код mycurrent: < /p>
@State private var showingHeader = true

var body: some View {
ZStack {
Color.backgroundColor3
.edgesIgnoringSafeArea(.all)
VStack(spacing: 0) {
if showingHeader {
GlobalContactsFilterView(viewModel: viewModel)
.frame(height: 60)
.transition(
.asymmetric(
insertion: .push(from: .top),
removal: .push(from: .bottom)
)
)
}

if viewModel.isRefreshing {
VStack {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
}
.frame(maxWidth: .infinity)
.padding(.top, 10)
}

if viewModel.contacts.isEmpty && !viewModel.isLoading && !viewModel.isRefreshing {
NoDataView()
} else {
GeometryReader { outer in
let outerHeight = outer.size.height
ScrollView(.vertical) {
LazyVStack {
ForEach(Array(viewModel.contacts.enumerated()), id: \.element.id) { index, contact in
VStack(alignment: .leading) {
VStack {
VStack(spacing: 12) {

if contactVisibleFields.contains(.firstName) {
ContactDetailField(title: Strings.firstName, text: contact.firstName, textFont: .system(size: 13, weight: .semibold))
}

Rectangle()
.fill(.clear)
.frame(maxWidth: .infinity, maxHeight: 1)
}
.padding(.top, 10)
}
.frame(maxWidth: .infinity)
.background(.backgroundColor2)
.padding(.bottom, 3)
}
.frame(maxWidth: .infinity)
.background(index == viewModel.contacts.count - 1 ? Color.clear : Color.filterBarBackground)
.padding(.bottom, index == viewModel.contacts.count - 1 ? 50 : 0)

}
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets())
.listRowSeparator(.hidden)

HStack {
Spacer()
if viewModel.isLoading && !viewModel.isRefreshing {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
} else {
Color.clear
.frame(height: 1)
.onAppear {
if let _ = clerk.user {
viewModel.fetchContacts()
}
}
}
Spacer()
}
.frame(maxWidth: .infinity)
.listRowSeparator(.hidden)
.listRowBackground(Color.clear)
}
.background {
GeometryReader { proxy in
let contentHeight = proxy.size.height
let minY = max(
min(0, proxy.frame(in: .named("ScrollView")).minY),
outerHeight - contentHeight
)
Color.clear
.onChange(of: minY) { oldVal, newVal in
if (showingHeader && newVal < oldVal) || !showingHeader && newVal > oldVal {
showingHeader = newVal > oldVal
}
}
}
}
}
.coordinateSpace(name: "ScrollView")
}
.padding(.top, 1)
}
}
//.frame(maxHeight: .infinity, alignment: .top)
.animation(.easeInOut, value: showingHeader)


Подробнее здесь: https://stackoverflow.com/questions/797 ... wn-gesture
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»