iOS 10有一個我想要複製的功能。當您在Apple Music應用程序中觸摸相冊時,會打開下面顯示的菜單。然而,與正常的偷看和流行不同,當你舉起手指時,它不會消失。我如何複製這個?如何複製iOS 10的Apple音樂「Peek and pop action menu」
回答
我得複製它下面的代碼。它創建音樂應用程序的虛擬複製品最接近的。然後我加入PeekPop-3D觸控代表。
但是,在委託中,我添加了一個觀察者到手勢識別器,然後在偷看時取消手勢,但是當手指擡起時重新啓用手勢。爲了重新啓用它,我做了異步操作,因爲預覽將立即消失,而不需要異步調度。我找不到辦法解決它..
現在,如果你點擊藍色的窗口外面,它就會消失像正常=]
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];
}
}
並執行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)
}
}
我猜我失去的是我不必向上滑動。我知道當我觸摸一個文本線程並向上滑動時,我會得到回覆選項。但是當我用3D觸摸一張專輯時,它只是爲上面顯示的屏幕製作動畫。沒有刷過或什麼。 –
實際上可以使用UIPreviewInteraction API來完成。
https://developer.apple.com/documentation/uikit/uipreviewinteraction
這幾乎是類似皮克和流行API。
這裏我們有兩個階段:Preview和Commit,它們對應於後面的API中的Peek和Pop。我們有UIPreviewInteractionDelegate,它使我們能夠訪問通過這些階段的過渡。
一個應該做的那麼什麼是,複製上面的蘋果音樂彈出,
模糊疊加生成上述菜單的廈門國際銀行,並在didUpdateCommitTransition表現出來
- 您可以使視圖在commitTransition階段結束。
其實,蘋果已經以聊天應用程序的形式構建了這個演示。
從here下載示例代碼並進行測試。
- 1. Peek和Pop函數SpriteKit
- 2. 3D Peek&Pop搜索結果
- 3. MKMapView上的Peek&pop預覽
- 4. 爲手動Segue實施3D觸摸「Peek and Pop」
- 5. iOS如何使UISlider和UIButton像Apple的音樂應用程序?
- 6. iOS 3D觸摸Peek /流行音樂沒有故事板
- 7. Onclick imagebutton-action(menu)
- 8. 如何在iOS之外創建Apple音樂用戶令牌
- 9. IOS背景音樂控制
- 10. WPF Push and Pop
- 11. UIStackView Peek和Pop覆蓋小故障
- 12. 3D Peek和Pop內存泄漏
- 13. 從我的iOS應用程序打開Apple音樂
- 14. 將音樂文件複製到ios上的ipod庫
- 15. 將iOS庫音樂複製到App Store允許的視頻中?
- 16. iOS複製音樂應用程序的字母順序
- 17. 在後臺播放Apple音樂
- 18. 如何啓用3D Touch peek&pop但防止在iOS 9中導航?
- 19. 如何製作背景音樂? AS3.0
- 20. 將音樂複製到iPod的API
- 21. iOS Swift - MPCommandCenter&NowPlayingInfoCenter控制音樂鎖屏
- 22. 如何製作「開關」音樂按鈕?
- 23. 如何創建像Apple音樂一樣的UIActionSheet或UIAlertController(UIAlertControllerStyleActionSheet)?
- 24. 如何將應用程序中的音樂複製到iPod?
- 25. 將音樂複製到iPod上
- 26. 如何停止在iOS中使用Gracenote SDK錄製音樂
- 27. 如何讓音樂恢復播放?
- 28. 如何在通話後恢復音樂
- 29. 用於音量控制的IOS音樂api
- 30. 控制應用程序內的音樂音量[iOS]
你確定這是一個3D觸摸,而不只是一個長按?它也適用於我的iPhone 6+,它沒有3D Touch。 – Fogmeister
@Fogmeister好吧,我去了,關閉3D觸摸。如果您注意到它顯示了相同的內容,但在底部添加了取消按鈕。我真的想要做到這一點。但我怎麼做的問題依然存在。 –
而不是使用偷看和流行的塞格式是不可能使用某種形式的力量觸摸手勢來觸發它?我目前不在電腦上,但這正是我期待的。 – Fogmeister