web-dev-qa-db-ja.com

iOS8-ポップオーバーを移動するUIPopoverPresentationController

新しいuipopoverpresentationcontrollerを使用してポップオーバーを再配置する効果的な方法を探しています。私はポップオーバーをうまく提示しました、そして今、私はそれを却下して再び提示することなくそれを動かしたいと思います。関数の使用に問題があります:

(void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController
      willRepositionPopoverToRect:(inout CGRect *)rect
                           inView:(inout UIView **)view

ゲームの早い段階だとは思いますが、これを効率的に行う方法の例を誰かが持っているので、私と共有していただければ幸いです。前もって感謝します。

20
angerboy

残念ながら、このハッキーな回避策は私が見つけた唯一の解決策です:

[vc.popoverPresentationController setSourceRect:newSourceRect];
[vc setPreferredContentSize:CGRectInset(vc.view.frame, -0.01, 0.0).size];

これにより、表示されるビューのコンテンツサイズが一時的に変更され、ポップオーバーと矢印の位置が変更されます。サイズの一時的な変更は表示されません。

これは問題のようですApple修正する必要があります-sourceViewsourceRectまたはUIPopoverPresentationControllerプロパティを変更しても、すでに表示されている場合は何も起こりませんポップオーバー(この回避策なし)。

これがあなたにもうまくいくことを願っています!

15
Rowan Jones

sourceRectpopoverPresentationControllerを変更した後、containerView?.setNeedsLayout()containerView?.layoutIfNeeded()を使用して運が良かった。

func movePopoverTo(_ newRect: CGRect) {
    let popover = self.presentedViewController as? MyPopoverViewController {
        popover.popoverPresentationController?.sourceRect = newRect
        popover.popoverPresentationController?.containerView?.setNeedsLayout()
        popover.popoverPresentationController?.containerView?.layoutIfNeeded()
    }
}

また、何も変更せずに、ポップオーバーをtableViewセルに従わせることもできます。

class MyTableViewController: UITableViewController {

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "MyPopoverSegue" {
            guard let controller = segue.destination as? MyPopoverViewController else { fatalError("Expected destination controller to be a 'MyPopoverViewController'!") }
            guard let popoverPresentationController = controller.popoverPresentationController else { fatalError("No popoverPresentationController!") }
            guard let rowIndexPath = sender as? IndexPath else { fatalError("Expected sender to be an 'IndexPath'!") }
            guard myData.count > rowIndexPath.row else { fatalError("Index (\(rowIndexPath.row)) Out Of Bounds for array (count: \(myData.count))!") }
            if self.presentedViewController is MyPopoverViewController {
                self.presentedViewController?.dismiss(animated: false)
            }
            popoverPresentationController.sourceView = self.tableView
            popoverPresentationController.sourceRect = self.tableView.rectForRow(at: rowIndexPath)
            popoverPresentationController.passthroughViews = [self.tableView]
            controller.configure(myData[rowIndexPath.row])
        }
        super.prepare(for: segue, sender: sender)
    }
}

// MARK: - UIScrollViewDelegate

extension MyTableViewController {
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if let popover = self.presentedViewController as? MyPopoverViewController {
            popover.popoverPresentationController?.containerView?.setNeedsLayout()
            popover.popoverPresentationController?.containerView?.layoutIfNeeded()
        }
    }
}
6
chown

@Rowan_Jonesによる別の回答で述べたのと同じ方法を使用しましたが、ポップオーバーのサイズを実際に変更したくありませんでした。ポイントの端数でも。 preferredContentSizeを連続して複数回設定できることに気付きましたが、視覚的には、サイズは最後の値に一致するように変更されるだけです。

[vc.popoverPresentationController setSourceRect:newSourceRect];
CGSize finalDesiredSize = CGSizeMake(320, 480);
CGSize tempSize = CGSizeMake(finalDesiredSize.width, finalDesiredSize.height + 1);
[vc setPreferredContentSize:tempSize];
[vc setPreferredContentSize:finalDesiredSize];

したがって、finalDesiredSizeが最初のpreferredContentSizeと同じであっても、サイズが実際には変更されていなくても、ポップオーバーが更新されます。

4
jamone

ポップオーバーを再センタリングする方法の例を次に示します。

- (void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController willRepositionPopoverToRect:(inout CGRect *)rect     inView:(inout UIView **)view {

     *rect = CGRectMake((CGRectGetWidth((*view).bounds)-2)*0.5f,(CGRectGetHeight((*view).bounds)-2)*0.5f, 2, 2);

また、このメソッドを使用して、* rectと* viewを元のsourceRectとsourceViewに設定することにより、移動後にポップオーバーが正しい場所に移動したことを確認しました。

補足として、ポップオーバーのソースがバーボタンアイテムを使用して設定されている場合、このメソッドが呼び出されるとは思いません。

2
turbs

投票やコメントするのに十分なポイントがないので、これを投稿します。 :)@ turbsの答えは私にとって完璧に機能しました。それは受け入れられた答えでなければなりません。

デリゲートメソッドで必要なrectに* rectを設定します。

(void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController
    willRepositionPopoverToRect:(inout CGRect *)rect     
        inView:(inout UIView **)view
1
S. George