iOS 10 ha una funzione che vorrei replicare. Quando tocchi un album 3D nell'app Apple Music, si apre il menu mostrato di seguito. Tuttavia a differenza di una normale sbirciatina e pop, non va via quando alzi il dito. Come posso replicare questo?Come faccio a replicare Apple Music di iOS 10 "Menu di azione Peek e pop"
risposta
Il più vicino ho avuto modo di replicare è il seguente codice .. E creare un manichino-replica dell'applicazione Musica .. poi ho aggiunto i delegati PeekPop-3D-Touch.
Tuttavia, nel delegato, aggiungo un osservatore al rilevatore di gesti e quindi annullo il gesto dopo averlo sbirciato ma poi lo riatroo quando il dito è sollevato. Per riattivarlo, l'ho fatto asincrono perché l'anteprima sparirà immediatamente senza la distribuzione asincrona. Non riuscivo a trovare un modo intorno ad esso ..
Ora, se si tocca fuori della scatola blu, sparirà come normale =]
http://i.imgur.com/073M2Ku.jpg http://i.imgur.com/XkwUBly.jpg
//
// 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];
}
}
E l'implementazione di ForceTouch in pausa ..
//
// 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)
}
}
Credo che dove mi sono perso è che non devo scorrere verso l'alto. So che quando tocco 3D un thread di testo e scorro verso l'alto ottengo le opzioni di risposta. Ma quando tocco 3D un album, si anima solo lo schermo mostrato sopra. Niente swiping o niente –
Questa operazione potrebbe essere eseguita utilizzando UIPreviewInteraction API.
https://developer.apple.com/documentation/uikit/uipreviewinteraction
è quasi simile al Peek e Pop API.
Qui abbiamo 2 fasi: Anteprima e Conferma che corrispondono a Peek e Pop nell'API successiva. abbiamo UIPreviewInteractionDelegate che ci dà l'accesso alla transizione attraverso queste fasi.
Allora, cosa si dovrebbe fare è, per replicare quanto sopra Apple Music Popup,
mostrano manuale di una sovrapposizione di sfocatura durante didUpdatePreviewTransition
Costruire un XI ter del menu in alto e mostrarlo durante didUpdateCommitTransition
- È possibile rendere la vista rimanere lì in fase di commitTransition fine.
In realtà, Apple ha creato una demo di questo sotto forma di app di chat.
Scaricare il codice di esempio da here e provarlo.
- 1. Come abilitare peek e pop in iOS WebView?
- 2. Schema URL Apple Music
- 3. Schermata di selezione del genere Apple Music
- 4. Peek & Pop: il pop porta alla cella errata in UICollectionView
- 5. Dissolvenza dei colori UISegmentedControl come Apple Music
- 6. L'applicazione si blocca nell'implementazione 'peek e pop' in iPhone 6s
- 7. beginReceivingRemoteControlEvents non eventi di attivazione per Apple Music
- 8. I file offline di Apple Music non hanno URL?
- 9. 3D Touch Peek Scorri come Mail
- 10. Come replicare background-attachment fisso su iOS
- 11. Personalizza il menu Apple
- 12. Come replicare listview come visualizzato nel menu "Start"
- 13. Come replicare l'effetto delle schede Chrome di iOS con UICollectionView
- 14. iOS - Effetti di animazione - Immagine pop-in
- 15. Come posso implementare il miniplayer in Apple Music nella mia app?
- 16. Menu popup pop-up con margine
- 17. iOS Tinder/Twitter come slider navigazione di navigazione e menu
- 18. Personalizza SLComposeServiceViewController pop-up dell'estensione di condivisione iOS 8
- 19. TestFlight e certificati di Apple
- 20. Menu di navigazione laterale Android: come includere la barra di azione nella visualizzazione a scorrimento?
- 21. Qual è l'altezza di un UITabBar su iOS 8, iOS 9, iOS 10 e iOS 11?
- 22. Come replicare da CouchDB a PouchDB?
- 23. Il pulsante di azione UILocalNotification di iOS blocca e corrompe i dati dell'app
- 24. Come disabilitare peek on vai alla definizione
- 25. Differenza tra a + = 10 e a = a + 10 in java?
- 26. Pop-up Android con testa a freccia
- 27. Menu popup Bubble iOS simile a ITunes
- 28. Ringer iterators e forwarding (peek/multipeek)
- 29. Come faccio riferimento a valori di array all'interno di string.Format?
- 30. python2.7 peek at stdin
Sei sicuro che sia un 3D Touch e non solo una lunga pressione? Funziona anche con il mio iPhone 6+ che non ha 3D Touch. – Fogmeister
@Fogmeister Ok, quindi sono andato e ho disattivato il tocco 3D. Se noti che mostra le stesse cose ma in fondo con un pulsante Annulla aggiunto. Mi piacerebbe davvero fare entrambe le cose. Ma il problema di come lo farei è ancora valido. –
piuttosto che usare un peek e un pop segue non è possibile usare una sorta di gesto di tocco di forza per attivarlo? Al momento non sono sul mio computer, ma è quello che cerco. – Fogmeister