2013-03-07 10 views
5

私はGLKitベースのアプリをいくつかの単純なオブジェクトで表示しています。GLKitの-drawRect:画面の回転中に呼び出されない

GLKViewが更新されていない(-drawRect:が呼び出されていない)画面回転を除くすべてが問題なく動作します。したがって、回転投影中に、動的に変化する画面サイズに応じてマトリックスが更新されず、オブジェクトがひどく見えます(伸びます)。

+0

シェイダーまたはGLKBaseEffectを使用していますか? –

+0

'GLKBaseEffect'と私自身のシェーダの両方を試しました - 同じ結果です。 '-drawRect:'はアニメーションが終了した後に呼び出されるので、通常はそこに置かれているGLレンダリングはその瞬間に中断されます。 – kpower

+1

私は、GLKBaseEffectのprojectionMatrixプロパティがバグだったと考えていました。私は思うようになるでしょう... –

答えて

1

これは、単純にUIKitアニメーションの仕組みではありません。それの半分はthis answerにどのように動作するか私はソートの説明が、私は、関連するビットを要約してみましょう:

  • すべてがテクスチャの長方形です。 (おそらくCAShapeLayerのようないくつかの例外がありますが、これはほとんどの場合当てはまります)
  • UIViewのプロパティはCALayerの「モデルツリー」プロパティにリンクされています。彼らはを瞬時に変更します
  • アニメーションは、「プレゼンテーションツリー」プロパティを開始値から現在のモデル値にアニメートすることによって機能します。
  • アニメーションの開始値は、デフォルトでは以前のモデル値です。 UIViewAnimationOptionBeginFromCurrentStateを指定すると、現在のプレゼンテーション値が使用されます。

があり、当然のことながら、いくつかの例外(CAShapeLayerは、UIViewの遷移が...全く別のものですUIScrollViewはタイマーでアニメーションをスクロールん、テクスチャーRECT以上のもののようです)。

回転がなっでどのように動作するようにあなたは、単一の-setFrame:は、すべてがレイアウト(および潜在的に再レン​​ダリング)されて取得し、その後、アニメーション可能な特性がアニメ化されていることです。デフォルトでは、これは新しいディメンションに再レンダリングすることを意味しますが、古いディメンションに合わせて伸ばしてから、回転が進行するとアニメーション(および伸縮)します。

つまり、GLKViewは異なる方法で動作する可能性があります。GLKViewControllerを使用している場合は、回転アニメーション中にレンダリングを中断することさえあります。回転中に-setNeedsDisplayを呼び出してみることもできますが、フレームが既に最終値に設定されているため、あまり役に立ちません。

回転アニメーションを自分で処理する最も簡単な方法は、アニメーションではない再レイアウトを回転したフレームに強制してから、レンダラーでいくつかのフージングを行うことです(黒い枠線とステータスバーは別々にアニメーション化されます)。

また、従来の方法ではVCのポートレートのみを作成し、デバイスの方向通知を自分で処理することもできますが、これは大きな脅威になります(ステータスバーの向きが心配な場合は、他のVCとの間でやりとりするときに「興味深いことに」相互作用する傾向があります)。

0

まず、アプリケーションライフサイクルの早い段階でデバイスの向きを変更できるようにしてください。

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 

次に、ビューがインスタンス化されると、そのような通知を登録します。

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil]; 

は、その後、あなたのビューコントローラで-deviceOrientationDidChange:を実装し、私はGLKitの経験を持っていないので、これは暗闇の中でショットかもしれない-setNeedsDisplay

+0

方向変更が起こった後、 ' - ... DidChange'が呼び出されます。そして今度は 'drawRect:'も呼び出されます(私は行列を各フレームの時間変化と時間変化で更新します)。しかし、私はこのプロセス中に変更を適用する必要があります。 – kpower

+0

私は今参照してください。私はあなたが回転情報を全く得ていないと言っていましたが。 View Controllerメソッド ' - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration'をリッスンして実装します。この時間は、トランジション中にアニメーションを計算するのに役立ちます。 –

+1

はい、わかっています。また、私はビューの '-setFrame:'を再実装することもでき、それぞれのアニメーションステップごとにビューのサイズを変更します。しかし、私はこの変更に対応することはできません。投影行列を更新することはできますが、アニメーションが終了するまで、 '-drawRect:'(対応するGL描画)を呼び出すことができないため、更新は適用されません。 – kpower

6

を呼び出して、しかし私はUIView-drawRect:の経験を持っています。再描画するために、問題のビューのcontentModeを変更してみてください:

view.contentMode = UIViewContentModeRedraw;

これは、それはそれは境界の変更だとき内容だ再描画する必要があるとの見解を教えてくれます。それ以外の場合、UIViewはコンテンツの縮尺を試みます(contentModeのデフォルトはUIViewContentModeScaleToFillです)。その理由は、コンテンツを再描画するよりも、そこにあるものを拡大するのがずっと簡単で、UIViewはできるだけ効率的になるように設計されているからです。

+0

残念ながら、これはGLKViewで実際に何の違いもないようです。 – pmdj

関連する問題