Кажется, что клавиатура не должна занимать весь экран, проверьте ОБНОВЛЕНИЕ в разделе вопросов моего сообщения. Спасибо.

Описание

Используйте UITextField, чтобы разместить на экране полноэкранную клавиатуру.

Справка

Я установил UISplitViewController и хотел бы, чтобы RootViewController (он же MasterViewController) имел UITextField с отображаемой клавиатурой. Тогда хотелось бы, чтобы результаты поиска были справа (в «ResultViewController» (UIViewController).

Идея в том, что когда пользователь вводит, предлагаются результаты.

Что я пробовал:

Сначала я добавил UITextField в свой RootViewController с помощью storyboard, но он занял весь экран, когда я активировал клавиатуру с помощью textField.becomeFirstResponder().

Я подумал, что если я использую 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. Клавиатура находится сверху и занимает всю ширину. Дно разделено на две части. Слева предлагаемые результаты слов, а справа - коллекция обложек возможных видеороликов. Все обновляется по мере ввода пользователя.

Если это считается плохим дизайном для Apple TV, не стесняйтесь указывать, почему.

Снимок экрана:

Это то, что я сейчас получаю. Текстовое поле открывает клавиатуру, занимающую весь экран.

enter image description here

14
kemicofa ghost 22 Апр 2016 в 17:52

3 ответа

Лучший ответ

Введение:

Наконец-то я смог реализовать это без использования TVML templates. Окончательное решение выглядит примерно так:

text keyboard and results on one view

Общая идея состоит в том, чтобы создать UICollectionViewController с UICollectionViewCell. Затем программно добавить клавиатуру и добавить ее к вашему TabViewController через AppDelegate.


Как реализовать это представление поиска с результатами:

Шаг 1. Создание раскадровки и контроллера

Откройте раскадровку и создайте UICollectionViewController (с настраиваемым классом "SearchResultViewController"), который не прикреплен к вашему TabViewController.

В нем создайте свой UICollectionViewCell с любыми labels и images, которые вы хотите. UICollectionViewCell должен иметь собственный класс под названием "VideoSearchCell".

В вашем 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 и StringSearchService. Это просто классы, которые я использую для фильтрации своего списка видео (также известного как 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

4
kemicofa ghost 9 Май 2016 в 11:33

Отображение клавиатуры только на части экрана невозможно с помощью встроенных методов SDK.

UIKeyboard отображается в окне приложения, а не в его подпредставлениях. Чтобы добиться желаемого поведения, используйте отражение, чтобы получить ссылку на объект UIKeyboard в UIWindow вашего приложения (путем итерации по вложенным представлениям окна), и измените его фрейм, чтобы он соответствовал ширине вашего {{X3 }}.

Для начала вы можете посмотреть частный заголовок tvOS UIKeyboard.h здесь. Я должен отметить, что Apple может иметь код для отключения изменения размера клавиатуры (например, в willMoveToWindow: или didMoveToWindow). Это неопределенное поведение, и ваш пробег будет отличаться, если он вообще работает.

Вы удалили свой комментарий к моему ответу о приложении Netflix, но, как говорится в ответе Shirefriends, Netflix, вероятно, использует шаблон TVML. Вы можете пойти по этому пути и создать гибридное приложение tvOS / TVML. Кроме того, вы также можете вручную собрать клавиатуру с помощью UICollectionView в своем RootViewController.

6
JAL 25 Апр 2016 в 14:48

Netflix использует шаблоны TVML для реализации своего поиска вместо UIKit. Вы можете добиться того же эстетического эффекта, что и Netflix, используя searchTemplate. Вы можете научиться смешивать TVML и UIKit здесь . К сожалению, searchTemplate недостаточно настраивается, чтобы соответствовать желаемому макету. В настоящее время нет возможности реализовать ваш конкретный макет для Apple TV.

4
Community 23 Май 2017 в 10:31