在我的应用程序中有一个图像视图。我将PAN手势添加到该图像视图。
这很好。
图像视图处于横向模式。
我希望在用户向右平移时增加标签数量,并在用户向左平移时减少该数量。
我google了很多,但没有找到解决方案。
任何人都可以帮助我如何检测用户平移的方向(左/右)?
答案 0 :(得分:88)
在手势识别器的目标选择器中,使用- (CGPoint)velocityInView:(UIView *)view;
:
- (void)panRecognized:(UIPanGestureRecognizer *)rec
{
CGPoint vel = [rec velocityInView:self.view];
if (vel.x > 0)
{
// user dragged towards the right
counter++;
}
else
{
// user dragged towards the left
counter--;
}
}
P.s。:直到约。我才知道这种方法。 3分钟前谷歌首次点击之一是官方的Apple文档。
答案 1 :(得分:36)
这样的事情:
- (void)pan:(UIPanGestureRecognizer *)sender
{
typedef NS_ENUM(NSUInteger, UIPanGestureRecognizerDirection) {
UIPanGestureRecognizerDirectionUndefined,
UIPanGestureRecognizerDirectionUp,
UIPanGestureRecognizerDirectionDown,
UIPanGestureRecognizerDirectionLeft,
UIPanGestureRecognizerDirectionRight
};
static UIPanGestureRecognizerDirection direction = UIPanGestureRecognizerDirectionUndefined;
switch (sender.state) {
case UIGestureRecognizerStateBegan: {
if (direction == UIPanGestureRecognizerDirectionUndefined) {
CGPoint velocity = [sender velocityInView:recognizer.view];
BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x);
if (isVerticalGesture) {
if (velocity.y > 0) {
direction = UIPanGestureRecognizerDirectionDown;
} else {
direction = UIPanGestureRecognizerDirectionUp;
}
}
else {
if (velocity.x > 0) {
direction = UIPanGestureRecognizerDirectionRight;
} else {
direction = UIPanGestureRecognizerDirectionLeft;
}
}
}
break;
}
case UIGestureRecognizerStateChanged: {
switch (direction) {
case UIPanGestureRecognizerDirectionUp: {
[self handleUpwardsGesture:sender];
break;
}
case UIPanGestureRecognizerDirectionDown: {
[self handleDownwardsGesture:sender];
break;
}
case UIPanGestureRecognizerDirectionLeft: {
[self handleLeftGesture:sender];
break;
}
case UIPanGestureRecognizerDirectionRight: {
[self handleRightGesture:sender];
break;
}
default: {
break;
}
}
}
case UIGestureRecognizerStateEnded: {
direction = UIPanGestureRecognizerDirectionUndefined;
break;
}
default:
break;
}
}
- (void)handleUpwardsGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Up");
}
- (void)handleDownwardsGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Down");
}
- (void)handleLeftGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Left");
}
- (void)handleRightGesture:(UIPanGestureRecognizer *)sender
{
NSLog(@"Right");
}
答案 2 :(得分:15)
我之前在Swift中的回答
public enum Direction: Int {
case Up
case Down
case Left
case Right
public var isX: Bool { return self == .Left || self == .Right }
public var isY: Bool { return !isX }
}
public extension UIPanGestureRecognizer {
public var direction: Direction? {
let velocity = velocityInView(view)
let vertical = fabs(velocity.y) > fabs(velocity.x)
switch (vertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return .Up
case (true, _, let y) where y > 0: return .Down
case (false, let x, _) where x > 0: return .Right
case (false, let x, _) where x < 0: return .Left
default: return nil
}
}
}
答案 3 :(得分:9)
这是一个清理过的Swift 3版本,其中包含使用示例:
public enum PanDirection: Int {
case up, down, left, right
public var isVertical: Bool { return [.up, .down].contains(self) }
public var isHorizontal: Bool { return !isVertical }
}
public extension UIPanGestureRecognizer {
public var direction: PanDirection? {
let velocity = self.velocity(in: view)
let isVertical = fabs(velocity.y) > fabs(velocity.x)
switch (isVertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return .up
case (true, _, let y) where y > 0: return .down
case (false, let x, _) where x > 0: return .right
case (false, let x, _) where x < 0: return .left
default: return nil
}
}
@IBAction func pan(recognizer: UIPanGestureRecognizer) {
if let direction = recognizer.direction {
if direction.isVertical {
//do what you want when pan is vertical
} else if direction == .left {
//do what you want when pan is left
}
}
}
答案 4 :(得分:1)
请注意,上面的Adam的Swift版本有错误。如果y&lt; .up应该返回。如果y> 0,则返回0和.down 0(他们反转)。
所以:
//MARK: - Direction
internal enum Direction {
case up
case down
case left
case right
}
//MARK: - UIPanGestureRecognizer
internal extension UIPanGestureRecognizer {
internal var direction: Direction? {
let velocity = velocityInView(view)
let isVertical = fabs(velocity.y) > fabs(velocity.x)
switch (isVertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return .up
case (true, _, let y) where y > 0: return .down
case (false, let x, _) where x > 0: return .right
case (false, let x, _) where x < 0: return .left
default: return nil
}
}
}
答案 5 :(得分:1)
在Swift 3上重写Adam Waite版本
List<String> newItemList = new List<string>();
private void AddButton_Click(object sender, EventArgs e)
{
string newItem = NameTextBox.Text + "\t" + QuantityBox.Value.ToString() + "\t" + PriceBox.Text;
newItemList.Add(newItem);
for(int i = 0; i < newItemList.Count; i++)
{
BasketBox.Text = newItemList[i] + "\n";
}
}
答案 6 :(得分:0)
用velocity
判断对我来说太敏感了,用户很容易将拍打屏幕与平移一小部分混合在一起。
所以我使用自定义UIPanGestureRecognizer
。 雨燕5
enum Orientation{
case lhs, rhs, `default`
}
class HPan: UIPanGestureRecognizer {
var first: CGPoint?
var orient = .default
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
state = .began
first = touches.first?.location(in: view?.window)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
if state == .cancelled{
return
}
if let location = touches.first?.location(in: view?.window), let begin = first{
let magicDistance: CGFloat = 20
if location.x - begin.x > magicDistance{
orient = .rhs
state = .ended
}
else if begin.x - location.x > magicDistance{
orient = .lhs
state = .ended
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event)
state = .ended
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesCancelled(touches, with: event)
state = .cancelled
}
override func reset() {
super.reset()
state = .possible
isRight = false
orient = .default
}
}
像这样打电话:
@objc func push(_ gesture: RightPan){
if gesture.state == UIGestureRecognizer.State.ended{
switch gesture.orient{
case .lhs:
counter -= 1
case .rhs:
counter += 1
default:
()
}
}
}