Skip to content

Commit

Permalink
Merge pull request #200 from kyleve/kve/adjust-keyboard-but-more-than…
Browse files Browse the repository at this point in the history
…-before

Adjust the keyboard inset more than before
  • Loading branch information
kyleve authored Aug 28, 2020
2 parents 09e1eff + 745ac28 commit b15afde
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### Fixed

- [Adjust calculated keyboard inset in both `setFrame` and `layoutSubviews`](https://github.com/kyleve/Listable/pull/200). This resolves issues that can occur if the list frame changes while the keyboard is visible.

### Added

- [Add support for `onInsert` , `onRemove`, `onMove`, `onUpdate`, on `Item`](https://github.com/kyleve/Listable/pull/196) to track when when items are added, removed, moved, or updated. Changed `onContentChanged` to `onContentUpdated` on `ListStateObserver`; it is always called during updates; you can check the `hadChanges` property.
Expand Down
4 changes: 4 additions & 0 deletions Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
0A07119324BA798400CDF65D /* ListStateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A07119224BA798400CDF65D /* ListStateViewController.swift */; };
0A0E070423870A5700DDD27D /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0A0E070323870A5700DDD27D /* README.md */; };
0A49210424E5E11300D17038 /* AccordionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A49210324E5E11300D17038 /* AccordionViewController.swift */; };
0A5DC1A924F6FD4200DC7C14 /* ListAppearsAfterKeyboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5DC1A824F6FD4200DC7C14 /* ListAppearsAfterKeyboardViewController.swift */; };
0A793B5824E4B53500850139 /* ManualSelectionManagementViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A793B5724E4B53500850139 /* ManualSelectionManagementViewController.swift */; };
0A87BA652463567B0047C3B5 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 0A87BA642463567B0047C3B5 /* CHANGELOG.md */; };
0AA4D9B9248064A300CF95A5 /* CustomLayoutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA4D9A8248064A200CF95A5 /* CustomLayoutsViewController.swift */; };
Expand Down Expand Up @@ -47,6 +48,7 @@
0A07119224BA798400CDF65D /* ListStateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStateViewController.swift; sourceTree = "<group>"; };
0A0E070323870A5700DDD27D /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
0A49210324E5E11300D17038 /* AccordionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccordionViewController.swift; sourceTree = "<group>"; };
0A5DC1A824F6FD4200DC7C14 /* ListAppearsAfterKeyboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListAppearsAfterKeyboardViewController.swift; sourceTree = "<group>"; };
0A793B5724E4B53500850139 /* ManualSelectionManagementViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualSelectionManagementViewController.swift; sourceTree = "<group>"; };
0A87BA642463567B0047C3B5 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = "<group>"; };
0AA4D9A8248064A200CF95A5 /* CustomLayoutsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLayoutsViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -133,6 +135,7 @@
0ACF96D524A0094D0090EAC4 /* ItemInsertAndRemoveAnimationsViewController.swift */,
0AA4D9B3248064A300CF95A5 /* ItemizationEditorViewController.swift */,
0AA4D9AB248064A300CF95A5 /* KeyboardTestingViewController.swift */,
0A5DC1A824F6FD4200DC7C14 /* ListAppearsAfterKeyboardViewController.swift */,
0A07119224BA798400CDF65D /* ListStateViewController.swift */,
0AC2A1952489F93E00779459 /* PagedViewController.swift */,
0AA4D9B7248064A300CF95A5 /* ReorderingViewController.swift */,
Expand Down Expand Up @@ -425,6 +428,7 @@
0AA4D9C6248064A300CF95A5 /* SwipeActionsViewController.swift in Sources */,
0AA4D9BF248064A300CF95A5 /* WidthCustomizationViewController.swift in Sources */,
0AA4D9C8248064A300CF95A5 /* ReorderingViewController.swift in Sources */,
0A5DC1A924F6FD4200DC7C14 /* ListAppearsAfterKeyboardViewController.swift in Sources */,
0A07119324BA798400CDF65D /* ListStateViewController.swift in Sources */,
0AA4D9C0248064A300CF95A5 /* InvoicesPaymentScheduleDemoViewController.swift in Sources */,
0AEB96E222FBCC1D00341DFF /* AppDelegate.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// ListAppearsAfterKeyboardViewController.swift
// Demo
//
// Created by Kyle Van Essen on 8/26/20.
// Copyright © 2020 Kyle Van Essen. All rights reserved.
//

import UIKit
import BlueprintLists
import BlueprintUICommonControls


final class ListAppearsAfterKeyboardViewController : UIViewController {

let blueprintView = BlueprintView()

override func loadView() {
self.view = self.blueprintView

self.blueprintView.element = self.element
}

override func viewDidLoad() {
super.viewDidLoad()

self.navigationItem.rightBarButtonItems = [
UIBarButtonItem(title: "Toggle List", style: .plain, target: self, action: #selector(toggleList)),
UIBarButtonItem(title: "Dismiss", style: .plain, target: self, action: #selector(dismissKeyboard))
]
}

var showingList : Bool = false

var element : Element {
EnvironmentReader { env in
Column { column in
column.horizontalAlignment = .fill
column.verticalUnderflow = .growProportionally

column.add(growPriority: 0, shrinkPriority: 0, child: TextField(text: "") {
$0.placeholder = "Tap Into This Field To Show The Keyboard"
$0.textAlignment = .center
})

if self.showingList {
column.add(child: List { list in

list.behavior.keyboardDismissMode = .none

list("section") { section in
section += (1...20).map { index in
DemoItem(text: "Item \(index)")
}
}
})
}
}.inset(by: env.safeAreaInsets)
}
}

@objc func toggleList() {
self.showingList.toggle()

self.blueprintView.element = self.element
}

@objc func dismissKeyboard() {
self.view.endEditing(true)
}
}
9 changes: 8 additions & 1 deletion Demo/Sources/Demos/DemosRootViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,19 @@ public final class DemosRootViewController : ListViewController
})

section += Item(
DemoItem(text: "Keyboard Testing"),
DemoItem(text: "Keyboard Inset (Full Screen List)"),
selectionStyle: .selectable(),
onSelect : { _ in
self.push(KeyboardTestingViewController())
})

section += Item(
DemoItem(text: "Keyboard Inset (Appears Later)"),
selectionStyle: .selectable(),
onSelect : { _ in
self.push(ListAppearsAfterKeyboardViewController())
})

section += Item(
DemoItem(text: "Reordering (Experimental)"),
selectionStyle: .selectable(),
Expand Down
71 changes: 51 additions & 20 deletions Listable/Sources/ListView/ListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ public final class ListView : UIView
*/
self.collectionView.frame = self.bounds

guard oldValue != self.frame else {
return
}

/**
Once the view actually has a size, we can provide content.

Expand All @@ -516,15 +520,16 @@ public final class ListView : UIView
self.updatePresentationState(for: .transitionedToBounds(isEmpty: true))
}

if oldValue != self.frame {
ListStateObserver.perform(self.stateObserver.onFrameChanged, "Frame Changed", with: self) { actions in
ListStateObserver.FrameChanged(
actions: actions,
positionInfo: self.scrollPositionInfo,
old: oldValue,
new: self.frame
)
}
/// Our frame changed, update the keyboard inset in case the inset should now be different.
self.setContentInsetWithKeyboardFrame()

ListStateObserver.perform(self.stateObserver.onFrameChanged, "Frame Changed", with: self) { actions in
ListStateObserver.FrameChanged(
actions: actions,
positionInfo: self.scrollPositionInfo,
old: oldValue,
new: self.frame
)
}
}
}
Expand Down Expand Up @@ -558,6 +563,9 @@ public final class ListView : UIView
super.layoutSubviews()

self.collectionView.frame = self.bounds

/// Our layout changed, update the keyboard inset in case the inset should now be different.
self.setContentInsetWithKeyboardFrame()
}

//
Expand Down Expand Up @@ -868,6 +876,27 @@ public final class ListView : UIView
}


public extension ListView
{
///
/// Call this method to force an immediate, synchronous re-render of the list
/// and its content when writing unit or snapshot tests. This avoids needing to
/// spin the runloop or needing to use test expectations to wait for content
/// to be rendered asynchronously.
///
/// **WARNING**: You must **not** call this method outside of tests. Doing so will cause a fatal error.
///
func testing_forceLayoutUpdateNow()
{
guard NSClassFromString("XCTestCase") != nil else {
fatalError("You must not call testing_forceLayoutUpdateNow outside of an XCTest environment.")
}

self.collectionView.reloadData()
}
}


extension ListView : ItemContentCoordinatorDelegate
{
func coordinatorUpdated(for : AnyItem, animated : Bool)
Expand Down Expand Up @@ -960,19 +989,21 @@ extension ListView : KeyboardObserverDelegate
return
}

let inset : CGFloat

switch self.behavior.keyboardAdjustmentMode {
case .none: inset = 0.0

case .adjustsWhenVisible:
switch frame {
case .nonOverlapping: inset = 0.0
let inset : CGFloat = {
switch self.behavior.keyboardAdjustmentMode {
case .none:
return 0.0

case .overlapping(let frame):
inset = (self.bounds.size.height - frame.origin.y) - self.lst_safeAreaInsets.bottom
case .adjustsWhenVisible:
switch frame {
case .nonOverlapping:
return 0.0

case .overlapping(let frame):
return (self.bounds.size.height - frame.origin.y) - self.lst_safeAreaInsets.bottom
}
}
}
}()

if self.collectionView.contentInset.bottom != inset {
self.collectionView.contentInset.bottom = inset
Expand Down

0 comments on commit b15afde

Please sign in to comment.