質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

948閲覧

collectionViewCell上のボタンをタップした際のpopoverの表示場所をcellスクロールさせた場所に調整したい。

退会済みユーザー

退会済みユーザー

総合スコア0

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/09/13 16:52

編集2018/09/14 02:56

いつもお世話になります。

collectionViewCell上のボタンをタップした際に、セルの背景色を変更して、セルをcollectionViewの中央に移動させてから、移動後のボタンに対してpopoverを表示したいのですが、移動前のボタンの位置に対してpopoverが表示されてしまいます。
表示位置を調整する方法はないでしょうか?

イメージ説明

セルを中央に移動させなければ、タップしたボタンの位置にpopoverを表示させることはできています。

イメージ説明

ストーリーボード

ストーリーボード

コード全文記載しますが、関連処理をなるべく上の方に記載してあります。

swift

1import UIKit 2class ViewController: UIViewController, UIPopoverPresentationControllerDelegate { 3 4 @IBOutlet weak var legendsCollectionView: UICollectionView! 5 let legendsArray = ["ブシニャン", "しゅらコマ", "イケメン犬", "花さか爺", "山吹鬼", "ネタバレリーナ", "うんちく魔", "やまタン"] 6 var selectedCellIndex: IndexPath? 7 8 // セル上のボタンがタップされた場合の処理 9 @IBAction func cellBtnTapped(_ sender: UIButton) { 10 11 // タップされたcellのインデックスパスを取得する 12 guard let indexPath = legendsCollectionView.indexPath( 13 for: sender.superview!.superview as! UICollectionViewCell) else { return } 14 15 // リロードしない場合のセルの背景処理 16 /* 17 // 以前に選択されたセルがある場合は背景を白にする 18 if let selectedCellIndex = selectedCellIndex { 19 let selectedCell = legendsCollectionView.cellForItem(at: selectedCellIndex) 20 selectedCell?.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 21 } 22 // 選択されたセルの背景をグレーにする 23 let selectCell = legendsCollectionView.cellForItem(at: indexPath) 24 selectCell?.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1) 25 */ 26 27 selectedCellIndex = indexPath 28 legendsCollectionView.reloadData() 29 moveCellCenter() 30 31 /* 32 ここでcellタップされたセルの最新の情報を取得して、sourceView/sourceRectに渡す? 33 let targetCell = legendsCollectionView.cellForItem(at: selectedCellIndex!)?.frame 34 */ 35 36 let popVC = self.storyboard?.instantiateViewController(withIdentifier: "popover") as! PopViewController 37 38 popVC.modalPresentationStyle = .popover 39 popVC.preferredContentSize = CGSize(width: 150, height: 70) 40 41 if let presentationController = popVC.popoverPresentationController { 42 presentationController.permittedArrowDirections = .up 43 // ↓ここで、座標を変換(collectionView系からviewController?)したUIButtonを渡す? 44 // CGRectなど座標だけならイメージできるが、変換した座標を含むViewをまるごと?渡す? 45 presentationController.sourceView = sender 46 // ↑ presentationController.sourceView.frame = ほにゃららを受け付ける?? 47 presentationController.sourceRect = sender.bounds 48 presentationController.delegate = self 49 } 50 present(popVC, animated: true, completion: nil) 51 } 52 53 func adaptivePresentationStyle( 54 for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { 55 return .none 56 } 57 58 // 選択されたセルを中央に移動する 59 func moveCellCenter() { 60 legendsCollectionView.selectItem( 61 at: selectedCellIndex, animated: true, scrollPosition: .centeredHorizontally) 62 } 63 64 // unwindSegue時に実行 65 @IBAction func unwindBtn01Tapped(segue: UIStoryboardSegue) { 66 printCellLabel() 67 } 68 69 @IBAction func unwindBtn02Tapped(segue: UIStoryboardSegue) { 70 printCellLabel() 71 } 72 73 func printCellLabel() { 74 if let index = selectedCellIndex { 75 let labelText = legendsArray[index.row] 76 print(labelText) 77 } 78 } 79} 80 81 82extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource { 83 84 // numOfCell 85 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 86 return legendsArray.count 87 } 88 // generateCell 89 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 90 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CCell 91 92 let nameStr = legendsArray[indexPath.item] 93 94 if selectedCellIndex == indexPath { 95 cell.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1) 96 } else { 97 cell.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 98 } 99 100 cell.setCell(name: nameStr) 101 return cell 102 } 103 // selectCell 104 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 105 selectedCellIndex = indexPath 106 legendsCollectionView.reloadData() 107 moveCellCenter() 108 } 109 110 //MARK: - LifeCycle 111 override func viewDidLoad() { 112 super.viewDidLoad() 113 // Do any additional setup after loading the view, typically from a nib. 114 } 115 116 override func didReceiveMemoryWarning() { 117 super.didReceiveMemoryWarning() 118 // Dispose of any resources that can be recreated. 119 } 120} 121

念の為、popViewControllerも、

swift

1import UIKit 2 3class PopViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 8 // Do any additional setup after loading the view. 9 } 10 11 override func didReceiveMemoryWarning() { 12 super.didReceiveMemoryWarning() 13 // Dispose of any resources that can be recreated. 14 } 15}

備忘録/回答でご指摘いただき直した部分

swift

1// セル上のボタンがタップされた場合の処理 2 @IBAction func cellBtnTapped(_ sender: UIButton) { 3 4 // タップされたUIButtonからインデックスパスを取得する 5 let point = legendsCollectionView.convert(sender.center, from: sender) 6 guard let indexPath = legendsCollectionView.indexPathForItem(at: point) else { return } 7 8 // リロードするとおかしくなるので禁じ手 9 // legendsCollectionView.reloadData() 10 11 // リロードしない場合のセルの背景処理 12 // 以前に選択されたセルがある場合は背景を白にする 13 if let selectedCellIndex = selectedCellIndex { 14 let selectedCell = legendsCollectionView.cellForItem(at: selectedCellIndex) 15 selectedCell?.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 16 } 17 // 選択されたセルの背景をグレーにする 18 let selectCell = legendsCollectionView.cellForItem(at: indexPath) 19 selectCell?.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1) 20 21 // 選択されたセルのindexPathを保存する 22 selectedCellIndex = indexPath 23 24 // prepare PopoverView 25 let popVC = self.storyboard?.instantiateViewController(withIdentifier: "popover") as! PopViewController 26 27 popVC.modalPresentationStyle = .popover 28 popVC.preferredContentSize = CGSize(width: 150, height: 70) 29 30 if let presentationController = popVC.popoverPresentationController { 31 presentationController.permittedArrowDirections = .up 32 presentationController.sourceView = sender 33 presentationController.sourceRect = sender.bounds 34 presentationController.delegate = self 35 } 36 37 UIView.animate(withDuration: 0.4, animations: { 38 self.moveCellCenter(animation: false) 39 }) { (finished) in 40 self.present(popVC, animated: true, completion: nil) 41 } 42 } 43 44 // 選択されたセルを中央に移動する 45 func moveCellCenter(animation: Bool) { 46 legendsCollectionView.selectItem( 47 at: selectedCellIndex, animated: animation, scrollPosition: .centeredHorizontally) 48 }

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

自前でアニメーションさせて終了を検知します。
期待した動きになるかどうか?

アニメーションに関しては調整して下さい。

swift

1func moveCellCenter() { 2 UIView.animate(withDuration: 0.5, animations: { 3 self.legendsCollectionView.selectItem(at: self.selectedCellIndex, animated: false, scrollPosition: .centeredHorizontally) 4 }) { (finished) in 5 //アニメーション終了 6 //ここでポップアップ表示 7 } 8}

投稿2018/09/14 00:49

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/09/14 02:29

なるほど、非同期的な動きが問題だと気づきませんでした。 期待したとおりの動きになりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問