2

私はユーザーがビューを上下に移動できるようにしようとしてUILabelUIPanGestureRecognizerます. したがって、基本的には、ジェスチャ レコグナイザーが 12pts 下に移動することを検出した場合、制約の定数を 12pts 移動して を移動します。UILabelUILabelUILabel

ただし、特定の垂直ポイント (高すぎるまたは低すぎる) に達したときに、それ以上移動しないようにしたい。パン ジェスチャの翻訳を確認することはUILabelできますが、何行でもかまいません。したがって、1 行ではなく 5 行の場合は、明らかにそこまでパンダウンできないため、翻訳に頼ることはできません。パン ジェスチャについては、ラベルのサイズを考慮する必要があります。

それで私はそのフレームを監視し始めました、そしてそれはうまくいきますが、私の実装では、彼らが完全に下限までパンすると、UILabel「追いつく」前に本当に遠くまでパンしなければならないという厄介な結果があります。上部境界に達した場合、そのような問題はありません)。基本的に、パンは下限までパンし、パンを上に戻すと (これはすべて同じジェスチャです)、十分にパンするまで一時的に「固着」し、その後指でジャンプします。

これを達成するために私が使用しているコードは次のとおりです。

- (void)textLabelPanned:(UIPanGestureRecognizer *)panGestureRecognizer {
    if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) {
        _textDistanceFromTopBeforeMove = self.textToReadLabelPositionFromTopConstraint.constant;
    }
    else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) {
        NSNumber *textDistanceFromTop = @(self.textToReadLabelPositionFromTopConstraint.constant);
        [[NSUserDefaults standardUserDefaults] setObject:textDistanceFromTop forKey:@"TextDistanceFromTop"];
    }
    else {
        if (CGRectGetMinY(self.textToReadLabel.frame) >= [UIScreen mainScreen].bounds.origin.y + CLOSEST_TEXT_DISTANCE_TO_TOP && CGRectGetMaxY(self.textToReadLabel.frame) <= [UIScreen mainScreen].bounds.size.height - CLOSEST_TEXT_DISTANCE_TO_BOTTOM) {
                self.textToReadLabelPositionFromTopConstraint.constant = _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y;
        }
        else if ([panGestureRecognizer translationInView:self.mainView].y > 0) {
            if (CGRectGetMaxY(self.textToReadLabel.frame) + _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y < [UIScreen mainScreen].bounds.size.height - CLOSEST_TEXT_DISTANCE_TO_BOTTOM) {
                self.textToReadLabelPositionFromTopConstraint.constant = _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y;
            }
        }
        else if ([panGestureRecognizer translationInView:self.mainView].y < 0) {
            if (CGRectGetMinY(self.textToReadLabel.frame) + _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y > [UIScreen mainScreen].bounds.origin.y + CLOSEST_TEXT_DISTANCE_TO_TOP) {
                self.textToReadLabelPositionFromTopConstraint.constant = _textDistanceFromTopBeforeMove + [panGestureRecognizer translationInView:self.mainView].y;
            }
        }


        // If one of the options views are present and the user pans really low, hide the options as to allow the user to see where they're panning
        if (_inSpeedChangingMode) {
            if (CGRectGetMaxY(self.textToReadLabel.frame) > CGRectGetMinY(self.progressBar.frame) - 10) {
                [self showWordOptions:nil];
            }
        }
        else if (_inTextChangingMode) {
            if (CGRectGetMaxY(self.textToReadLabel.frame) > CGRectGetMinY(self.progressBar.frame) - 10) {
                [self showTextOptions:nil];
            }
        }
    }
}

それが「くっつく」原因となる、私は正確に何を間違っていますか?そして、おそらくこれを行うためのより良い方法はありますか?

4

2 に答える 2

2

これは、Interface Builder またはコードで定義された制約によって完全に達成できます。トリックは、目的の位置を設定する制約よりも優先度の高い、ラベルが範囲外に移動するのを防ぐ制約を定義することです。

私のテスト プロジェクトでは、1) ビュー コントローラー ビュー、2) 境界を定義する「コンテナー ビュー」、3) 複数行の UILabel を持つストーリーボードに完全にビュー階層を設定しました。コンテナからラベルに作用する 6 つの制約があります。

  • 4 つの 'space to' 制約 (先頭、末尾、上、下) により、ラベルが親コンテナーの境界の外に配置されることはありません。これらの優先度は、Interface Builder でデフォルト値の「1000」に設定されています。これらの制約の関係は「>=」で、定数値は「0」です。

  • 2 つの 'space to' 制約 (先頭、上) は、ラベルの実際の位置を駆動します。これらの優先順位は低く設定されています。私は「500」を選びました。これらの制約はView Controllerにアウトレットがあるため、コードで調整できます。これらの制約の関係は「=」であり、初期値はラベルを配置したいものです。

ラベル自体には、複数行で表示するように強制する幅の制約があります。

IB では次のようになります。

選択した制約は優先度が低く、ラベルの x 位置を駆動するために使用されます。この制約はビュー コントローラーの ivar に関連付けられているため、実行時に調整できます。 配置制約が選択されていることを示す

選択した制約は優先度が高く、親ビュー内でラベルを囲うために使用されます。 選択された囲い込み制約を示す

ビュー コントローラのコードは次のとおりです。

@interface TSViewController ()
@end

@implementation TSViewController
{
    IBOutlet NSLayoutConstraint* _xLayoutConstraint;

    IBOutlet NSLayoutConstraint* _yLayoutConstraint;
}

- (IBAction) pan: (UIGestureRecognizer*) pgr
{
    CGPoint p = [pgr locationInView: self.view];

    p.x -= pgr.view.frame.size.width / 2.0;
    p.y -= pgr.view.frame.size.height / 2.0;

    _xLayoutConstraint.constant = p.x;
    _yLayoutConstraint.constant = p.y;
}

@end

UIPanGestureRecognizerUILabel に関連付けられており、そのコールバックがビュー コントローラーの pan: メソッドに設定されています。

于 2013-10-31T18:36:40.253 に答える