私はGLKit
ベースのアプリをいくつかの単純なオブジェクトで表示しています。GLKitの-drawRect:画面の回転中に呼び出されない
GLKView
が更新されていない(-drawRect:
が呼び出されていない)画面回転を除くすべてが問題なく動作します。したがって、回転投影中に、動的に変化する画面サイズに応じてマトリックスが更新されず、オブジェクトがひどく見えます(伸びます)。
私はGLKit
ベースのアプリをいくつかの単純なオブジェクトで表示しています。GLKitの-drawRect:画面の回転中に呼び出されない
GLKView
が更新されていない(-drawRect:
が呼び出されていない)画面回転を除くすべてが問題なく動作します。したがって、回転投影中に、動的に変化する画面サイズに応じてマトリックスが更新されず、オブジェクトがひどく見えます(伸びます)。
これは、単純にUIKitアニメーションの仕組みではありません。それの半分はthis answerにどのように動作するか私はソートの説明が、私は、関連するビットを要約してみましょう:
UIView
のプロパティはCALayerの「モデルツリー」プロパティにリンクされています。彼らはを瞬時に変更します。UIViewAnimationOptionBeginFromCurrentState
を指定すると、現在のプレゼンテーション値が使用されます。があり、当然のことながら、いくつかの例外(CAShapeLayer
は、UIViewの遷移が...全く別のものですUIScrollView
はタイマーでアニメーションをスクロールん、テクスチャーRECT以上のもののようです)。
回転がなっでどのように動作するようにあなたは、単一の-setFrame:
は、すべてがレイアウト(および潜在的に再レンダリング)されて取得し、その後、アニメーション可能な特性がアニメ化されていることです。デフォルトでは、これは新しいディメンションに再レンダリングすることを意味しますが、古いディメンションに合わせて伸ばしてから、回転が進行するとアニメーション(および伸縮)します。
つまり、GLKView
は異なる方法で動作する可能性があります。GLKViewController
を使用している場合は、回転アニメーション中にレンダリングを中断することさえあります。回転中に-setNeedsDisplay
を呼び出してみることもできますが、フレームが既に最終値に設定されているため、あまり役に立ちません。
回転アニメーションを自分で処理する最も簡単な方法は、アニメーションではない再レイアウトを回転したフレームに強制してから、レンダラーでいくつかのフージングを行うことです(黒い枠線とステータスバーは別々にアニメーション化されます)。
また、従来の方法ではVCのポートレートのみを作成し、デバイスの方向通知を自分で処理することもできますが、これは大きな脅威になります(ステータスバーの向きが心配な場合は、他のVCとの間でやりとりするときに「興味深いことに」相互作用する傾向があります)。
まず、アプリケーションライフサイクルの早い段階でデバイスの向きを変更できるようにしてください。
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
次に、ビューがインスタンス化されると、そのような通知を登録します。
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil];
は、その後、あなたのビューコントローラで-deviceOrientationDidChange:
を実装し、私はGLKit
の経験を持っていないので、これは暗闇の中でショットかもしれない-setNeedsDisplay
方向変更が起こった後、 ' - ... DidChange'が呼び出されます。そして今度は 'drawRect:'も呼び出されます(私は行列を各フレームの時間変化と時間変化で更新します)。しかし、私はこのプロセス中に変更を適用する必要があります。 – kpower
私は今参照してください。私はあなたが回転情報を全く得ていないと言っていましたが。 View Controllerメソッド ' - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration'をリッスンして実装します。この時間は、トランジション中にアニメーションを計算するのに役立ちます。 –
はい、わかっています。また、私はビューの '-setFrame:'を再実装することもでき、それぞれのアニメーションステップごとにビューのサイズを変更します。しかし、私はこの変更に対応することはできません。投影行列を更新することはできますが、アニメーションが終了するまで、 '-drawRect:'(対応するGL描画)を呼び出すことができないため、更新は適用されません。 – kpower
を呼び出して、しかし私はUIView
と-drawRect:
の経験を持っています。再描画するために、問題のビューのcontentModeを変更してみてください:
view.contentMode = UIViewContentModeRedraw;
これは、それはそれは境界の変更だとき内容だ再描画する必要があるとの見解を教えてくれます。それ以外の場合、UIView
はコンテンツの縮尺を試みます(contentModeのデフォルトはUIViewContentModeScaleToFill
です)。その理由は、コンテンツを再描画するよりも、そこにあるものを拡大するのがずっと簡単で、UIView
はできるだけ効率的になるように設計されているからです。
残念ながら、これはGLKViewで実際に何の違いもないようです。 – pmdj
シェイダーまたはGLKBaseEffectを使用していますか? –
'GLKBaseEffect'と私自身のシェーダの両方を試しました - 同じ結果です。 '-drawRect:'はアニメーションが終了した後に呼び出されるので、通常はそこに置かれているGLレンダリングはその瞬間に中断されます。 – kpower
私は、GLKBaseEffectのprojectionMatrixプロパティがバグだったと考えていました。私は思うようになるでしょう... –