많은 시행 착오 끝에 나는 포기하고 질문을하고 있습니다. 비슷한 문제를 가진 많은 사람들을 보았지만 모든 답변을 올바르게 얻을 수는 없습니다.
UITableView
커스텀 셀로 구성된을 가지고 있습니다 . 셀은 서로 옆에 5 개의 텍스트 필드로 구성됩니다 (그리드와 같은 정렬).
의 맨 아래에있는 셀을 스크롤하고 편집하려고하면 셀 UITableView
이 키보드 위에 올바르게 배치되도록 할 수 없습니다.
뷰 크기 변경 등에 대해 많은 답변을 보았지만 지금까지 아무도 잘 작동하지 않았습니다.
누구든지 구체적인 코드 예제로 이것을 수행하는 “올바른”방법을 명확히 할 수 있습니까?
답변
UIViewController 대신 UITableViewController를 사용하면 자동으로 수행됩니다.
답변
스크롤을 수행하는 기능은 훨씬 간단 할 수 있습니다.
- (void) textFieldDidBeginEditing:(UITextField *)textField {
UITableViewCell *cell;
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
// Load resources for iOS 6.1 or earlier
cell = (UITableViewCell *) textField.superview.superview;
} else {
// Load resources for iOS 7 or later
cell = (UITableViewCell *) textField.superview.superview.superview;
// TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Cell!
}
[tView scrollToRowAtIndexPath:[tView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
그게 다야. 전혀 계산이 없습니다.
답변
나는 매우 일반적인 일을하고 있으며, 코드에 특정한 것을 계산할 필요가 없습니다. 코드에서 언급을 확인하십시오.
MyUIViewController.h에서
@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableView *myTableView;
UITextField *actifText;
}
@property (nonatomic, retain) IBOutlet UITableView *myTableView;
@property (nonatomic, retain) IBOutlet UITextField *actifText;
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField;
- (IBAction)textFieldDidEndEditing:(UITextField *)textField;
-(void) keyboardWillHide:(NSNotification *)note;
-(void) keyboardWillShow:(NSNotification *)note;
@end
MyUIViewController.m에서
@implementation MyUIViewController
@synthesize myTableView;
@synthesize actifText;
- (void)viewDidLoad
{
// Register notification when the keyboard will be show
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
// Register notification when the keyboard will be hide
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
// To be link with your TextField event "Editing Did Begin"
// memoryze the current TextField
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
self.actifText = textField;
}
// To be link with your TextField event "Editing Did End"
// release current TextField
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
self.actifText = nil;
}
-(void) keyboardWillShow:(NSNotification *)note
{
// Get the keyboard size
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];
// Detect orientation
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = self.myTableView.frame;
// Start animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
// Reduce size of the Table view
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
frame.size.height -= keyboardBounds.size.height;
else
frame.size.height -= keyboardBounds.size.width;
// Apply new size of table view
self.myTableView.frame = frame;
// Scroll the table view to see the TextField just above the keyboard
if (self.actifText)
{
CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];
[self.myTableView scrollRectToVisible:textFieldRect animated:NO];
}
[UIView commitAnimations];
}
-(void) keyboardWillHide:(NSNotification *)note
{
// Get the keyboard size
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];
// Detect orientation
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = self.myTableView.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
// Increase size of the Table view
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
frame.size.height += keyboardBounds.size.height;
else
frame.size.height += keyboardBounds.size.width;
// Apply new size of table view
self.myTableView.frame = frame;
[UIView commitAnimations];
}
@end
스위프트 1.2 이상 버전 :
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var activeText: UITextField!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("keyboardWillShow:"),
name: UIKeyboardWillShowNotification,
object: nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("keyboardWillHide:"),
name: UIKeyboardWillHideNotification,
object: nil)
}
func textFieldDidBeginEditing(textField: UITextField) {
activeText = textField
}
func textFieldDidEndEditing(textField: UITextField) {
activeText = nil
}
func keyboardWillShow(note: NSNotification) {
if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
var frame = tableView.frame
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.3)
frame.size.height -= keyboardSize.height
tableView.frame = frame
if activeText != nil {
let rect = tableView.convertRect(activeText.bounds, fromView: activeText)
tableView.scrollRectToVisible(rect, animated: false)
}
UIView.commitAnimations()
}
}
func keyboardWillHide(note: NSNotification) {
if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
var frame = tableView.frame
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.3)
frame.size.height += keyboardSize.height
tableView.frame = frame
UIView.commitAnimations()
}
}
}
답변
Bartłomiej Semańczyk 솔루션을 기반으로 하는 Swift 3를 위한 가장 간단한 솔루션 :
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(CreateEditRitualViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(CreateEditRitualViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: Keyboard Notifications
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
}
}
@objc func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.2, animations: {
// For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
})
}
답변
나는 같은 문제가 있었지만 한 가지 관점에서만 나타납니다. 그래서 컨트롤러의 차이점을 찾기 시작했습니다.
스크롤 동작이 - (void)viewWillAppear:(BOOL)animated
슈퍼 인스턴스 에서 설정되어 있음을 알았습니다 .
따라서 다음과 같이 구현하십시오.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// your code
}
당신이 사용하는 경우 그리고 그것은 중요하지 않습니다 UIViewController
또는 UITableViewController
; UITableView
에 self.view의 하위 뷰로 넣어서 확인했습니다 UIViewController
. 같은 행동이었습니다. 통화 [super viewWillAppear:animated];
가 없으면 보기를 스크롤 할 수 없습니다.
답변
나는 여기에 전체 게시물을 읽지 않았으므로 이것을 놓쳤을 수도 있지만, 내가 생각해 낸 것은 기만적으로 단순 해 보입니다. 나는 이것을 모든 상황에서 테스트하는 데 wringer를 넣지 않았지만 그것이 잘 작동하는 것처럼 보입니다.
키보드의 높이로 tableview의 contentInset을 조정 한 다음 셀을 아래쪽으로 스크롤하십시오.
- (void)keyboardWasShown:(NSNotification *)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.myTableView.contentInset = contentInsets;
self.myTableView.scrollIndicatorInsets = contentInsets;
[self.myTableView scrollToRowAtIndexPath:self.currentField.indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
그리고 물론
- (void)keyboardWasHidden:(NSNotification *)aNotification
{
[UIView animateWithDuration:.3 animations:^(void)
{
self.myTableView.contentInset = UIEdgeInsetsZero;
self.myTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}];
}
너무 간단합니까? 내가 뭔가를 놓치고 있습니까? 지금까지 그것은 나를 위해 잘 작동하지만, 내가 말했듯이, 나는 그것을 wringer를 넣지 않았습니다 …
답변
애플 앱의 동작에 맞는 솔루션을 생각해 냈습니다.
먼저 viewWillAppear : 키보드 알림을 구독하면 키보드가 표시되고 숨겨지는시기를 알 수 있으며 시스템에서 키보드 크기를 알려 주지만 viewWillDisappear :에서 등록을 취소하는 것을 잊지 마십시오.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
키보드가 표시되면 보이는 영역과 일치하도록 tableView의 크기를 조정하도록 아래와 비슷한 방법을 구현하십시오. 여기에서는 키보드 상태를 개별적으로 추적하므로 모든 필드가 변경 될 때마다 알림을 받기 때문에 tableView를 전체 높이로 다시 설정할 시점을 선택할 수 있습니다. keyboardWillHide를 구현하는 것을 잊지 말고 tableView 크기를 수정하기에 적절한 곳을 선택하십시오.
-(void) keyboardWillShow:(NSNotification *)note
{
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardBounds];
keyboardHeight = keyboardBounds.size.height;
if (keyboardIsShowing == NO)
{
keyboardIsShowing = YES;
CGRect frame = self.view.frame;
frame.size.height -= keyboardHeight;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
self.view.frame = frame;
[UIView commitAnimations];
}
}
이제 스크롤 비트가 있습니다. 먼저 몇 가지 크기를 계산 한 다음 보이는 영역의 위치를 확인하고 스크롤하려는 rect를 텍스트 필드의 중간 위 또는 아래의 절반보기로 설정하십시오. 보기의 위치에 있습니다. 이 경우, UITextFields 배열과 그것들을 추적하는 열거 형이 있으므로 rowHeight에 행 번호를 곱하면이 외부 뷰 내에서 프레임의 실제 오프셋이 제공됩니다.
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
CGRect frame = textField.frame;
CGFloat rowHeight = self.tableView.rowHeight;
if (textField == textFields[CELL_FIELD_ONE])
{
frame.origin.y += rowHeight * CELL_FIELD_ONE;
}
else if (textField == textFields[CELL_FIELD_TWO])
{
frame.origin.y += rowHeight * CELL_FIELD_TWO;
}
else if (textField == textFields[CELL_FIELD_THREE])
{
frame.origin.y += rowHeight * CELL_FIELD_THREE;
}
else if (textField == textFields[CELL_FIELD_FOUR])
{
frame.origin.y += rowHeight * CELL_FIELD_FOUR;
}
CGFloat viewHeight = self.tableView.frame.size.height;
CGFloat halfHeight = viewHeight / 2;
CGFloat midpoint = frame.origin.y + (textField.frame.size.height / 2);
if (midpoint < halfHeight)
{
frame.origin.y = 0;
frame.size.height = midpoint;
}
else
{
frame.origin.y = midpoint;
frame.size.height = midpoint;
}
[self.tableView scrollRectToVisible:frame animated:YES];
}
이것은 꽤 잘 작동하는 것 같습니다.