7

高低を検索しましたが、答えが見つからないようです。私が見た中で最も近いものは次のとおりです。 フレームを変更するときに、フレームの下の UITextView カーソル

申し訳ありませんが、私には(ほとんど)評判がないため、スクリーンショットはありませんが、リンクされた SO 投稿に似ています。

iOS6 でアプリを実行すると、問題なく動作します (コンテンツはカーソルと共にスクロールして画面上に表示されます) が、iOS7 では、カーソルが UITextView の末尾を 1 行超えて移動します。コンテンツを移動するために UIEdgeInsets を追加しようとしましたが、ユーザーがテキストを積極的に入力しているときに、カーソルがテキスト ビューの末尾より下に来るまで新しい行を追加し続けます。

私のレイアウトは、Label (headerText) とその下の UITextView (textView) で構成されています。このビューは、タブ バーから表示されます。追加されたキーボード入力アクセサリがありますが、その高さは、関数が呼び出される前にキーボードの高さに自動的に計算されます。

これは、キーボードの表示/非表示デリゲート、回転、初期レイアウトなどから呼び出される、ビューのサイズを変更するために使用する関数です。

-(void)resizeViewsWithKbdHeight:(float)kbHeight
{
    //set the header label frame

    //set constraints
    //total view width - 30 (15 each for left and right padding)
    CGFloat labelWidth = ([[[self navigationController] view] bounds].size.width - 30);
    CGSize constraintSize = {labelWidth, CGFLOAT_MAX};
    //calculate needed height for header label
    CGSize textSize = [[self headerText] sizeWithFont:[UIFont systemFontOfSize:17.0f]
                                    constrainedToSize:constraintSize
                                        lineBreakMode:NSLineBreakByWordWrapping];
    //build and set frame for header label:
    //make it the same as the old
    CGRect headerTempSize = [[self headerLabel] frame];
    //except for the height
    headerTempSize.size.height = textSize.height;
    //and set it
    [[self headerLabel] setFrame:headerTempSize];

    //correct the placement of the UITextView, so it's under the header label

    //build a new frame based on current textview frame
    CGRect newFrame = [[self textView] frame];

    //get the y position of the uitextview, the +8 is the padding between header and uitextview
    CGFloat vertPadding = [[self headerLabel] frame].origin.y + [[self headerLabel] frame].size.height + 8;

    //bump it down vertically
    newFrame.origin.y = vertPadding;

    //bump things down by the amount of the navigation bar and status bar
    float offscreenBump = [[[self navigationController] navigationBar] frame].origin.y + [[[self navigationController] navigationBar] frame].size.height;

    //if we aren't showing the keyboard, add the height of the tab bar
    if(kbHeight == 0) {
        offscreenBump += [[[self tabBarController] tabBar] frame].size.height;
    }

    //calculate the new height of the textview, the +9 is for padding below the text view
    CGFloat newHeight = [[[self navigationController] view] bounds].size.height - ([[self textView] frame].origin.y + 9 + kbHeight + offscreenBump);

    //resize the height as calculated
    newFrame.size.height = newHeight;

    //set textview frame to this new frame
    [[self textView] setFrame:newFrame];
}

私は iOS5 をサポートしようとしているので、AutoLayout はありません。

私が物事をどのように行っているかについて、信じられないほどナイーブである可能性があります。

前もって感謝します!

4

2 に答える 2

7

これは iOS 7 のバグのようです。この問題を修正する唯一の方法は、UITextView のデリゲートを追加して実装しtextViewDidChangeSelection、ビューをリセットして次のように選択を表示することです。

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

- (void) textViewDidChangeSelection: (UITextView *) tView {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        [tView scrollRangeToVisible:[tView selectedRange]];
    }
}
于 2013-10-08T17:25:12.990 に答える
6

この問題に対処するための、よりハックでより効果的な方法を見つけました。

- (void)textViewDidChangeSelection:(UITextView *)textView
{
    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        if ([textView.text characterAtIndex:textView.text.length-1] != ' ') {
            textView.text = [textView.text stringByAppendingString:@" "];
        }

        NSRange range0 = textView.selectedRange;
        NSRange range = range0;
        if (range0.location == textView.text.length) {
            range = NSMakeRange(range0.location - 1, range0.length);
        } else if (range0.length > 0 &&
                   range0.location + range0.length == textView.text.length) {
            range = NSMakeRange(range0.location, range0.length - 1);
        }
        if (!NSEqualRanges(range, range0)) {
            textView.selectedRange = range;
        }
    }
}

基本的に、テキスト フィールドの末尾には常にスペースを入れるようにしています。次に、スペースが表示されるようにユーザーが選択を変更しようとした場合は、選択を変更します。常にカーソルの前にスペースを保持することで、フィールドは想定どおりにスクロールします。

最後に、必要に応じて、テキストをモデルにコピーするときに末尾のスペースを削除します (表示されていません)。

于 2013-11-13T00:07:53.890 に答える