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

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

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

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

1回答

9361閲覧

UIScrollViewの中のコンテンツ初期表示位置がずれてしまう

u-u

総合スコア7

Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2016/05/15 13:51

編集2016/05/17 17:19

###前提・実現したいこと

Swift初心者です。
iOSでカード表示アプリを作成しています。
1つの画面に2つのScrollViewを配置し、AutoLayoutの設定をしています。
起動してすぐに、ここに表示しているような状態になるようにしたいです。

イメージ説明

###発生している問題・エラーメッセージ

起動時にScrollViewの中のコンテンツの表示位置がずれてしまいます。
デバイス回転時も同様です。
しかしModal画面を開き(タップした時に現れるツールバーを開く)、それを閉じると、正常の位置に表示されます。

異常画面

###該当のソースコード

コードかAutoLayoutの設定かどちらが悪いのかわかっていないので、
プロジェクトを以下に挙げています。
GitHubのプロジェクト

一応ScrollView関連の設定のコードを抜粋します。
settingScrollViewとgenerateViewメソッドで実装しており、
viewWillAppearの中で呼んでいます。

Swift

1 2 //ScrollViewの設定 3 func settingScrollView () { 4 5 print("Setting View Size") 6 7 //Page幅の設定 8 //pageWidth = self.view.frame.size.width 9 pageWidth = upperCardView.frame.size.width + CGFloat(pageMargin) 10 11 //pageHeight 12 pageHeight = upperCardView.frame.size.height + CGFloat(pageMargin) 13 14 //ScrollViewのサイズ設定 15 16 if isPortrait { 17 //Portraitの時 18 upperScrollView.bounds = CGRectMake(0, 0, pageWidth, upperScrollView.frame.height) 19 lowerScrollView.bounds = CGRectMake(0, 0, pageWidth, lowerScrollView.frame.height) 20// upperScrollView.frame.size.width = pageWidth 21// lowerScrollView.frame.size.width = pageWidth 22 upperScrollView.frame = upperScrollView.bounds 23 24 //Bounceの設定 25 upperScrollView.alwaysBounceVertical = false 26 upperScrollView.alwaysBounceHorizontal = true 27 lowerScrollView.alwaysBounceVertical = false 28 lowerScrollView.alwaysBounceHorizontal = true 29 30 } else { 31 //Landscapeの時 32 upperScrollView.bounds = CGRectMake(0, 0, upperScrollView.frame.width, pageHeight) 33 lowerScrollView.bounds = CGRectMake(0, 0, lowerScrollView.frame.width, pageHeight) 34// upperScrollView.frame.size.height = pageHeight 35// lowerScrollView.frame.size.height = pageHeight 36 upperScrollView.frame = upperScrollView.bounds 37 38 //Bounceの設定 39 upperScrollView.alwaysBounceVertical = true 40 upperScrollView.alwaysBounceHorizontal = false 41 lowerScrollView.alwaysBounceVertical = true 42 lowerScrollView.alwaysBounceHorizontal = false 43 44 } 45 46 //はみ出したカードも表示 47 upperScrollView.clipsToBounds = false 48 lowerScrollView.clipsToBounds = false 49 50 } 51 52 //ScrollViewの中のPage生成 53 func generateView () { 54 55 56 //SubViewを削除 57 removeAllSubviews(upperScrollView, jogaiSubView: upperCardView) 58 removeAllSubviews(lowerScrollView, jogaiSubView: lowerCardView) 59 60 61 //コンテンツ量に合わせてScrollViewのサイズを確保 62 if isPortrait { 63 upperScrollView.contentSize = CGSizeMake(pageWidth * CGFloat(upperCardString.count), upperScrollView.frame.height) 64 lowerScrollView.contentSize = CGSizeMake(pageWidth * CGFloat(lowerCardString.count), lowerScrollView.frame.height) 65 } else { 66 upperScrollView.contentSize = CGSizeMake(upperScrollView.frame.width, pageHeight * CGFloat(upperCardString.count) ) 67 lowerScrollView.contentSize = CGSizeMake(lowerScrollView.frame.width, pageHeight * CGFloat(lowerCardString.count)) 68 } 69 70 71 //viewの生成(Upper) 72 print("generate view") 73 74 for i in 0 ..< upperCardString.count { 75 76 //CardViewを複製 77 let genCardView = duplicateCardView(upperCardView, index: i) 78 upperScrollView.addSubview(genCardView) 79 80 //ラベルの裏ビューを複製 81 let genLabelBG = duplicateBGView(upperCVlabelBG) 82 genCardView.addSubview(genLabelBG) 83 84 //ラベルView1を設定 85 let genLabel1 = duplicateLabel(upperCVlabel1) 86 genCardView.addSubview(genLabel1) 87 //ラベルView2を設定 88 let genLabel2 = duplicateLabel(upperCVlabel2) 89 genCardView.addSubview(genLabel2) 90 91 //テキストViewを設定 92 let cardText = duplicateTextView(upperCVtext) 93 genCardView.addSubview(cardText) 94 95 //ラベルとテキストの中身を設定 96 genLabel1.text = upperCardString[i][0] 97 genLabel2.text = upperCardString[i][1] 98 cardText.text = upperCardString[i][2] 99 } 100 101 102 //viewの生成(lower) 103 for i in 0 ..< lowerCardString.count { 104 105 //CardViewを複製 106 let genCardView = duplicateCardView(lowerCardView, index: i) 107 lowerScrollView.addSubview(genCardView) 108 109 //ラベルの裏ビューを複製 110 let genLabelBG = duplicateBGView(lowerCVlabelBG) 111 genCardView.addSubview(genLabelBG) 112 113 //ラベルView1を設定 114 let genLabel1 = duplicateLabel(lowerCVlabel1) 115 genCardView.addSubview(genLabel1) 116 //ラベルView2を設定 117 let genLabel2 = duplicateLabel(lowerCVlabel2) 118 genCardView.addSubview(genLabel2) 119 120 //テキストViewを設定 121 let cardText = duplicateTextView(lowerCVtext) 122 genCardView.addSubview(cardText) 123 124 //ラベルとテキストの中身を設定 125 genLabel1.text = lowerCardString[i][0] 126 genLabel2.text = lowerCardString[i][1] 127 cardText.text = lowerCardString[i][2] 128 129 } 130 131 //最初の表示位置の初期化 132 print("Position Reset") 133 upperScrollView.contentOffset = CGPointMake(0, 0); 134 lowerScrollView.contentOffset = CGPointMake(0, 0); 135 136 } 137

###試したこと
上記のコードを、viewDidAppearの中で呼んでみたり、
UIScrollView.contentOffset = 0
をいろいろな所に入れてみたりしています。
また、AutoLayout使用以前は正しく表示されていました。

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報
XCode7.3.1, Swift, iPhone6で検証しています

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

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

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

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

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

fuzzball

2016/05/17 16:03

回答に書くほどのことではないのでここに書きます。質問後すぐにプロジェクトを見ましたが、制約でエラーが出てますよね?その後、修正されていないのでしたら、まずはエラーを解消してみてはどうでしょうか。
u-u

2016/05/17 17:14

ご指摘ありがとうございます。制約というのはAutoLayoutのConstraintsのことでしょうか。 Missing...は解消できたのですが、Scrollable Content Size Ambiguityのエラーがわからず、しかしScrollView自体の位置は合ってそうなので後回し、というか放置していました。ここが真因なのであれば、質問の表題を変えたほうがよさそうですね・・・。 ここはもしかしてCodeの中で記述しているcontentSizeが効くのではないかと思って、呼ぶタイミングをいろいろ変えてみたりというのはやってみました。StoryBoard上の設定の方に問題があるのでしょうか?
guest

回答1

0

ベストアンサー

起動直後にレイアウトがおかしいのは、Autolayoutによるレイアウトが完了する前に座標などを参照しているせいだと思いますので、例えば、settingScrollView()の呼び出し前にレイアウトを更新すると正しい(かも知れない)レイアウトになります。

swift

1 : 2print("[before]", upperCardView.frame) 3self.view.layoutIfNeeded() //レイアウト更新 4print("[after]", upperCardView.frame) 5 6//Pageの設定 7settingScrollView() 8 :

レイアウト更新の前後でupperCardView.frameが変化しているのが分かると思います。


あと、viewWillLayoutSubviewsとviewDidLayoutSubviewsが呼び出されるタイミングを理解/把握しておきましょう。

swift

1override func viewWillLayoutSubviews() { 2 print("viewWillLayoutSubviews") 3 super.viewWillLayoutSubviews() 4} 5 6override func viewDidLayoutSubviews() { 7 print("viewDidLayoutSubviews") 8 super.viewDidLayoutSubviews() 9}

layoutIfNeeded()でこれらの関数が呼び出されていることが分かります。


もう一つ、ついでに書いておきますが、viewWillAppearやviewDidAppearでは、スーパークラスの呼び出しを行って下さい。

swift

1override func viewWillAppear(animated: Bool) { 2 super.viewWillAppear(animated) 3 : 4} 5 6override func viewDidAppear(animated: Bool) { 7 super.viewDidAppear(animated) 8 : 9}

最初に書いた修正方法は付け焼刃的な対応ですので、もう少しレイアウトについての理解を深めた後で、より良い修正を行うことをお勧めします。
また、Storyboard上での制約(Constraint)のエラーも取り除いた方が良いと思います。Has ambiguous scrollable content xxxはググれば解決方法は見つかるでしょう。

投稿2016/05/18 00:52

fuzzball

総合スコア16731

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

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

u-u

2016/05/18 15:26

ご丁寧な回答ありがとうございます。 self.view.layoutIfNeeded() の前後でupperCardView.frameが変化していること、確認できました。 また、起動時のレイアウトについてはViewDidAppearのところでレイアウト更新&settingScrollViewを呼び出すことで正しい初期位置になることを確認できました。 ただ、ご指摘の通り付け焼き刃の対応になっているようで、回転すると乱れたりします。 今回教えていただいたことを手掛かりに、他の不具合への対処、より良い修正を検討します。 Has ambiguous scrollable content・・についても早速それらしきものが幾つか見つかりました。なぜこれを自分で検索かけなかったのか、我ながら不思議ですが・・。 考えられるところを適当にいじっていてわけがわからなくなっていたのですが、道筋が見えて大変助かりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問