ios - 运行一个循环直到 UIPanGestureRecognizer 结束

标签 ios swift cocoa-touch uigesturerecognizer

希望这对于模组来说不会太模糊。

我想让用户交互类似于一些高保真音响上的音量控制,您可以向左或向右移动转盘来改变音量,而不是将转盘转动整圈,而是稍微向左或向右转动它,并且转动得越多音量变化得越快,直到您放开它,它会砰砰地回到中间。

在我的应用程序中,我想使用 UIPanGestureRecogniser,当用户从中间向上平移时,音量会增加,离中间越远,增加得越快。当他们平移到屏幕中点以下时,音量会下降,离中间越远越快。

我遇到的问题是如何在不锁定 UI 的情况下实现这一点。我不能只使用 gestureRecognizer Action 选择器,因为只有在有移动时才会调用它,为了使这种交互起作用,用户通常会在等待达到正确的音量时将手指放在一个位置。

我觉得我想设置一个在手势识别器选择器外部运行的循环,并让它监视一个类变量,该变量在手势移动或结束时得到更新。如果它在手势识别器选择器中执行此操作,它将继续运行....

如果这是一个嵌入式系统,我会设置某种基于中断的轮询来检查输入控件的位置并继续添加音量直到它回到中间 - 在这里找不到 iOS 的可比对象.

欢迎提出建议,抱歉,如果这太模糊了 - 它更像是一个框架方法论问题,而不是特定代码问题。

最佳答案

有趣的问题我给你写了一个示例,它一定是你想要的:

objective-c 代码:

#import "ViewController.h"

@interface ViewController ()

@property float theValue;
@property NSTimer *timer;
@property bool needRecord;
@property UIView *dot;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.needRecord = NO;
    self.theValue = 0;

    UIView *circle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
    circle.layer.borderWidth = 3;
    circle.layer.borderColor = [UIColor redColor].CGColor;
    circle.layer.cornerRadius = 25;
    circle.center = self.view.center;
    [self.view addSubview:circle];

    self.dot = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    self.dot.backgroundColor = [UIColor redColor];
    self.dot.layer.cornerRadius = 20;
    self.dot.center = self.view.center;
    [self.view addSubview:self.dot];

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandle:)];

    [self.dot addGestureRecognizer:pan];

    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timerFire) userInfo:nil repeats:YES];
}

-(void)panHandle:(UIPanGestureRecognizer *)pan{
    CGPoint pt = [pan translationInView:self.view];
//    NSLog([NSString stringWithFormat:@"pt.y = %f",pt.y]);
    switch (pan.state) {
        case UIGestureRecognizerStateBegan:
            [self draggingStart];
            break;
        case UIGestureRecognizerStateChanged:
            self.dot.center = CGPointMake(self.view.center.x, self.view.center.y + pt.y);
            break;
        case UIGestureRecognizerStateEnded:
            [self draggingEnned];
            break;
        default:
            break;
    }
}

-(void)draggingStart{
    self.needRecord = YES;
}

-(void)draggingEnned{
    self.needRecord = NO;
    [UIView animateWithDuration:0.5 animations:^{
        self.dot.center = self.view.center;
    }];
}

-(void)timerFire{
    if (self.needRecord) {
        float distance = self.dot.center.y - self.view.center.y;
//        NSLog([NSString stringWithFormat:@"distance = %f",distance]);
        self.theValue -= distance/1000;
        NSLog([NSString stringWithFormat:@"theValue = %f",self.theValue]);
    }
}

@end

我现在正在学习 Swift,所以如果你需要,这是 Swift 代码:

class ViewController: UIViewController {

    var lbInfo:UILabel?;
    var theValue:Float?;
    var timer:NSTimer?;
    var needRecord:Bool?;
    var circle:UIView?;
    var dot:UIView?;

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        needRecord = false;
        theValue = 0;

        lbInfo = UILabel(frame: CGRect(x: 50, y: 50, width: UIScreen.mainScreen().bounds.width-100, height: 30));
        lbInfo!.textAlignment = NSTextAlignment.Center;
        lbInfo!.text = "Look at here!";
        self.view.addSubview(lbInfo!);

        circle = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50));
        circle!.layer.borderWidth = 3;
        circle!.layer.borderColor = UIColor.redColor().CGColor;
        circle!.layer.cornerRadius = 25;
        circle!.center = self.view.center;
        self.view.addSubview(circle!);

        dot = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40));
        dot!.backgroundColor = UIColor.redColor();
        dot!.layer.cornerRadius = 20;
        dot!.center = self.view.center;
        self.view.addSubview(dot!);

        let pan = UIPanGestureRecognizer(target: self, action: #selector(ViewController.panhandler));
        dot!.addGestureRecognizer(pan);

        timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: #selector(ViewController.timerFire), userInfo: nil, repeats: true)
    }

    func panhandler(pan: UIPanGestureRecognizer) -> Void {
        let pt = pan.translationInView(self.view);
        switch pan.state {
        case UIGestureRecognizerState.Began:
            draggingStart();
        case UIGestureRecognizerState.Changed:
            self.dot!.center = CGPoint(x: self.view.center.x, y: self.view.center.y + pt.y);
        case UIGestureRecognizerState.Ended:
            draggingEnded();
        default:
            break;
        }
    }

    func draggingStart() -> Void {
        needRecord = true;
    }

    func draggingEnded() -> Void {
        needRecord = false;
        UIView.animateWithDuration(0.1, animations: {
            self.dot!.center = self.view.center;
        });
    }

    @objc func timerFire() -> Void {
        if(needRecord!){
            let distance:Float = Float(self.dot!.center.y) - Float(self.view.center.y);
            theValue! -= distance/1000;
            self.lbInfo!.text = String(format: "%.2f", theValue!);
        }
    }
}

希望对您有所帮助。

如果您还需要一些建议,请留在这里,稍后我会查看。

关于ios - 运行一个循环直到 UIPanGestureRecognizer 结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39354885/

相关文章:

iphone - 可变高度 UILabel

objective-c - iOS 上使用 Facebook API 请求超时

ios - PromiseKit for In Loop 实现时

ios - Swiftchars - 条形图在特定数量的点后重叠

ios - 如何检查 View 中是否已存在约束?

xcode - 如何在 Swift 3.0 中使用@asmname()

ios - 如何让 iOS 13 map 同时显示用户位置和另一个注释,即使它们靠得很近

ios - UINavigationController appDelegate UIViewController 以编程方式

swift - 将获胜机会转换为 bool 值的最佳方法是什么?

iphone - 设置分组 UITableViewCell 的背景颜色