web-dev-qa-db-ja.com

UISearchControllerのカスタムアニメーション?

ナビゲーションコントローラーに埋め込まれたコントローラーからのUISearchControllerを提示しています。デフォルトのアニメーションが発生し、検索ボックスがナビゲーションバーの上からドロップダウンします。

ユーザーが画面の中央でUITextFieldをタップしたときに検索を表示するため、これは私の場合は適切なUXではありません。私がやりたいのは、UITextFieldを一番上にフロートさせて検索ボックスに変形させることですが、これを行う方法がわかりません。

これは私が持っているものです:

class PlacesSearchController: UISearchController, UISearchBarDelegate {

    convenience init(delegate: PlacesAutocompleteViewControllerDelegate) {

        let tableViewController = PlacesAutocompleteContainer(
            delegate: delegate
        )

        self.init(searchResultsController: tableViewController)

        self.searchResultsUpdater = tableViewController
        self.hidesNavigationBarDuringPresentation = false
        self.definesPresentationContext = true
        self.searchBar.placeholder = searchBarPlaceholder
    }
}

private extension ShowAddressViewController {

    @objc func streetAddressTextFieldEditingDidBegin() {
        present(placesSearchController, animated: true, completion: nil)
    }
}

検索を上からドロップダウンする代わりに、テキストフィールドをナビゲーションバーまで飛ばしたいと思っています。私が求めているのは、iOS11ファイルアプリと同じ効果です。

画面の中央にテキストフィールドがあり、タップするとナビゲーションバーまでアニメーション化されます。私の場合、テキストフィールドは画面のずっと下にあり、元々はナビゲーションバーの一部ではありません。

12
TruMan1

UISearchController

UISearchControllerは、カスタマイズが非常に難しいコンポーネントです。私の経験から言えば、大幅なカスタマイズや大幅なカスタマイズを行わずに、そのまま使用する方がよいと言えます。そうしないと、カスタマイズによってコードが乱雑になり、グローバル状態変数、UIView階層を使用したランタイムトリックなどが発生する可能性があります。特定の動作が引き続き必要な場合は、検索コントローラーを最初から実装するか、サードパーティのものを使用することをお勧めします。

デフォルトの実装

UISearchControllerは、テーブルヘッダービューにインストールされたUITableViewおよびUISearchBarと組み合わせて使用​​するように設計されているようです。 Apple公式のコードサンプルとドキュメントでもそのような使用例が提供されています( ISearchController を参照)。UISearchBarを別の場所にインストールしようとすると、検索バーフレームに多くの醜い副作用が発生することがよくあります。 、位置、けいれんアニメーション、向きの変更など。

IOS 11以降、UINavigationItemは searchController プロパティを取得しました。検索コントローラーをナビゲーションインターフェイスに統合できるため、検索はiOSファイルまたはiOSAppStoreアプリとまったく同じようになります。 UISearchControllerの動作はまだ別のコンポーネントと結合していますが、UITableViewと常に結合するよりも優れていると思います。

可能な解決策

私の見解では、あなたの問題にはいくつかの可能な解決策があります。実装に必要な作業が増える順に提供します。

  1. それでもUISearchControllerを使用する場合は、大幅なカスタマイズを行わずにそのまま使用することを検討してください。 Appleは、UISearchControllerの使用方法を示すサンプルコードを提供します( ISearchControllerを使用したテーブル検索 を参照)。
  2. 多くの追加機能を備えたより柔軟なサードパーティライブラリがいくつかあります。例: YNSearchPYSearch 。ご覧ください。
  3. UISearchControllerプレゼンテーションに加えて、アルファを1から0に変更してUITextFieldを上に移動することもできます。これにより、UITextFieldがUISearchBarにスムーズに変換されているように感じられます。このアプローチは、Chris Slowikによって提供された記事で説明されています(元の投稿へのコメントを参照してください)。私が改善する唯一のことは、遷移コーディネーターを使用したアニメーションです(例 ここ を参照)。これにより、同期されたタイミングでアニメーションがスムーズになります。最終的な実装もはるかにクリーンになります。
  4. オプションとして、UISearchBarのみ、またはプレーンなUITextFieldを使用して、独自の検索コントローラーを設計することもできます。
  5. UISearchControllerをサブクラス化し、UITextFieldオブジェクトを追加できます。 UISearchControllerは、UIViewControllerAnimatedTransitioningおよびUIViewControllerTransitioningDelegateプロトコルに準拠しており、UITextFiledは、遷移アニメーションとともに削除または追加できます。

これがお役に立てば幸いです。

更新:

ポイント3で説明したアプローチを実装しました。その仕組みは次のとおりです。

UISearchController with UITextField

コードスニペットを見つけることができます ここ 。これは単なるコード例であり、処理されない場合があることに注意してください。その後、2回確認してください。

14
Alex D.
  1. XIBで1つのUIViewを作成します。 searchViewという名前を付けます。
  2. 同じxibのUIViewの上にUIButtonを追加し、btnSearchという名前を付けます。以下のように in your scenario you have added textfield which is not mendetary

  3. 以下のように、ViewDidLoadで検索コントローラーをセットアップします。

    func setupSearchController()  {
      self.searchController = UISearchController(searchResultsController: nil)
      self.searchController.delegate = self
      self.searchController.searchBar.delegate = self
      definesPresentationContext = true
      self.searchController.dimsBackgroundDuringPresentation = false
      self.searchController.searchBar.sizeToFit()
      searchView.addSubview(self.searchController.searchBar)
      self.searchController.searchBar.isHidden = true
      self.searchController.searchBar.tintColor = UIColor.white
      self.searchController.searchBar.showsCancelButton = false
      UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = session?.makeColor(fromHexString: TYPE_COLOR, alpha: 1.0)
      self.searchController.searchBar.isTranslucent = false
      self.searchController.searchBar.barTintColor = UIColor(red: 239.0 / 255.0, green: 135.0 / 255.0, blue: 1.0 / 255.0, alpha: 1.0)
    }
    

    このメソッドは、searchview内にプログラムでsearchcontrollerをセットアップします。

  4. これで、searchcontrollerをプログラムで表示する必要があります。手順2でボタンのクリック時メソッドを追加します。以下のメソッド名showsearchAnimationを呼び出します。

    func ShowSeachAnimation() {
      searchFrame = searchView.frame (add one global variable "searchFrame" in controller which saves searchView.frame so it will be used when cancel button clicked on search)
      self.btnSearch.isHidden = true        
      var yAxis : CGFloat = 20
      if #available(iOS 11 , *) {
         yAxis = 8
      } else  {
         yAxis = 20
      }
      searchView.translatesAutoresizingMaskIntoConstraints = true
      searchView.frame = CGRect(x: 0, y: yAxis, width: view.frame.size.width, height: view.frame.size.height - yAxis)
    
      self.searchController.searchBar.isHidden = false
      self.searchController.searchBar.becomeFirstResponder()
      self.searchController.searchBar.showsCancelButton = true
      self.searchBar(self.searchController.searchBar, textDidChange: "")
      searchView.layoutIfNeeded()
    }
    
  5. 検索バーを非表示にするには、searchcontrollerデリゲートに「searchbarcancelbuttonclicked」という名前の検索非表示メソッドを追加します。

    func searchViewHideAnimation()  {
      self.removeNavigationBar()
      self.navigationController?.isNavigationBarHidden = false
      self.searchController.searchBar.text = " "
      self.searchController.searchBar.isHidden = true
      UIView.animate(withDuration: 0.3, animations: {() -> Void in
          self.searchView.frame = self.searchFrame!
          self.btnSearch.isHidden = false
      }, completion: {(_ finished: Bool) -> Void in
          self.searchView.layoutIfNeeded()
      })
    }
    
3
Code Hunterr

私の https://github.com/Blackjacx/SHSearchBar を使用してみることができます。これは基本的にテキストフィールドになります。左、右、上に制約を追加し、テキストフィールドの編集開始時に上部の制約を調整できます。同時に、オーバーレイビューを使用して、アニメーション化されたナビゲーションバーを非表示にし、背景をグレー表示します。このようにして、アニメーションを最大限に制御できます。このアプローチは、聞こえるほど難しくはありません。

2
blackjacx