UITextField가 첫 번째 응답자가 될 때 UIScrollView 스크롤 비활성화
UITextField
에 포함 된, UIScrollView
가 첫 번째 응답자가 될 때 사용자가 일부 문자를 입력 UIScrollView
하면 해당 필드로 자동으로 스크롤됩니다.이를 비활성화 할 수있는 방법이 있습니까?
Moshe의 대답을 바탕으로 ...
UIScrollView를 하위 클래스로 만들고 다음 메서드를 재정의합니다.
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
비워 둡니다. 완료되었습니다!
나는 같은 문제로 고심하고 있었고 마침내 해결책을 찾았습니다.
콜 트레이스를 추적하여 자동 스크롤이 어떻게 수행되는지 조사한 결과 [UIFieldEditor scrollSelectionToVisible]
.NET Framework에 문자를 입력 할 때 내부 가 호출 되는 것을 발견했습니다 UITextField
. 이 방법 UIScrollView
은의 가장 가까운 조상 에서 작동하는 것으로 보입니다 UITextField
.
따라서에서를 같은 크기의 new 로 textFieldDidBeginEditing
래핑하면 (즉, superview와 superview 사이에 뷰를 삽입 ) 자동 스크롤이 차단됩니다. 마지막으로이 래퍼를 .UITextField
UIScrollView
UITextField
textFieldDidEndEditing
코드는 다음과 같습니다.
- (void)textFieldDidBeginEditing:(UITextField*)textField {
UIScrollView *wrap = [[[UIScrollView alloc] initWithFrame:textField.frame] autorelease];
[textField.superview addSubview:wrap];
[textField setFrame:CGRectMake(0, 0, textField.frame.size.width, textField.frame.size.height)];
[wrap addSubview: textField];
}
- (void)textFieldDidEndEditing:(UITextField*)textField {
UIScrollView *wrap = (UIScrollView *)textField.superview;
[textField setFrame:CGRectMake(wrap.frame.origin.x, wrap.frame.origin.y, wrap.frame.size.width, textField.frame.size.height)];
[wrap.superview addSubview:textField];
[wrap removeFromSuperview];
}
도움이 되었기를 바랍니다!
UITextView
셀의 자동 스크롤을 비활성화하는 것과 동일한 문제가 발생했습니다 UITableView
. 다음 접근 방식을 사용하여 해결할 수있었습니다.
@interface MyTableViewController : UITableViewController<UITextViewDelegate>
@implementation MyTableViewController {
BOOL preventScrolling;
// ...
}
// ... set self as the delegate of the text view
- (void)textViewDidBeginEditing:(UITextView *)textView {
preventScrolling = YES;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (preventScrolling) {
[self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:NO];
}
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
preventScrolling = NO;
}
정의 scrollViewWillBeginDragging
는 사용자가 스크롤을 시작할 때 기본 스크롤 동작을 복원하는 데 사용됩니다.
Taketo가 언급했듯이 a UITextField
가 첫 번째 응답자로 만들어지면 유형 UIScrollView
(있는 경우 ) 인 첫 번째 상위 뷰 가 스크롤되어 UITextField
표시됩니다. 가장 쉬운 방법은 단순히 각 UITextField를 UIScrollView
하나의 더미로 감싸는 것입니다 (또는 이상적으로는 모두 하나의 더미로 감싸는 것입니다 UIScrollView
). 이것은 Taketo의 솔루션과 매우 유사하지만 약간 더 나은 성능을 제공해야하며 제 생각에는 코드 (또는 Interface Builder의 인터페이스)를 훨씬 깔끔하게 유지할 것입니다.
Luke의 대답을 바탕으로 그의 솔루션이 자동 스크롤을 완전히 비활성화하는 문제를 처리하기 위해 다음과 같이 선택적으로 비활성화 할 수 있습니다.
// TextFieldScrollView
#import <UIKit/UIKit.h>
@interface TextFieldScrollView : UIScrollView
@property (assign, nonatomic) IBInspectable BOOL preventAutoScroll;
@end
@implementation TextFieldScrollView
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
if (self.preventAutoScroll == NO) {
[super scrollRectToVisible:rect animated:animated];
}
}
@end
이렇게하면 자동 스크롤을 비활성화하도록 Interface Builder에서 완전히 설정할 수 있지만 언제든지 다시 활성화 할 수있는 모든 권한을 가질 수 있습니다.
UITextfield를 포함하는 UIScrollview처럼 보이며 콘텐츠 오프셋을 자동으로 조정합니다. 텍스트 필드가 첫 번째 응답자가 될 때. 이 문제는 먼저 동일한 크기의 scrollview에 텍스트 필드를 추가 한 다음 메인 스크롤 뷰에 추가하여 해결할 수 있습니다. 기본 scrollview에 직접 추가하는 대신
// Swift
let rect = CGRect(x: 0, y: 0, width: 200, height: 50)
let txtfld = UITextField()
txtfld.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)
let txtFieldContainerScrollView = UIScrollView()
txtFieldContainerScrollView.frame = rect
txtFieldContainerScrollView.addSubview(txtfld)
// Now add this txtFieldContainerScrollView in desired UITableViewCell, UISCrollView.. etc
self.mainScrollView.addSubview(txtFieldContainerScrollView)
// Am33T
이것이 내가하는 방법입니다.
매우 간단합니다. scrollRectToVisible에 대해 자신의 contentOffset을 반환합니다.
이렇게하면 정상적인 동작과 사물의 흐름에 해를 끼치 지 않고 동일한 채널에서 동일한 기능을 제공하고 자신의 개선 사항을 개선 할 수 있습니다.
#import <UIKit/UIKit.h>
@protocol ExtendedScrollViewDelegate <NSObject>
- (CGPoint)scrollView:(UIScrollView*)scrollView offsetForScrollingToVisibleRect:(CGRect)rect;
@end
@interface ExtendedScrollView : UIScrollView
@property (nonatomic, unsafe_unretained) id<ExtendedScrollViewDelegate> scrollToVisibleDelegate;
@end
#import "ExtendedScrollView.h"
@implementation ExtendedScrollView
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
{
if (_scrollToVisibleDelegate && [_scrollToVisibleDelegate respondsToSelector:@selector(scrollView:offsetForScrollingToVisibleRect:)])
{
[self setContentOffset:[_scrollToVisibleDelegate scrollView:self offsetForScrollingToVisibleRect:rect] animated:animated];
}
else
{
[super scrollRectToVisible:rect animated:animated];
}
}
@end
@TaketoSano의 대답을 시도했지만 작동하지 않는 것 같습니다. 제 경우에는 스크롤 뷰가없고 여러 텍스트 필드가있는 뷰만 있습니다.
그리고 마지막으로 해결 방법이 있습니다. 필요한 키보드에 대한 두 가지 기본 알림 이름이 있습니다.
UIKeyboardDidShowNotification
키보드가 표시되었을 때;UIKeyboardWillHideNotification
when the keyboard will hide.
Here's the sample code I used:
- (void)viewDidLoad {
[super viewDidLoad];
...
NSNotificationCenter * notificationCetner = [NSNotificationCenter defaultCenter];
[notificationCetner addObserver:self
selector:@selector(_keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[notificationCetner addObserver:self
selector:@selector(_keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)_keyboardWasShown:(NSNotification *)note {
[self.view setFrame:(CGRect){{272.f, 55.f}, {480.f, 315.f}}];
}
- (void)_keyboardWillHide:(NSNotification *)note {
[self.view setFrame:(CGRect){{272.f, 226.5f}, {480.f, 315.f}}];
}
Here, the (CGRect){{272.f, 226.5f}, {480.f, 315.f}}
is view's default frame when keyboard is hidden. And (CGRect){{272.f, 55.f}, {480.f, 315.f}}
is view's frame when keyboard did show.
And b.t.w., the view's frame changing will be applied animation automatically, this's really perfect!
I have a collection view with a text field at the very top, mimicking the UITableView.tableHeaderView
. This text field is located in the negative content offset space so that it doesn't interfere with the rest of the collection view. I basically am detecting whether or not the user is performing the scrolling in the scroll view and whether or not the text field is first responder and if the scroll view is being scrolled beyond the top of the scroll view's content inset. This exact code won't necessarily help anyone but they could manipulate it to fit their case.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// This is solving the issue where making the text field first responder
// automatically scrolls the scrollview down by the height of the search bar.
if (!scrollView.isDragging && !scrollView.isDecelerating &&
self.searchField.isFirstResponder &&
(scrollView.contentOffset.y < -scrollView.contentInset.top)) {
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top) animated:NO];
}
}
I don't know of any property of UIScrollView
that would allow that. It would be poor user experience to be able to disable that, IMHO.
That said, it may be possible to subclass UIScrollView
and override some of its methods to check that the UITextfield
is not a first responder before scrolling.
An easier way to stop the scrollview scrolling when you select a textField is in your viewController::viewWillAppear() DO NOT call [super viewWillAppear];
You can then control the scroll as you wish.
'IT TIP' 카테고리의 다른 글
C에서 문자열 상수를 어떻게 선언합니까? (0) | 2020.12.03 |
---|---|
일부 Python 코드의 형식을 올바르게 지정하려면 어떻게해야합니까? (0) | 2020.12.03 |
Android : 프로그래밍 방식으로 선택기 (StateListDrawable)를 업데이트하는 방법 (0) | 2020.12.03 |
Django-정적 파일을 찾을 수 없습니다. (0) | 2020.12.03 |
LESS 파일에 대한 공통 이미지 경로를 설정하는 방법이 있습니까? (0) | 2020.12.03 |