Как мы можем реализовать 3D-касание, чтобы проверить, удаляет ли пользователь UIView
или нажимает на UIView
?3D touch/Force touch реализация
Есть ли способ сделать это с помощью UIGestureRecognize
или только с UITouch
?
Как мы можем реализовать 3D-касание, чтобы проверить, удаляет ли пользователь UIView
или нажимает на UIView
?3D touch/Force touch реализация
Есть ли способ сделать это с помощью UIGestureRecognize
или только с UITouch
?
Вы можете сделать это без специального распознавателя жестов. Вам не нужно настраивать метод touchesEnded и touchhesBegan, но просто прикасаетсяМодуль для получения правильных значений. получение силы uitouch от начала/окончания вернет странные значения.
UITouch *touch = [touches anyObject];
CGFloat maximumPossibleForce = touch.maximumPossibleForce;
CGFloat force = touch.force;
CGFloat normalizedForce = force/maximumPossibleForce;
затем установить порог силы и сравнить normalizedForce этого порога (0,75 кажется нормально для меня).
Свойства 3D Touch are available on UITouch
objects.
Вы можете получить эти штрихи, переопределив UIView
touchesBegan:
и touchesMoved:
методов. Не уверен, что вы видите в touchesEnded:
.
Если вы хотите создать новые распознаватели жестов, у вас есть полный доступ к UITouch
es, как показано в UIGestureRecognizerSubclass
.
Я не уверен, как вы можете использовать свойства 3D-касания в традиционном UIGestureRecognizer
. Возможно, с помощью метода UIGestureRecognizerDelegate
протокола gestureRecognizer:shouldReceiveTouch:
.
Я хочу, чтобы проверить, если пользователь нажмите на UIView или сила прикосновения к UIView –
'UITapGestureRecognizer' не был обновлен для 3D Touch, так что вы должны сделать свой собственный' UIGestureRecognizer' подкласс или подкласс мнения и обрабатывать 'touchhesBegan' и' touchhesMoved'. –
Если прикосновение не двигается, но это изменения в силу, 'touchhesMoved:' get called? – Warpling
Способ, которым я это делаю, состоит в использовании комбинации UITapGestureRecognizer (предоставляется Apple) и DFContinuousForceTouchGestureRecognizer (предоставляется мной).
DFContinuousForceTouchGestureRecognizer
приятно, потому что он постоянно обновляет информацию о изменениях давления, поэтому вы можете делать такие вещи, как увеличение вида, поскольку пользователь меняет свое давление на него, в отличие от одного события. Если вам просто нужно одно событие, вы можете игнорировать eveything в DFContinuousForceTouchDelegate
, за исключением обратного вызова - (void) forceTouchRecognized
.
https://github.com/foggzilla/DFContinuousForceTouchGestureRecognizer
Вы можете скачать этот и запустить пример приложения на устройстве, которое поддерживает силы нажмите, чтобы увидеть, как это чувствует.
в вашем UIViewController
осуществлять следующее:
- (void)viewDidLoad {
[super viewDidLoad];
_forceTouchRecognizer = [[DFContinuousForceTouchGestureRecognizer alloc] init];
_forceTouchRecognizer.forceTouchDelegate = self;
//here to demonstrate how this works alonside a tap gesture recognizer
_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
[self.imageView addGestureRecognizer:_tapGestureRecognizer];
[self.imageView addGestureRecognizer:_forceTouchRecognizer];
}
реализовать селектор для крана жеста
#pragma UITapGestureRecognizer selector
- (void)tapped:(id)sender {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[[UIAlertView alloc] initWithTitle:@"Tap" message:@"YEAH!!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
});
}
Реализовать протокол делегата для силового контакта:
#pragma DFContinuousForceTouchDelegate
- (void)forceTouchRecognized:(DFContinuousForceTouchGestureRecognizer *)recognizer {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[[UIAlertView alloc] initWithTitle:@"Force Touch" message:@"YEAH!!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
});
}
- (void)forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer *)recognizer didStartWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
CGFloat transformDelta = 1.0f + ((force/maxForce)/3.0f);
self.imageView.transform = CGAffineTransformMakeScale(transformDelta, transformDelta);
[self.imageView setNeedsDisplay];
}
- (void) forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer *)recognizer didMoveWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
CGFloat transformDelta = 1.0f + ((force/maxForce)/3.0f);
self.imageView.transform = CGAffineTransformMakeScale(transformDelta, transformDelta);
[self.imageView setNeedsDisplay];
}
- (void)forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer *)recognizer didCancelWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
}
- (void)forceTouchRecognizer:(DFContinuousForceTouchGestureRecognizer *)recognizer didEndWithForce:(CGFloat)force maxForce:(CGFloat)maxForce {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
}
- (void)forceTouchDidTimeout:(DFContinuousForceTouchGestureRecognizer *)recognizer {
self.imageView.transform = CGAffineTransformIdentity;
[self.imageView setNeedsDisplay];
}
Обратите внимание, что это будет только быть полезным на устройстве, которое поддерживает силовое прикосновение.
Кроме того, вы не должны добавить DFContinuousForceTouchGestureRecognizer
к виду, если вы работаете на 8 прошивке или под, так как он использует новое force
свойство на UITouch
доступно только в прошивке 9.
Если добавить это на прошивке 8 так ли будет сбой, поэтому условно добавьте этот распознаватель на основе версии iOS, на которой вы работаете, если вы поддерживаете версии старше iOS 9.
Wow thanks! Можете ли вы преобразовать свой ответ в Swift 2.0? И мое приложение поддерживает iOS 8-9, поэтому мне не нужно добавлять DFContinuousForceTouchGestureRecognizer для просмотра –
Я создал UIGestureRecognizer, который эмулирует поведение приложения Apple Mail. При 3D-касании он начинается с короткого одиночного импульса, а затем дополнительного вторичного действия (hardTarget) и импульса, вызванного жестким нажатием вскоре после первоначального нажатия.
адаптирован из https://github.com/FlexMonkey/DeepPressGestureRecognizer
Изменения:
Примечание: Я добавил недокументированный системный звук k_PeakSoundID, но не стесняйтесь отключить его, если вам неудобно использовать константу за пределами документированного диапазона. Я использую системные звуки с неопределенными константами в течение многих лет, но вам предлагается отключить вибрационные импульсы, используя свойство vibrateOnDeepPress.
import AudioToolbox
import UIKit.UIGestureRecognizerSubclass
class DeepPressGestureRecognizer: UIGestureRecognizer
{
var vibrateOnDeepPress = true
var threshold:CGFloat = 0.75
var hardTriggerMinTime:NSTimeInterval = 0.5
private var deepPressed: Bool = false
private var deepPressedAt: NSTimeInterval = 0
private var k_PeakSoundID:UInt32 = 1519
private var hardAction:Selector?
private var target: AnyObject?
required init(target: AnyObject?, action: Selector, hardAction:Selector?=nil, threshold: CGFloat = 0.75)
{
self.target = target
self.hardAction = hardAction
self.threshold = threshold
super.init(target: target, action: action)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent)
{
if let touch = touches.first
{
handleTouch(touch)
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent)
{
if let touch = touches.first
{
handleTouch(touch)
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent)
{
super.touchesEnded(touches, withEvent: event)
state = deepPressed ? UIGestureRecognizerState.Ended : UIGestureRecognizerState.Failed
deepPressed = false
}
private func handleTouch(touch: UITouch)
{
guard let _ = view where touch.force != 0 && touch.maximumPossibleForce != 0 else
{
return
}
let forcePercentage = (touch.force/touch.maximumPossibleForce)
let currentTime = NSDate.timeIntervalSinceReferenceDate()
if !deepPressed && forcePercentage >= threshold
{
state = UIGestureRecognizerState.Began
if vibrateOnDeepPress
{
AudioServicesPlaySystemSound(k_PeakSoundID)
}
deepPressedAt = NSDate.timeIntervalSinceReferenceDate()
deepPressed = true
}
else if deepPressed && forcePercentage <= 0
{
endGesture()
}
else if deepPressed && currentTime - deepPressedAt > hardTriggerMinTime && forcePercentage == 1.0
{
endGesture()
if vibrateOnDeepPress
{
AudioServicesPlaySystemSound(k_PeakSoundID)
}
//fire hard press
if let hardAction = self.hardAction, let target = self.target {
target.performSelector(hardAction, withObject: self)
}
}
}
func endGesture() {
state = UIGestureRecognizerState.Ended
deepPressed = false
}
}
// MARK: DeepPressable protocol extension
protocol DeepPressable
{
var gestureRecognizers: [UIGestureRecognizer]? {get set}
func addGestureRecognizer(gestureRecognizer: UIGestureRecognizer)
func removeGestureRecognizer(gestureRecognizer: UIGestureRecognizer)
func setDeepPressAction(target: AnyObject, action: Selector)
func removeDeepPressAction()
}
extension DeepPressable
{
func setDeepPressAction(target: AnyObject, action: Selector)
{
let deepPressGestureRecognizer = DeepPressGestureRecognizer(target: target, action: action, threshold: 0.75)
self.addGestureRecognizer(deepPressGestureRecognizer)
}
func removeDeepPressAction()
{
guard let gestureRecognizers = gestureRecognizers else
{
return
}
for recogniser in gestureRecognizers where recogniser is DeepPressGestureRecognizer
{
removeGestureRecognizer(recogniser)
}
}
}
. Почему бы вам просто не предоставить весь код. – Esqarrouth