2012-10-04 20 views
25

आईओएस 6 में ऑटो लेआउट पर फोकस देखते हुए, और ऐप्पल इंजीनियरों की सिफारिश (डब्ल्यूडब्ल्यूडीसी 2012 वीडियो देखें) कि हम अब सीधे एक विचार 'फ्रेम में हेरफेर नहीं करते हैं, कोई कैसे बचने के बारे में जाएगा कीबोर्ड केवल ऑटो लेआउट और NSLayoutConstraint का उपयोग कर?UIKeyboard से बचने और ऑटो लेआउट

अद्यतन

यह एक उचित समाधान की तरह दिखता है: An example of keyboard sensitive layout (GitHub source) लेकिन एक संभावित मुद्दा मैं देखो क्या होता है जब कोई उपयोगकर्ता डिवाइस घूमता है और कुंजीपटल स्क्रीन पर पहले से ही है जब है

+0

लिंक से उदाहरण लें तो मैं की गणना 'keyboardHeight' के लिए बाहर कोड refactor हैं और' willRotateToInterfaceOrientation जोड़ें: 'और/या' willAnimateRotationToInterfaceOrientation: 'कीबोर्ड ऊंचाई बाधा अद्यतन करने के लिए के रूप में उपयुक्त कहता है। –

+1

'UIKeyboardWillShowNotification' अधिसूचना तब भी पोस्ट की जाती है जब कीबोर्ड का आकार रोटेशन के कारण बदलता है, इसलिए आपको इसके बारे में चिंता करने की आवश्यकता नहीं है। रोचक लिंक – omz

+0

+1 यह ऑटोलायआउट के साथ संपादन फ़ॉर्म को संभालने के लिए एक सुरुचिपूर्ण समाधान है। – memmons

उत्तर

6

मेरा विचार UIView बनाना है, चलिए इसे कीबोर्ड दृश्य पर कॉल करें, और इसे अपने दृश्य नियंत्रक के दृश्य में रखें। फिर कीबोर्ड फ्रेम परिवर्तन अधिसूचनाएं UIKeyboardDidChangeFrameNotification देखें और कीबोर्ड दृश्य पर कीबोर्ड के फ्रेम से मिलान करें (मैं परिवर्तन को एनिमेट करने की अनुशंसा करता हूं)। इस अधिसूचना को देखते हुए आपके द्वारा वर्णित रोटेशन को नियंत्रित किया जाता है और आईपैड पर कीबोर्ड भी बढ़ता है।

फिर इस कीबोर्ड दृश्य के सापेक्ष अपनी बाधाएं बनाएं। अपने सामान्य पर्यवेक्षण में बाधा जोड़ने के लिए मत भूलना।

कुंजीपटल फ्रेम को सही ढंग से अनुवादित करने और आपके दृश्य निर्देशांक में घूमने के लिए UIKeyboardFrameEndUserInfoKey के लिए दस्तावेज़ देखें।

+0

इस तरह से प्रॉक्सी दृश्य का उपयोग करना वास्तव में अच्छा काम करता है; महान विचार! –

+1

मैंने इस तरह के एक दृश्य को लागू किया है, इसका उपयोग करने के लिए स्वतंत्र भरें: 3 https://gist.github.com/safareli/d9270e7faaad3f8d151c – Safareli

+1

मैंने एक पुस्तकालय लिखा है जो यह आपके लिए सब कुछ करेगा (ऑटो लेआउट और स्प्रिंग्स और स्ट्रूट्स का समर्थन करता है) https://github.com/IdleHandsApps/IHKeyboardAvoiding – Fraser

-1

ऑटो के लिए? कीबोर्ड केस के साथ लेआउट, मैं स्थिर तालिका दृश्य का उपयोग करता हूं। यह आपके कोड को बहुत आसान रखता है और कीबोर्ड की ऊंचाई को ट्रैक रखने की आवश्यकता नहीं है। तालिका दृश्य के बारे में मैंने जो कुछ सीखा है, वह प्रत्येक तालिका पंक्ति को यथासंभव संकीर्ण रखना है। यदि आप बहुत अधिक डालते हैं एक पंक्ति में लंबवत यूआई, आप कीबोर्ड ओवरलैप प्राप्त कर सकते हैं।

+0

के लिए –

5

मैंने इस तरह का एक दृश्य बनाया जो कीबोर्ड को देखेगा और स्क्रीन पर स्क्रीन चालू होने पर अपनी बाधाओं को बदल देगा।

@interface YMKeyboardLayoutHelperView() 
@property (nonatomic) CGFloat desiredHeight; 
@property (nonatomic) CGFloat duration; 
@end 

@implementation YMKeyboardLayoutHelperView 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.translatesAutoresizingMaskIntoConstraints = NO; 

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:@"UIKeyboardWillShowNotification" object:nil]; 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:@"UIKeyboardWillHideNotification" object:nil]; 
    } 
    return self; 
} 

- (void)keyboardWillShow:(NSNotification *)notification 
{ 
    // Save the height of keyboard and animation duration 
    NSDictionary *userInfo = [notification userInfo]; 
    CGRect keyboardRect = [userInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue]; 
    self.desiredHeight = CGRectGetHeight(keyboardRect); 
    self.duration = [userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] floatValue]; 

    [self setNeedsUpdateConstraints]; 
} 

- (void)keyboardWillHide:(NSNotification *)notification 
{ 
    // Reset the desired height (keep the duration) 
    self.desiredHeight = 0.0f; 

    [self setNeedsUpdateConstraints]; 
} 

- (void)updateConstraints 
{ 
    [super updateConstraints]; 

    // Remove old constraints 
    if ([self.constraints count]) { 
     [self removeConstraints:self.constraints]; 
    } 

    // Add new constraint with desired height 
    NSString *constraintFormat = [NSString stringWithFormat:@"V:[self(%f)]", self.desiredHeight]; 
    [self addVisualConstraints:constraintFormat views:@{@"self": self}]; 

    // Animate transition 
    [UIView animateWithDuration:self.duration animations:^{ 
     [self.superview layoutIfNeeded]; 
    }]; 

} 

- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

@end 
7

वह ब्लॉग पोस्ट बहुत अच्छा है, लेकिन मैं इसमें कुछ सुधार सुझा सकता हूं। सबसे पहले, आप फ्रेम परिवर्तनों का निरीक्षण करने के लिए पंजीकरण कर सकते हैं, इसलिए आपको शो और छुपाएं नोटिफिकेशन दोनों का निरीक्षण करने के लिए पंजीकरण करने की आवश्यकता नहीं है। दूसरा, आपको निर्देशांक देखने के लिए स्क्रीन से कुंजीपटल के लिए सीजीआरईटी को परिवर्तित करना चाहिए। अंत में, आप कुंजीपटल के लिए आईओएस द्वारा उपयोग किए जाने वाले सटीक एनीमेशन वक्र की प्रतिलिपि बना सकते हैं, इसलिए कीबोर्ड और ट्रैकिंग दृश्य सिंक्रनाइज़ेशन में जाते हैं।

यह सबको एक साथ रखें, तो आपको निम्न मिलता है:

@interface MyViewController() 
// This IBOutlet holds a reference to the bottom vertical spacer 
// constraint that positions the "tracking view",i.e., the view that 
// we want to track the vertical motion of the keyboard 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomVerticalSpacerConstraint; 
@end 


@implementation MyViewController 
-(void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // register for notifications about the keyboard changing frame 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(keyboardWillChangeFrame:) 
               name:UIKeyboardWillChangeFrameNotification 
              object:self.view.window]; 
} 

-(void)keyboardWillChangeFrame:(NSNotification*)notification 
{ 
    NSDictionary * userInfo = notification.userInfo; 
    UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] intValue]; 
    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 

    // convert the keyboard's CGRect from screen coords to view coords 
    CGRect kbEndFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] 
            fromView:self.view.window]; 
    CGRect kbBeginFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] 
             fromView:self.view.window]; 
    CGFloat deltaKeyBoardOrigin = kbEndFrame.origin.y - kbBeginFrame.origin.y; 

    // update the constant factor of the constraint governing your tracking view 
    self.bottomVerticalSpacerConstraint.constant -= deltaKeyBoardOrigin; 
    // tell the constraint solver it needs to re-solve other constraints. 
    [self.view setNeedsUpdateConstraints]; 

    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:duration]; 
    [UIView setAnimationCurve:animationCurve]; 
    [UIView setAnimationBeginsFromCurrentState:YES]; 
    // within this animation block, force the layout engine to apply 
    // the new layout changes immediately, so that we 
    // animate to that new layout. We need to use old-style 
    // UIView animations to pass the curve type. 
    [self.view layoutIfNeeded]; 
    [UIView commitAnimations]; 
} 

-(void)dealloc { 
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:UIKeyboardWillChangeFrameNotification 
               object:nil]; 
} 
@end 

यह काम करेंगे, जब तक आप ओरिएंटेशन बदलने नहीं है, जबकि कुंजीपटल निर्भर है।

How to mimic Keyboard animation on iOS 7 to add "Done" button to numeric keyboard? पर यह एक उत्तर था कि कुंजीपटल एनीमेशन वक्र की नकल कैसे करें।

इन सभी अधिसूचना-आधारित समाधानों के संबंध में सावधान रहना एक आखिरी बात है: यदि आपके ऐप में कुछ अन्य स्क्रीन कीबोर्ड का भी उपयोग करती है तो वे अप्रत्याशित प्रभाव उत्पन्न कर सकते हैं, क्योंकि आपका व्यू कंट्रोलर तब भी अधिसूचनाएं प्राप्त करेगा जब तक कि आपका व्यू कंट्रोलर तब तक अधिसूचनाएं प्राप्त करेगा को हटाया नहीं गया है, भले ही इसका विचार उतार दिया गया हो। इसके लिए एक उपाय अधिसूचना हैंडलर में एक सशर्त डालना है ताकि यह सुनिश्चित किया जा सके कि दृश्य नियंत्रक स्क्रीन पर ही काम करता है।

+0

कई सूचनाओं को देखने में पंजीकृत होना चाहिए WillAppear और दृश्य में अनियंत्रित WillDisappear। –

+0

@StevenKramer यह मेरी धारणा है कि (1) viewWillAppear और viewWillDisappear विश्वसनीय रूप से संतुलित कॉल नहीं हैं, और (2) यह दृश्य विशेष रूप से विल्लएपियर को कई परिस्थितियों में नहीं कहा जाता है जब दृश्य दृश्यमान होता है (ऐप सक्रिय होता है, इत्यादि)। तो मुझे यकीन नहीं है कि अधिसूचनाओं का प्रबंधन करने के लिए उनका उपयोग कैसे किया जाए। क्या आपके मन में कुछ विशिष्ट है? – algal

+0

यह बहुत कुछ होता था, लेकिन इन दिनों ऐसी समस्या नहीं है (आईओएस 5+)। वास्तव में, यदि आपके पास अभी भी असंतुलित उपस्थिति संदेश हैं, तो मैं कहूंगा कि आपको तुरंत इसे ठीक करना चाहिए। या इसके चारों ओर काम करें, अगर यह एक ढांचा मुद्दा है। –

1

Ive एक पुस्तकालय है कि यह सभी के लिए आप (समर्थन करता है, ऑटो लेआउट और स्प्रिंग्स & Struts) करना होगा लिखा

IHKeyboardAvoiding https://github.com/IdleHandsApps/IHKeyboardAvoiding

बस फोन [IHKeyboardAvoiding setAvoidingView: self.myView];

6

ढांचे में KeyboardLayoutConstraint का उपयोग करना अब तक का सबसे आसान समाधान है। KeyboardLayoutConstraint

+1

+1, क्योंकि यह सभी मामलों के लिए सबसे अच्छा समाधान नहीं है, लेकिन यदि आपकी परियोजना पहले ही स्प्रिंग ढांचे का उपयोग कर रही है, तो यह जाने का तरीका है। –

+0

ढांचे का उपयोग करने की कोई ज़रूरत नहीं है, बस अपनी परियोजना में कीबोर्डलायआउट कॉन्स्ट्रेनट.विफ्ट फ़ाइल की प्रतिलिपि बनाएँ और इसे – Nirri

+0

पर उपयोग करें, इस रणनीति का उपयोग करने वाले लोगों को सावधानी बरतें, कीबोर्डलायआउट कॉन्स्ट्रेनट ब्लूटूथ कीबोर्ड नोटिफिकेशन को सही तरीके से संभाल नहीं पाता है। समाधान के लिए यहां देखें: http://stackoverflow.com/questions/32319697/view-aligned-to-top-of-keyboard-appears-in-wrong-place-in-ios-9-shortcut-bar-onl – elprl

संबंधित मुद्दे