我想创建WhatsApp,使用目标c在iPhone中推出一键式语音留言功能。
答案 0 :(得分:3)
首先,这是一个非常基本的例子。所以谁想要使用它,还需要做更多的事情。如果有人在 Swift 3.x
中需要它
import UIKit
protocol SPKRecordViewDelegate: class {
func SPKRecordViewDidSelectRecord(sender : SPKRecordView, button: UIView)
func SPKRecordViewDidStopRecord(sender : SPKRecordView, button: UIView)
func SPKRecordViewDidCancelRecord(sender : SPKRecordView, button: UIView)
}
class SPKRecordView: UIView {
enum SPKRecordViewState {
case Recording
case None
}
var state : SPKRecordViewState = .None {
didSet {
UIView.animate(withDuration: 0.3) { () -> Void in
self.slideToCancel.alpha = 1.0
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
}
let recordButton : UIButton = UIButton(type: .custom)
let slideToCancel : UILabel = UILabel(frame: CGRect.zero)
weak var delegate : SPKRecordViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
self.translatesAutoresizingMaskIntoConstraints = false
setupRecordButton()
setupLabel()
}
func setupRecordButton() {
recordButton.translatesAutoresizingMaskIntoConstraints = false
addSubview(recordButton)
let hConsts = NSLayoutConstraint.constraints(withVisualFormat: "H:[recordButton]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["recordButton":recordButton])
self.addConstraints(hConsts)
let vConsts = NSLayoutConstraint.constraints(withVisualFormat: "V:|[recordButton]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["recordButton":recordButton])
self.addConstraints(vConsts)
recordButton.setImage(UIImage(named: "record")!, for: .normal)
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(userDidTapRecord(_:)))
longPress.cancelsTouchesInView = false
longPress.allowableMovement = 10
longPress.minimumPressDuration = 0.2
recordButton.addGestureRecognizer(longPress)
}
func setupLabel() {
slideToCancel.translatesAutoresizingMaskIntoConstraints = false
addSubview(slideToCancel)
backgroundColor = UIColor.clear
let hConsts = NSLayoutConstraint.constraints(withVisualFormat: "H:|[slideToCancel][bt]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["slideToCancel":slideToCancel,"bt":recordButton])
self.addConstraints(hConsts)
let vConsts = NSLayoutConstraint.constraints(withVisualFormat: "V:|[slideToCancel]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["slideToCancel":slideToCancel])
self.addConstraints(vConsts)
slideToCancel.alpha = 0.0
slideToCancel.font = UIFont(name: "Lato-Bold", size: 17)
slideToCancel.textAlignment = .center
slideToCancel.textColor = UIColor.black
}
override public var intrinsicContentSize: CGSize {
if state == .none {
return recordButton.intrinsicContentSize
} else {
return CGSize(width: recordButton.intrinsicContentSize.width * 3, height: recordButton.intrinsicContentSize.height)
}
}
func userDidTapRecordThenSwipe(sender: UIButton) {
slideToCancel.text = nil
delegate?.SPKRecordViewDidCancelRecord(sender: self, button: sender)
}
func userDidStopRecording(sender: UIButton) {
slideToCancel.text = nil
delegate?.SPKRecordViewDidStopRecord(sender: self, button: sender)
}
func userDidBeginRecord(sender : UIButton) {
slideToCancel.text = "Slide to cancel <"
delegate?.SPKRecordViewDidSelectRecord(sender: self, button: sender)
}
func userDidTapRecord(_ sender: UIGestureRecognizer) {
print("Long Tap")
let button = sender.view as! UIButton
let location = sender.location(in: button)
var startLocation = CGPoint.zero
switch sender.state {
case .began:
startLocation = location
userDidBeginRecord(sender: button)
case .changed:
let translate = CGPoint(x: location.x - startLocation.x, y: location.y - startLocation.y)
if !button.bounds.contains(translate) {
if state == .Recording {
userDidTapRecordThenSwipe(sender: button)
}
}
case .ended:
if state == .None { return }
let translate = CGPoint(x: location.x - startLocation.x, y: location.y - startLocation.y)
if !button.frame.contains(translate) {
userDidStopRecording(sender: button)
}
case .failed, .possible ,.cancelled :
if state == .Recording {
userDidStopRecording(sender: button)
}
else {
userDidTapRecordThenSwipe(sender: button)
}
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension ViewController : SPKRecordViewDelegate {
func SPKRecordViewDidCancelRecord(sender: SPKRecordView, button: UIView) {
sender.state = .None
print("Cancelled")
}
func SPKRecordViewDidSelectRecord(sender: SPKRecordView, button: UIView) {
sender.state = .Recording
print("Began " + NSUUID().uuidString)
}
func SPKRecordViewDidStopRecord(sender : SPKRecordView, button: UIView) {
sender.state = .None
print("Done")
}
}
&#13;
用法:
import UIKit
let rec = SPKRecordView(frame: CGRect.zero)
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
rec.delegate = self
view.addSubview(rec)
let hConsts = NSLayoutConstraint.constraints(withVisualFormat: "H:[bt]-(100)-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["bt":rec])
view.addConstraints(hConsts)
let vConsts = NSLayoutConstraint.constraints(withVisualFormat: "V:|-(100)-[bt]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["bt":rec])
view.addConstraints(vConsts)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
&#13;
答案 1 :(得分:1)
这类似于Whatsapp录制行为只是为了好玩,但它写在protocol SPKRecordViewDelegate: class {
func SPKRecordViewDidSelectRecord(sender : SPKRecordView, button: UIView)
func SPKRecordViewDidStopRecord(sender : SPKRecordView, button: UIView)
func SPKRecordViewDidCancelRecord(sender : SPKRecordView, button: UIView)
}
class SPKRecordView: UIView {
enum SPKRecordViewState {
case Recording
case None
}
var state : SPKRecordViewState = .None {
didSet {
UIView.animateWithDuration(0.3) { () -> Void in
self.slideToCancel.alpha = 1.0
self.invalidateIntrinsicContentSize()
self.setNeedsLayout()
self.layoutIfNeeded()
}
}
}
let recordButton : UIButton = UIButton(type: .Custom)
let slideToCancel : UILabel = UILabel(frame: CGRectZero)
weak var delegate : SPKRecordViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
self.translatesAutoresizingMaskIntoConstraints = false
setupRecordButton()
setupLabel()
}
func setupRecordButton() {
recordButton.translatesAutoresizingMaskIntoConstraints = false
addSubview(recordButton)
let hConsts = NSLayoutConstraint.constraintsWithVisualFormat("H:[recordButton]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["recordButton":recordButton])
self.addConstraints(hConsts)
let vConsts = NSLayoutConstraint.constraintsWithVisualFormat("V:|[recordButton]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["recordButton":recordButton])
self.addConstraints(vConsts)
recordButton.setImage(UIImage(named: "record")!, forState: .Normal)
let longPress = UILongPressGestureRecognizer(target: self, action: "userDidTapRecord:")
longPress.cancelsTouchesInView = false
longPress.allowableMovement = 10
longPress.minimumPressDuration = 0.2
recordButton.addGestureRecognizer(longPress)
}
func setupLabel() {
slideToCancel.translatesAutoresizingMaskIntoConstraints = false
addSubview(slideToCancel)
backgroundColor = UIColor.clearColor()
let hConsts = NSLayoutConstraint.constraintsWithVisualFormat("H:|[slideToCancel][bt]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["slideToCancel":slideToCancel,"bt":recordButton])
self.addConstraints(hConsts)
let vConsts = NSLayoutConstraint.constraintsWithVisualFormat("V:|[slideToCancel]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["slideToCancel":slideToCancel])
self.addConstraints(vConsts)
slideToCancel.alpha = 0.0
slideToCancel.font = UIFont(name: "Lato-Bold", size: 17)
slideToCancel.textAlignment = .Center
slideToCancel.textColor = UIColor.blackColor()
}
override func intrinsicContentSize() -> CGSize {
if state == .None {
return recordButton.intrinsicContentSize()
} else {
return CGSizeMake(recordButton.intrinsicContentSize().width * 3, recordButton.intrinsicContentSize().height)
}
}
func userDidTapRecordThenSwipe(sender: UIButton) {
slideToCancel.text = nil
delegate?.SPKRecordViewDidCancelRecord(self, button: sender)
}
func userDidStopRecording(sender: UIButton) {
slideToCancel.text = nil
delegate?.SPKRecordViewDidStopRecord(self, button: sender)
}
func userDidBeginRecord(sender : UIButton) {
slideToCancel.text = "Slide to cancel <"
delegate?.SPKRecordViewDidSelectRecord(self, button: sender)
}
func userDidTapRecord(gesture: UIGestureRecognizer) {
let button = gesture.view as! UIButton
let location = gesture.locationInView(button)
var startLocation = CGPointZero
switch gesture.state {
case .Began:
startLocation = location
userDidBeginRecord(button)
case .Changed:
let translate = CGPoint(x: location.x - startLocation.x, y: location.y - startLocation.y)
if !CGRectContainsPoint(button.bounds, translate) {
if state == .Recording {
userDidTapRecordThenSwipe(button)
}
}
case .Ended:
if state == .None { return }
let translate = CGPoint(x: location.x - startLocation.x, y: location.y - startLocation.y)
if !CGRectContainsPoint(button.frame, translate) {
userDidStopRecording(button)
}
case .Failed, .Possible ,.Cancelled : if state == .Recording { userDidStopRecording(button) } else { userDidTapRecordThenSwipe(button)}
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension ViewController : SPKRecordViewDelegate {
func SPKRecordViewDidCancelRecord(sender: SPKRecordView, button: UIView) {
sender.state = .None
print("Cancelled")
}
func SPKRecordViewDidSelectRecord(sender: SPKRecordView, button: UIView) {
sender.state = .Recording
print("Began " + NSUUID().UUIDString)
}
func SPKRecordViewDidStopRecord(sender : SPKRecordView, button: UIView) {
sender.state = .None
print("Done")
}
}
class HomeViewController: UIViewController {
let rec = SPKRecordView(frame: CGRectZero)
override func viewDidLoad() {
super.viewDidLoad()
rec.delegate = self
view.addSubview(rec)
let hConsts = NSLayoutConstraint.constraintsWithVisualFormat("H:[bt]-(100)-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["bt":rec])
view.addConstraints(hConsts)
let vConsts = NSLayoutConstraint.constraintsWithVisualFormat("V:|-(100)-[bt]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["bt":rec])
view.addConstraints(vConsts)
}
}
用法:
$qr1