2016-07-17 14 views
6

iOS 10には、複製したい機能があります。 Apple Musicアプリで3Dを3Dでタッチすると、以下のメニューが開きます。しかし、通常の覗き見とポップとは異なり、あなたが指を上げたときにそれは離れません。これをどのように複製するのですか?iOS 10のApple Music「Peek and pop action menu」を複製する方法

enter image description here

+0

長時間押すだけでなく、3Dタッチだと確信していますか? 3D Touchを持たない私のiPhone 6+でも動作します。 – Fogmeister

+0

@Fogmeisterさようなら私は行って3Dタッチをオフにしました。あなたが気付くと、同じことが表示されますが、下部にはキャンセルボタンが追加されています。私は実際に両方をしたいと思う。しかし、私はそれをどうやってやるのかという問題はまだ立っています。 –

+0

を使用するのではなく、それを起動するために何らかの力のタッチジェスチャーを使用することはできませんか?私は現時点では私のコンピュータにはないが、それは私が探しているものだ。 – Fogmeister

答えて

1

私はそれが次のコードで複製になった最も近い...それは音楽アプリケーションのダミーレプリカを作成...それから私はPeekPop-3Dタッチデリゲートを追加しました。

しかし、代理人では、オブジェクトレコグナイザにオブザーバを追加してから、表示中にジェスチャをキャンセルしてから、指が離されたときに再度有効にします。これを再び有効にするには、プレビューが非同期ディスパッチなしで直ちに消えるため、非同期にしました。私はそれを回避する方法..あなたは青いボックスの外側をタップすると、それは通常のように消えてしまいます今

=]

http://i.imgur.com/073M2Ku.jpg http://i.imgur.com/XkwUBly.jpg

enter image description here enter image description here

// 
// ViewController.swift 
// PeekPopExample 
// 
// Created by Brandon Anthony on 2016-07-16. 
// Copyright © 2016 XIO. All rights reserved. 
// 

import UIKit 


class MusicViewController: UITabBarController, UITabBarControllerDelegate { 

    var tableView: UITableView! 
    var collectionView: UICollectionView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.initControllers() 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
    } 

    func initControllers() { 
     let libraryController = LibraryViewController() 
     let forYouController = UIViewController() 
     let browseController = UIViewController() 
     let radioController = UIViewController() 
     let searchController = UIViewController() 

     libraryController.title = "Library" 
     libraryController.tabBarItem.image = nil 

     forYouController.title = "For You" 
     forYouController.tabBarItem.image = nil 

     browseController.title = "Browse" 
     browseController.tabBarItem.image = nil 

     radioController.title = "Radio" 
     radioController.tabBarItem.image = nil 

     searchController.title = "Search" 
     searchController.tabBarItem.image = nil 

     self.viewControllers = [libraryController, forYouController, browseController, radioController, searchController]; 
    } 


} 
を見つけることができませんでした

そしてForceTouchの実装は..

// 
// LibraryViewController.swift 
// PeekPopExample 
// 
// Created by Brandon Anthony on 2016-07-16. 
// Copyright © 2016 XIO. All rights reserved. 
// 

import Foundation 
import UIKit 


//Views and Cells.. 

class AlbumView : UIView { 
    var albumCover: UIImageView! 
    var title: UILabel! 
    var artist: UILabel! 

    override init(frame: CGRect) { 
     super.init(frame: frame) 

     self.initControls() 
     self.setTheme() 
     self.doLayout() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    func initControls() { 
     self.albumCover = UIImageView() 
     self.title = UILabel() 
     self.artist = UILabel() 
    } 

    func setTheme() { 
     self.albumCover.contentMode = .scaleAspectFit 
     self.albumCover.layer.cornerRadius = 5.0 
     self.albumCover.backgroundColor = UIColor.lightGray() 

     self.title.text = "Unknown" 
     self.title.font = UIFont.systemFont(ofSize: 12) 

     self.artist.text = "Unknown" 
     self.artist.textColor = UIColor.lightGray() 
     self.artist.font = UIFont.systemFont(ofSize: 12) 
    } 

    func doLayout() { 
     self.addSubview(self.albumCover) 
     self.addSubview(self.title) 
     self.addSubview(self.artist) 

     let views = ["albumCover": self.albumCover, "title": self.title, "artist": self.artist]; 
     var constraints = Array<String>() 

     constraints.append("H:|-0-[albumCover]-0-|") 
     constraints.append("H:|-0-[title]-0-|") 
     constraints.append("H:|-0-[artist]-0-|") 
     constraints.append("V:|-0-[albumCover]-[title]-[artist]-0-|") 

     let aspectRatioConstraint = NSLayoutConstraint(item: self.albumCover, attribute: .width, relatedBy: .equal, toItem: self.albumCover, attribute: .height, multiplier: 1.0, constant: 0.0) 

     self.addConstraint(aspectRatioConstraint) 

     for constraint in constraints { 
      self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 
     } 

     for view in self.subviews { 
      view.translatesAutoresizingMaskIntoConstraints = false 
     } 
    } 
} 

class AlbumCell : UITableViewCell { 
    var firstAlbumView: AlbumView! 
    var secondAlbumView: AlbumView! 

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 
     super.init(style: style, reuseIdentifier: reuseIdentifier) 

     self.initControls() 
     self.setTheme() 
     self.doLayout() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    func initControls() { 
     self.firstAlbumView = AlbumView(frame: CGRect.zero) 
     self.secondAlbumView = AlbumView(frame: CGRect.zero) 
    } 

    func setTheme() { 

    } 

    func doLayout() { 
     self.contentView.addSubview(self.firstAlbumView) 
     self.contentView.addSubview(self.secondAlbumView) 

     let views: [String: AnyObject] = ["firstAlbumView": self.firstAlbumView, "secondAlbumView": self.secondAlbumView]; 
     var constraints = Array<String>() 

     constraints.append("H:|-15-[firstAlbumView(==secondAlbumView)]-15-[secondAlbumView(==firstAlbumView)]-15-|") 
     constraints.append("V:|-15-[firstAlbumView]-15-|") 
     constraints.append("V:|-15-[secondAlbumView]-15-|") 

     for constraint in constraints { 
      self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 
     } 

     for view in self.contentView.subviews { 
      view.translatesAutoresizingMaskIntoConstraints = false 
     } 
    } 
} 



//Details.. 

class DetailSongViewController : UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.view.backgroundColor = UIColor.blue() 
    } 

    /*override func previewActionItems() -> [UIPreviewActionItem] { 
     let regularAction = UIPreviewAction(title: "Regular", style: .default) { (action: UIPreviewAction, vc: UIViewController) -> Void in 

     } 

     let destructiveAction = UIPreviewAction(title: "Destructive", style: .destructive) { (action: UIPreviewAction, vc: UIViewController) -> Void in 

     } 

     let actionGroup = UIPreviewActionGroup(title: "Group...", style: .default, actions: [regularAction, destructiveAction]) 

     return [actionGroup] 
    }*/ 
} 











//Implementation.. 

extension LibraryViewController : UIViewControllerPreviewingDelegate { 
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { 

     guard let indexPath = self.tableView.indexPathForRow(at: location) else { 
      return nil 
     } 

     guard let cell = self.tableView.cellForRow(at: indexPath) else { 
      return nil 
     } 


     previewingContext.previewingGestureRecognizerForFailureRelationship.addObserver(self, forKeyPath: "state", options: .new, context: nil) 


     let detailViewController = DetailSongViewController() 
     detailViewController.preferredContentSize = CGSize(width: 0.0, height: 300.0) 
     previewingContext.sourceRect = cell.frame 
     return detailViewController 
    } 

    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) { 

     //self.show(viewControllerToCommit, sender: self) 
    } 

    override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey : AnyObject]?, context: UnsafeMutablePointer<Void>?) { 
     if let object = object { 
      if keyPath == "state" { 
       let newValue = change![NSKeyValueChangeKey.newKey]!.integerValue 
       let state = UIGestureRecognizerState(rawValue: newValue!)! 
       switch state { 
       case .began, .changed: 
        self.navigationItem.title = "Peeking" 
        (object as! UIGestureRecognizer).isEnabled = false 

       case .ended, .failed, .cancelled: 
        self.navigationItem.title = "Not committed" 
        object.removeObserver(self, forKeyPath: "state") 

        DispatchQueue.main.async(execute: { 
         (object as! UIGestureRecognizer).isEnabled = true 
        }) 


       case .possible: 
        break 
       } 
      } 
     } 
    } 
} 


class LibraryViewController : UIViewController, UITableViewDelegate, UITableViewDataSource { 

    var tableView: UITableView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.initControls() 
     self.setTheme() 
     self.registerClasses() 
     self.registerPeekPopPreviews(); 
     self.doLayout() 
    } 

    func initControls() { 
     self.tableView = UITableView(frame: CGRect.zero, style: .grouped) 
    } 

    func setTheme() { 
     self.edgesForExtendedLayout = UIRectEdge() 
     self.tableView.dataSource = self; 
     self.tableView.delegate = self; 
    } 

    func registerClasses() { 
     self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Default") 
     self.tableView.register(AlbumCell.self, forCellReuseIdentifier: "AlbumCell") 
    } 

    func registerPeekPopPreviews() { 
     //if (self.traitCollection.forceTouchCapability == .available) { 
      self.registerForPreviewing(with: self, sourceView: self.tableView) 
     //} 
    } 

    func doLayout() { 
     self.view.addSubview(self.tableView) 

     let views: [String: AnyObject] = ["tableView": self.tableView]; 
     var constraints = Array<String>() 

     constraints.append("H:|-0-[tableView]-0-|") 
     constraints.append("V:|-0-[tableView]-0-|") 

     for constraint in constraints { 
      self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) 
     } 

     for view in self.view.subviews { 
      view.translatesAutoresizingMaskIntoConstraints = false 
     } 
    } 



    func numberOfSections(in tableView: UITableView) -> Int { 
     return 2 
    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return section == 0 ? 5 : 10 
    } 

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
     return (indexPath as NSIndexPath).section == 0 ? 44.0 : 235.0 
    } 

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
     return section == 0 ? 75.0 : 50.0 
    } 

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 
     return 0.0001 
    } 

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
     return section == 0 ? "Library" : "Recently Added" 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

     if (indexPath as NSIndexPath).section == 0 { //Library 
      let cell = tableView.dequeueReusableCell(withIdentifier: "Default", for: indexPath) 

      switch (indexPath as NSIndexPath).row { 
      case 0: 
       cell.accessoryType = .disclosureIndicator 
       cell.textLabel?.text = "Playlists" 

      case 1: 
       cell.accessoryType = .disclosureIndicator 
       cell.textLabel?.text = "Artists" 

      case 2: 
       cell.accessoryType = .disclosureIndicator 
       cell.textLabel?.text = "Albums" 

      case 3: 
       cell.accessoryType = .disclosureIndicator 
       cell.textLabel?.text = "Songs" 

      case 4: 
       cell.accessoryType = .disclosureIndicator 
       cell.textLabel?.text = "Downloads" 


      default: 
       break 
      } 
     } 

     if (indexPath as NSIndexPath).section == 1 { //Recently Added 
      let cell = tableView.dequeueReusableCell(withIdentifier: "AlbumCell", for: indexPath) 
      cell.selectionStyle = .none 
      return cell 
     } 

     return tableView.dequeueReusableCell(withIdentifier: "Default", for: indexPath) 
    } 
} 
+0

私は失われていると思うのは、私はスワイプする必要がないということです。私が3Dのテキストスレッドに触れ、スワイプすると、返信オプションが表示されます。しかし、3Dでアルバムに触れると、上の画面がアニメーション表示されます。スワイプやその他のものはありません。 –

0

これは実際にUIPreviewInteraction APIを使用して行うことができます。

https://developer.apple.com/documentation/uikit/uipreviewinteraction

それは、覗くとポップAPIとほぼ同様です。

ここでは、後のAPIのPeekとPopに対応するプレビューとコミットの2つのフェーズがあります。我々はUIPreviewInteractionDelegateを持っており、これらの段階を経て移行することができます。 1が何をすべきだから何

  • が手動で上記のメニューのXIBを構築し、didUpdateCommitTransition中にそれを示してdidUpdatePreviewTransition

  • 時のぼかしオーバーレイを示し、Appleの音楽ポップアップ上に複製すること、です

  • ビューをcommitTransitionフェーズの終了時に表示させることができます。

実際に、リンゴは、チャットアプリケーションの形でこれのデモを作成しました。

hereからサンプルコードをダウンロードしてテストしてください。

関連する問題