IOS Swiftサードパーティライブラリなしで、Side Sidebar Menu(Facebookアプリのような)を実装する方法はありますか? Objective-Cに実装された機能。
IOS8で大幅に更新されたUISplitViewControllerフォームを開始できると思います。セッションの監視 iOS8のコントローラーの進歩の表示 および IKitを使用したアダプティブアプリの構築 詳細 2番目のセッションのコード例 を提供します(ただし、最初のセッションは形成しません:/)。この時点で、iOS8のSplit View Controllerに基づいてこの種のUIを作成するのは自然なことです。
更新:彼らが話しているすべてのAPIがまだ上陸していないようです。ビデオで言及されている現在のベータ4では、例えばBarsOnSwipeは表示されません。
Update:この回答ではなく、更新された回答の使用を検討してください。 Scrollview/Container Viewアプローチには、カスタムビューコントローラートランジションを代わりに使用することで回避できる多くのEdgeケースがあります。
ライブラリを必要としないSwiftメニューソリューションを探しました。Fengsonのアプローチとかなり似た、独自のチュートリアルを作成することになりました。
主なポイントは次のとおりです。
scrollview
を作成しますcontainer
内に、2つのscrollview
ビューを並べて配置します。コンテナを使用すると、トップレベルのコントローラーを埋め込むことができます。scrollview
で、paging enabled
を設定しますが、bounces
を無効にします。これにより、スライドアウトが強制的に開いた状態または閉じた状態になりますembed
a UITableViewController
は左のコンテナにありますembed
a UITabBarController
は右のコンテナにありますcontainer
に、0.8のランタイム属性layer.shadowOpacity
を追加します。これにより、コードなしで無料のシャドウセパレーターが提供されます。NSNotificationCenter
を使用して、scrollview
と通信できます。scrollView.setContentOffset.x
を使用して、メニューの実際の開閉を処理します以下に、スクリーンショットと手順を含む、左のスライドアウトメニューを備えたタブバーアプリケーションの実用的なプロジェクト例を示します。
https://github.com/ThornTechPublic/LeftSlideoutMen
それがどのように機能するかについてのより一般的な説明とともに:
http://www.thorntech.com/2015/06/want-to-implement-a-slideout-menu-in-your-Swift-app-heres-how/
IOS7およびiOS8のスライドサイドバーメニュー、Swiftコーディング。
NavigationController levelで必要な場合(背後のすべてのViewコントローラーの場合):
https://github.com/evnaz/ENSwiftSideMen
ただ1つにしたい場合ViewController:
ビデオ: https://www.youtube.com/watch?v=qaLiZgUK2T
ソースコード: http://goo.gl/ULWxJh
この場合、iOS7との互換性のために、次のように、「ぼかしビューを追加」コメントが配置される「if」条件を追加します。
if (NSClassFromString("UIVisualEffectView") != nil) {
// Add blur view
let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
blurView.frame = sideBarContainerView.bounds
sideBarContainerView.addSubview(blurView)
}
カスタムビューコントローラートランジションの使用は、スライドアウトメニューを作成するための堅実なアプローチだと思います。
カスタムView Controllerトランジションは、最初は習得が困難です(少なくとも私にとってはそうでした)。インタラクティブなスライドアウトメニューの作成方法について ブログ投稿 を作成し、できる限り簡単に理解できるように最善を尽くしました。
GitHubのコード に直接ジャンプすることもできます。
非常に高いレベルで、これはどのように機能するかです:
UIViewControllerAnimatedTransitioning
プロトコルを使用してトランジションを閉じます。スナップショットを使用して、アニメーション中にメインビューコントローラーを表します。UIPercentDrivenInteractiveTransition
オブジェクトに配線して、遷移をユーザーの動きと同期させます。UIViewControllerTransitioningDelegate
プロトコルを採用し、すべてのカスタムアニメーションとインタラクティブなトランジションを結び付けます。実際、Scrollview/Container Viewを使用するこのスレッドに関する以前の回答があります。このアプローチはプロトタイプとしては問題ありませんが、アプリのプロダクションを準備する際に多くのEdgeのケースとバグに遭遇します。毎週ブログのコメントに返信し、Edgeのケースを修正することが、このテーマに関する2番目のブログ投稿を書くきっかけになりました。
ここに、ミックスに追加するために作成した別のSideMenuライブラリを示します。 https://github.com/jonkykong/SideMen 。
Swift Facebookに触発されたiOSのシンプルなサイドメニューコントロール。右側と左側。コーディングは不要。
- 1行のコードなしでストーリーボードに実装できます。
- 4つの標準アニメーションスタイルから選択できます(奇妙な場合は視差も)。
- 大量のカスタムコードを記述することなく高度にカスタマイズ可能。
- 1回のジェスチャーで、両側のサイドメニュー間で連続スワイプをサポートします。
- グローバルメニュー構成。一度セットアップすれば、すべての画面で完了します。
- このコントロールはカスタムトランジションを使用するため、メニューは他のView Controllerと同じように表示および非表示にできます。
ここに私がそれを行う方法の小さな例を示します。この引き出しコントロールには、左、中央、右のuiviewcontrollersがあります。これは、どちらか一方が開いているSlack IPadアプリのように機能します。
/*
To use simply instantiate SlidingDrawerController as your root view in your AppDelegate, or in the
StoryBoard.
Once SlidingDrawerController is instantiated, set the drawerSize of the SlidingDrawerController,
and its leftViewControllerIdentifier, centerViewControllerIdentifier, and
rightViewControllerIdentifier to the Storyboard Identifier of the UIViewController
you want in the different locations.
*/
class SlidingDrawerController: UIViewController {
var drawerSize:CGFloat = 4.0
var leftViewControllerIdentifier:String = "leftViewController"
var centerViewControllerIdentifier:String = "centerViewController"
var rightViewControllerIdentifier:String = "rightViewController"
enum Drawers {
case left
case right
}
private var _leftViewController:UIViewController?
var leftViewController:UIViewController {
get{
if let vc = _leftViewController {
return vc;
}
return UIViewController();
}
}
private var _centerViewController:UIViewController?
var centerViewController:UIViewController {
get{
if let vc = _centerViewController {
return vc;
}
return UIViewController();
}
}
private var _rightViewController:UIViewController?
var rightViewController:UIViewController {
get{
if let vc = _rightViewController {
return vc;
}
return UIViewController();
}
}
static let SlidingDrawerOpenLeft = 1
static let SlidingDrawerOpenRight = 2
var openSide:SlidingDrawerController.Drawers {
get{
return _openSide;
}
}
private var _openSide = SlidingDrawerController.Drawers.left
override func viewDidLoad() {
super.viewDidLoad()
// Instantiate VC's with storyboard ID's
self._leftViewController = self.instantiateViewControllers(storyboardID: self.leftViewControllerIdentifier)
self._centerViewController = self.instantiateViewControllers(storyboardID: self.centerViewControllerIdentifier)
self._rightViewController = self.instantiateViewControllers(storyboardID: self.rightViewControllerIdentifier)
self.drawDrawers(size: UIScreen.main.bounds.size)
self.view.addSubview(self.leftViewController.view)
self.view.addSubview(self.centerViewController.view)
self.view.addSubview(self.rightViewController.view)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition(in: self.view, animation: { (UIViewControllerTransitionCoordinatorContext) -> Void in
// This is for beginning of transition
self.drawDrawers(size: size)
}, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
// This is for after transition has completed.
})
}
// MARK: - Drawing View
func drawDrawers(size:CGSize) {
// Calculate Center View's Size
let centerWidth = (size.width/drawerSize) * (drawerSize - 1)
// Left Drawer
self.leftViewController.view.frame = CGRect(x: 0.0, y: 0.0, width: size.width/self.drawerSize, height: size.height)
// Center Drawer
self.centerViewController.view.frame = CGRect(x: self.leftViewController.view.frame.width, y: 0.0, width: centerWidth, height: size.height)
// Right Drawer
self.rightViewController.view.frame = CGRect(x: self.centerViewController.view.frame.Origin.x + self.centerViewController.view.frame.size.width, y: 0.0, width: size.width/self.drawerSize, height: size.height)
// Capture the Swipes
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeRightAction(rec:)))
swipeRight.direction = .right
centerViewController.view.addGestureRecognizer(swipeRight)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeLeftAction(rec:)))
swipeLeft.direction = .left
centerViewController.view.addGestureRecognizer(swipeLeft)
openDrawer(openSide)
}
// MARK: - Open Drawers
func openDrawer(_ side:Drawers) {
self._openSide = side
var rect:CGRect
switch side{
case .left:
rect = CGRect(
x: 0.0,
y: 0.0,
width: self.view.bounds.width,
height: self.view.bounds.height
)
case .right:
rect = CGRect(
x: self.view.bounds.Origin.x - self.leftViewController.view.bounds.size.width,
y: 0.0,
width: self.view.bounds.width,
height: self.view.bounds.height
)
}
UIView.animate(withDuration: 0.1, delay: 0, options: UIViewAnimationOptions.curveEaseIn, animations:
{ () -> Void in
// move views here
self.view.frame = rect
}, completion:
{ finished in
})
}
// MARK: - Swipe Handling
@objc func swipeRightAction(rec: UISwipeGestureRecognizer){
self.openDrawer(.left)
}
@objc func swipeLeftAction(rec:UISwipeGestureRecognizer){
self.openDrawer(.right)
}
// MARK: - Helpers
func instantiateViewControllers(storyboardID: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil)
.instantiateViewController(withIdentifier: "\(storyboardID)")
}
}
ソース ここ 。
画像 ここ 。
ビデオ ここ 。
2つの方法で実装しました。
最初はScroll View
を使用し、2番目はContainer Views
を使用します。
1つのコンテナでTableViewController
をメニューとして機能させ、2番目のコンテナでTabBarController
を非表示のタブで使用できます。テーブルビューでCell
を押すと、タブバーのn番目のタブに移動します。
あなたがしなければならないのは、ボタンのクリックまたはジェスチャで一番上のコンテナをアニメーション化することです。その場合、次のようになります。
素敵なのは、組み込みのメソッドを使用してスプリングダンピングを使用してUIViewをアニメーション化するなどのクールな効果を簡単に追加して、リアルな弾むような効果を与えることができることです。メインビュー(写真には追加されていません)に影を追加して、メニューの上のページのように見せることもできます。