UITextField 的键盘是否必须占据整个屏幕?
Does the keyboard for a UITextField have to take up the whole screen?
看来键盘不必占据整个屏幕,请查看我post的问题部分中的更新。谢谢
描述
Use UITextField to place a full-screen keyboard on the screen.
我已经设置了 UISplitViewController
,我希望 RootViewController
(又名 MasterViewController
)显示 UITextField
和键盘。然后我想要右边的搜索结果(在 "ResultViewController" (UIViewController).
想法是当用户输入时,建议结果。
我尝试过的:
我首先通过 storyboard
向我的 RootViewController
添加了一个 UITextField
,但是当我通过 textField.becomeFirstResponder()
.[=25 激活键盘时它占据了整个屏幕=]
我想如果我使用 UIAlertController
我会解决这个问题,但键盘仍然占据了整个屏幕。
class RootViewController: UIViewController {
override func viewDidLoad() {
let alertController = UIAlertController(title: "Search", message: "Search for something!.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = "Search"
})
self.addChildViewController(alertController)
alertController.view.frame = self.view.frame
self.view.addSubview(alertController.view)
}
}
问题:
使用 UISplitViewController
时,如何让键盘只停留在 RootViewController
中而不占据整个屏幕?
更新: 看来这已经在新苹果电视上的 Netflix 应用程序中实现了。键盘在顶部,占据了整个宽度。底部分为两部分。左边是建议的单词结果,右边是可能视频的视频封面集合视图。一切都随着用户输入而更新。
如果这被认为是 Apple TV 的糟糕设计,请随时指出原因。
屏幕截图:
这是我目前得到的。文本框打开一个占满整个屏幕的键盘。
使用 built-in SDK 方法无法仅在屏幕的一部分显示键盘。
A UIKeyboard
显示在应用程序的 window 上,而不显示在其任何子视图上。要完成您想要的行为,请使用反射在应用程序的 UIWindow
上获取对 UIKeyboard
object 的引用(通过遍历 window 的子视图),并更改其框架以匹配 RootViewController
.
的宽度
入门可以看私有UIKeyboard.h tvOS header here。我应该注意到 Apple 可能有适当的代码来禁用调整键盘大小(例如 willMoveToWindow:
或 didMoveToWindow
)。这是未定义的行为,你的里程数会有所不同,如果它能起作用的话。
你已经删除了对我关于 Netflix 应用程序的回答的评论,但正如 shirefriendship 在他们的回答中所说,Netflix 可能使用了 TVML 模板。您可以走那条路并构建一个混合 tvOS/TVML 应用程序。此外,您还可以在 RootViewController
.
中使用 UICollectionView
手动构建键盘
Netflix 正在使用 TVML 模板而不是 UIKit 来实现他们的搜索。您可以使用 searchTemplate. You can learn to mix TVML and UIKit 实现与 Netflix 相同的美学效果。不幸的是,searchTemplate 的可定制性不足以符合您想要的布局。目前无法为 Apple TV 实施您的特定布局。
简介:
我终于能够在不使用 TVML templates
的情况下实现它。最终解决方案如下所示:
总体思路是创建一个 UICollectionViewController
和一个 UICollectionViewCell
。然后以编程方式添加键盘并通过 AppDelegate
将其添加到 TabViewController
。
如何使用结果实现此搜索视图:
第 1 步:故事板和控制器创建
打开您的故事板并创建一个 UICollectionViewController
(带有自定义 class“SearchResultViewController
”),没有附加到您的TabViewController
.
在其中创建一个 UICollectionViewCell
,其中包含您想要的任何 labels
和 images
。 UICollectionViewCell
应该有一个名为“VideoSearchCell
”的自定义 class。
你的 SearchViewController 里面应该没有其他东西。
第 2 步:将 SearchViewController
添加到 TabViewController
并通过 AppDelegate
以编程方式实现键盘
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
override init() {
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if let tabController = window?.rootViewController as? UITabBarController {
tabController.viewControllers?.append(configueSearchController())
}
return true
}
//... standard code in-between
func configueSearchController() -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let searchResultController = storyboard.instantiateViewControllerWithIdentifier(SearchResultViewController.storyboardIdentifier) as? SearchResultViewController else {
fatalError("Unable to instatiate a SearchResultViewController from the storyboard.")
}
/*
Create a UISearchController, passing the `searchResultsController` to
use to display search results.
*/
let searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.searchBar.placeholder = NSLocalizedString("Enter keyword (e.g. Gastric Bypass)", comment: "")
// Contain the `UISearchController` in a `UISearchContainerViewController`.
let searchContainer = UISearchContainerViewController(searchController: searchController)
searchContainer.title = NSLocalizedString("Search", comment: "")
// Finally contain the `UISearchContainerViewController` in a `UINavigationController`.
let searchNavigationController = UINavigationController(rootViewController: searchContainer)
return searchNavigationController
}
}
添加 SearchResultViewController 的基本框架后,您应该能够在 运行 项目时看到搜索视图顶部的键盘。
第 3 步:处理文本输入和更新结果
您会注意到,在我的 filterString
中,我使用了一个名为 ScoreVideo 的 class 和一个 StringSearchService。这些只是我用来过滤视频列表的 classes(又名:self.vms.videos)。
所以最后,只需使用 filterString
,创建一个新的 过滤列表 并重新加载您的集合视图。
import UIKit
import Foundation
class SearchResultViewController: UICollectionViewController, UISearchResultsUpdating {
//private let cellComposer = DataItemCellComposer()
private var vms: VideoManagerService!
private var filteredVideos = [ScoreVideo]()
static let storyboardIdentifier = "SearchResultViewController"
var filterString = "" {
didSet {
// Return if the filter string hasn't changed.
guard filterString != oldValue else { return }
// Apply the filter or show all items if the filter string is empty.
if self.filterString.isEmpty {
self.filteredVideos = StringSearchService.start(self.filterString, videos: self.vms.videos)
}
else {
self.filteredVideos = StringSearchService.start(self.filterString, videos: self.vms.videos)
}
self.collectionView?.reloadData()
}
}
override func viewDidLoad() {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
self.vms = appDelegate.getVideoManagerService()
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("count..\(filteredVideos.count)")
return filteredVideos.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// Dequeue a cell from the collection view.
return collectionView.dequeueReusableCellWithReuseIdentifier(VideoSearchCell.reuseIdentifier, forIndexPath: indexPath)
}
// MARK: UICollectionViewDelegate
override func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = cell as? VideoSearchCell else { fatalError("Expected to display a `VideoSearchCell`.") }
let item = filteredVideos[indexPath.row]
cell.configureCell(item.video)
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
dismissViewControllerAnimated(true, completion: nil)
}
// MARK: UISearchResultsUpdating
func updateSearchResultsForSearchController(searchController: UISearchController) {
print("updating... \(searchController.searchBar.text)")
filterString = searchController.searchBar.text!.lowercaseString ?? ""
}
}
如有不明之处,欢迎随时提问。我很可能忘记了什么。谢谢
答案灵感来自 apple sample code
看来键盘不必占据整个屏幕,请查看我post的问题部分中的更新。谢谢
描述
Use UITextField to place a full-screen keyboard on the screen.
我已经设置了 UISplitViewController
,我希望 RootViewController
(又名 MasterViewController
)显示 UITextField
和键盘。然后我想要右边的搜索结果(在 "ResultViewController" (UIViewController).
想法是当用户输入时,建议结果。
我尝试过的:
我首先通过 storyboard
向我的 RootViewController
添加了一个 UITextField
,但是当我通过 textField.becomeFirstResponder()
.[=25 激活键盘时它占据了整个屏幕=]
我想如果我使用 UIAlertController
我会解决这个问题,但键盘仍然占据了整个屏幕。
class RootViewController: UIViewController {
override func viewDidLoad() {
let alertController = UIAlertController(title: "Search", message: "Search for something!.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = "Search"
})
self.addChildViewController(alertController)
alertController.view.frame = self.view.frame
self.view.addSubview(alertController.view)
}
}
问题:
使用 UISplitViewController
时,如何让键盘只停留在 RootViewController
中而不占据整个屏幕?
更新: 看来这已经在新苹果电视上的 Netflix 应用程序中实现了。键盘在顶部,占据了整个宽度。底部分为两部分。左边是建议的单词结果,右边是可能视频的视频封面集合视图。一切都随着用户输入而更新。
如果这被认为是 Apple TV 的糟糕设计,请随时指出原因。
屏幕截图:
这是我目前得到的。文本框打开一个占满整个屏幕的键盘。
使用 built-in SDK 方法无法仅在屏幕的一部分显示键盘。
A UIKeyboard
显示在应用程序的 window 上,而不显示在其任何子视图上。要完成您想要的行为,请使用反射在应用程序的 UIWindow
上获取对 UIKeyboard
object 的引用(通过遍历 window 的子视图),并更改其框架以匹配 RootViewController
.
入门可以看私有UIKeyboard.h tvOS header here。我应该注意到 Apple 可能有适当的代码来禁用调整键盘大小(例如 willMoveToWindow:
或 didMoveToWindow
)。这是未定义的行为,你的里程数会有所不同,如果它能起作用的话。
你已经删除了对我关于 Netflix 应用程序的回答的评论,但正如 shirefriendship 在他们的回答中所说,Netflix 可能使用了 TVML 模板。您可以走那条路并构建一个混合 tvOS/TVML 应用程序。此外,您还可以在 RootViewController
.
UICollectionView
手动构建键盘
Netflix 正在使用 TVML 模板而不是 UIKit 来实现他们的搜索。您可以使用 searchTemplate. You can learn to mix TVML and UIKit
简介:
我终于能够在不使用 TVML templates
的情况下实现它。最终解决方案如下所示:
总体思路是创建一个 UICollectionViewController
和一个 UICollectionViewCell
。然后以编程方式添加键盘并通过 AppDelegate
将其添加到 TabViewController
。
如何使用结果实现此搜索视图:
第 1 步:故事板和控制器创建
打开您的故事板并创建一个 UICollectionViewController
(带有自定义 class“SearchResultViewController
”),没有附加到您的TabViewController
.
在其中创建一个 UICollectionViewCell
,其中包含您想要的任何 labels
和 images
。 UICollectionViewCell
应该有一个名为“VideoSearchCell
”的自定义 class。
你的 SearchViewController 里面应该没有其他东西。
第 2 步:将 SearchViewController
添加到 TabViewController
并通过 AppDelegate
以编程方式实现键盘
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
override init() {
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if let tabController = window?.rootViewController as? UITabBarController {
tabController.viewControllers?.append(configueSearchController())
}
return true
}
//... standard code in-between
func configueSearchController() -> UIViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let searchResultController = storyboard.instantiateViewControllerWithIdentifier(SearchResultViewController.storyboardIdentifier) as? SearchResultViewController else {
fatalError("Unable to instatiate a SearchResultViewController from the storyboard.")
}
/*
Create a UISearchController, passing the `searchResultsController` to
use to display search results.
*/
let searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.searchBar.placeholder = NSLocalizedString("Enter keyword (e.g. Gastric Bypass)", comment: "")
// Contain the `UISearchController` in a `UISearchContainerViewController`.
let searchContainer = UISearchContainerViewController(searchController: searchController)
searchContainer.title = NSLocalizedString("Search", comment: "")
// Finally contain the `UISearchContainerViewController` in a `UINavigationController`.
let searchNavigationController = UINavigationController(rootViewController: searchContainer)
return searchNavigationController
}
}
添加 SearchResultViewController 的基本框架后,您应该能够在 运行 项目时看到搜索视图顶部的键盘。
第 3 步:处理文本输入和更新结果
您会注意到,在我的 filterString
中,我使用了一个名为 ScoreVideo 的 class 和一个 StringSearchService。这些只是我用来过滤视频列表的 classes(又名:self.vms.videos)。
所以最后,只需使用 filterString
,创建一个新的 过滤列表 并重新加载您的集合视图。
import UIKit
import Foundation
class SearchResultViewController: UICollectionViewController, UISearchResultsUpdating {
//private let cellComposer = DataItemCellComposer()
private var vms: VideoManagerService!
private var filteredVideos = [ScoreVideo]()
static let storyboardIdentifier = "SearchResultViewController"
var filterString = "" {
didSet {
// Return if the filter string hasn't changed.
guard filterString != oldValue else { return }
// Apply the filter or show all items if the filter string is empty.
if self.filterString.isEmpty {
self.filteredVideos = StringSearchService.start(self.filterString, videos: self.vms.videos)
}
else {
self.filteredVideos = StringSearchService.start(self.filterString, videos: self.vms.videos)
}
self.collectionView?.reloadData()
}
}
override func viewDidLoad() {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
self.vms = appDelegate.getVideoManagerService()
}
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("count..\(filteredVideos.count)")
return filteredVideos.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// Dequeue a cell from the collection view.
return collectionView.dequeueReusableCellWithReuseIdentifier(VideoSearchCell.reuseIdentifier, forIndexPath: indexPath)
}
// MARK: UICollectionViewDelegate
override func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = cell as? VideoSearchCell else { fatalError("Expected to display a `VideoSearchCell`.") }
let item = filteredVideos[indexPath.row]
cell.configureCell(item.video)
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
dismissViewControllerAnimated(true, completion: nil)
}
// MARK: UISearchResultsUpdating
func updateSearchResultsForSearchController(searchController: UISearchController) {
print("updating... \(searchController.searchBar.text)")
filterString = searchController.searchBar.text!.lowercaseString ?? ""
}
}
如有不明之处,欢迎随时提问。我很可能忘记了什么。谢谢
答案灵感来自 apple sample code