iOS5 切换中文键盘时覆盖输入框的完美解决方案

copy from http://www.apkbus.com/blog-107838-44715.html

众所周知,iOS5之前,iPhone上的键盘的高度是固定为216.0px高的,中文汉字的选择框是悬浮的,所以不少应用都将此高度来标注键盘的高度(包括米聊也是这么做的)。

可是在iOS5中,键盘布局变了,尤其是中文输入时,中文汉字选择框就固定在键盘上方,这样就使得原本与键盘紧密贴合的界面视图被中文汉字选择框给覆盖住了。一方面影响了界面的美观,另一方面,如果被覆盖的部分就是文本输入框的话,用户就无法看到输入的内容了。因此这个问题就必须得解决了。

解决方法

其实在一开始使用216.0px这个固定值来标注键盘的高度就是错误的。因为在iOS3.2以后的系统中,苹果就提供了键盘使用的API以及Demo程序——“KeyboardAccessory”。

处理键盘事件的正确方法是这样的:(包括获取键盘的位置以及键盘弹出和消失动画的时间)

1)在要使用键盘的视图控制器中(既viewDidLoad中),接收键盘事件的通知:

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

// 键盘高度变化通知,ios5.0新增的
#ifdef __IPHONE_5_0
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 5.0) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
#endif

2)然后添加键盘事件的处理代码:

获取到当前keyboard的高度以及动画时间,然后对视图进行对应的操作即可。

#pragma mark –
#pragma mark Responding to keyboard events
– (void)keyboardWillShow:(NSNotification *)notification {

/*

Reduce the size of the text view so that it’s not obscured by the keyboard.

Animate the resize so that it’s in sync with the appearance of the keyboard.

*/

NSDictionary *userInfo = [notification userInfo];

// Get the origin of the keyboard when it’s displayed.

NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];

// Get the top of the keyboard as the y coordinate of its origin in self’s view’s coordinate system. The bottom of the text view’s frame should align with the top of the keyboard’s final position.

CGRect keyboardRect = [aValue CGRectValue];

// Get the duration of the animation.

NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];

NSTimeInterval animationDuration;

[animationDurationValue getValue:&animationDuration];

// Animate the resize of the text view’s frame in sync with the keyboard’s appearance.

[UIView animateWithDuration:animationDuration animations:^{

//此处的viewFooter即是你的输入框View

//20为状态栏的高度

self.viewFooter.frame = CGRectMake(viewFooter.frame.origin.x, keyboardRect.origin.y-20-viewFooter.frame.size.height,viewFooter.frame.size.width, viewFooter.frame.size.height);

} completion:^(BOOL finished){

}];

}

– (void)keyboardWillHide:(NSNotification *)notification {

NSDictionary* userInfo = [notification userInfo];

NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];

CGRect keyboardRect = [aValue CGRectValue];

/*

Restore the size of the text view (fill self’s view).

Animate the resize so that it’s in sync with the disappearance of the keyboard.

*/

[UIView animateWithDuration:0 animations:^{

self.viewFooter.frame = CGRectMake(viewFooter.frame.origin.x, keyboardRect.origin.y-20-viewFooter.frame.size.height, viewFooter.frame.size.width, viewFooter.frame.size.height);

} completion:^(BOOL finished){

}];

}  3)在视图控制器消除时(即viewDidUnload中),移除键盘事件的通知:

[[NSNotificationCenter defaultCenter] removeObserver:self];

背景:

ios5之前,iphone上的键盘的高度是固定为216.0px高的,中文汉字的选择框是悬浮的,所以不少应用都将此高度来标注键盘的高度。

可是在ios5中,键盘布局变了,尤其是中文输入时,中文汉字选择框就固定在键盘上方,这样就使得原本与键盘紧密贴合的界面视图被中文汉字选择框给覆盖住了。一方面影响了界面的美观,另一方面,如果被覆盖的部分就是文本输入框的话,用户就无法看到输入的内容了。因此这个问题就必须得解决了。

解决方法:

其实在一开始使用216.0px这个固定值来标注键盘的高度就是错误的。因为在ios3.2以后的系统中,苹果就提供了键盘使用的api以及demo程序——“KeyboardAccessory”。

处理键盘事件的正确方法是这样的:(包括获取键盘的高度以及键盘弹出和消失动画的时间)

 

1)在要使用键盘的视图控制器中,接收键盘事件的通知:

复制代码
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

        // 键盘高度变化通知,ios5.0新增的  
#ifdef __IPHONE_5_0
        float version = [[[UIDevice currentDevice] systemVersion] floatValue];
        if (version >= 5.0) {
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil];
        }
#endif
复制代码

 

2)然后添加键盘事件的处理代码:

获取到当前keyboard的高度以及动画时间,然后对视图进行对应的操作即可。

复制代码
#pragma mark -
#pragma mark Responding to keyboard events
- (void)keyboardWillShow:(NSNotification *)notification {
    
    /*
     Reduce the size of the text view so that it's not obscured by the keyboard.
     Animate the resize so that it's in sync with the appearance of the keyboard.
     */
    
    NSDictionary *userInfo = [notification userInfo];
    
    // Get the origin of the keyboard when it's displayed.
    NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
    
    // Get the top of the keyboard as the y coordinate of its origin in self's view's coordinate system. The bottom of the text view's frame should align with the top of the keyboard's final position.
    CGRect keyboardRect = [aValue CGRectValue];
    
    // Get the duration of the animation.
    NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval animationDuration;
    [animationDurationValue getValue:&animationDuration];
    
    // Animate the resize of the text view's frame in sync with the keyboard's appearance.
    [self moveInputBarWithKeyboardHeight:keyboardRect.size.height withDuration:animationDuration];
}


- (void)keyboardWillHide:(NSNotification *)notification {
    
    NSDictionary* userInfo = [notification userInfo];
    
    /*
     Restore the size of the text view (fill self's view).
     Animate the resize so that it's in sync with the disappearance of the keyboard.
     */
    NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval animationDuration;
    [animationDurationValue getValue:&animationDuration];
    
    [self moveInputBarWithKeyboardHeight:0.0 withDuration:animationDuration];
}
复制代码

3)在视图控制器消除时,移除键盘事件的通知:

[[NSNotificationCenter defaultCenter] removeObserver:self];

ps:

ios5隐藏功能分享——“字典”功能(英英字典):

在任何输入框中选中一个英文单词,此时会有选择项“复制”,“删除”…等,还有一个向右的箭头,点击这个向右的箭头后,就会出现“定义”选项,点击这个“定义”按钮即会弹出这个英语单词的英文解释。

 

 

首先,你得监听键盘的事件,最基本的两个事件:

UIKeyboardWillShowNotification

UIKeyboardWillHideNotification

UIKeyboard…

iOS 5新增加了一些

UIKeyboardDidChangeFrameNotification(will)

一般情况下,前两个事件已经可以完成你要做的事情。在你的事件处理方法中加上NSNotification参数可以为你获得更多的东西:

view plainprint?

– (void)keyboardWillShow:(NSNotification *)notification

{

CGPoint beginCentre = [[[notification userInfo] valueForKey:UIKeyboardCenterBeginUserInfoKey] CGPointValue];

CGPoint endCentre = [[[notification userInfo] valueForKey:UIKeyboardCenterEndUserInfoKey] CGPointValue];

CGRect keyboardBounds = [[[notification userInfo] valueForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];

CGRect keyboardFrames = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

UIViewAnimationCurve animationCurve = [[[notification userInfo] valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

NSTimeInterval animationDuration = [[[notification userInfo] valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

}

如果你要在程序中使用键盘的高度和宽度,永远不要尝试去手动指定,动态获取也很简单而且一定准确,不会出现键盘

挡住输入框的问题。

你可以利用这些参数把动画做的和键盘一致。假设你要把一个控件放在Window上,并且想让它的交互方式和键盘一样,

如果只是简单的做个向下偏移动画并不能很好的完成,因为你还要考虑从导航栏中Pop出来的时候,这个时候的键盘动画是

在x轴上偏移的,你用UIKeyboardFrameEndUserInfoKey获取的frame可以很准确的做到。

 

如果在某些特殊的字段上,你不想用默认的键盘,而是用类似于Picker这样的拾取器,你只需要设置inputView就行了,用你自定义的视图去替换掉键盘;如果你想在键盘上面再增加一个视图,比如toolbar,那么你可以不用自己对toolbar的位置进行控制,只需要设置inputAccessoryView就行了,这个值默认为nil,设置的视图将在你的控件变成第一响应者的时候显示在inputView的上方。

\\

 

在UIScrollView(UITableView继承于它)上,当你触碰控件使之变成第一响应者的时候,系统会自动调整位置,避免键盘挡住控件。如果在代码中用becomeFirstResponder使之变成第一响应者将不会出现自动调整。你可以设置contentOffset去手动调整。其他视图,最简单的方法就是修改控件的frame属性,让控件总是显示在可见区域。

 

 

IOS键盘事件记

IOS5.0之前不支持键盘sizechange事件(5.0之前键盘尺寸一直保持不变),而5.1居然在键盘size改变时无法正常发出通知。所以要想捕获键盘尺寸变化的事件,可以在键盘didShow事件里通过beginSize和endSize和判断。

 

如果想让UI随着键盘的变化而变化(动画一致),需要在willshow及willhide里加入动画代码。动画的两个参数需要和键盘同步(animationDuration和animationCurve)。

获取键盘的动画参数:

NSDictionary *info = [notification userInfo];

NSTimeInterval duration = 0;

UIViewAnimationCurve curve;

[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];

[[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];

 

duration在默认【中文拼音输入法】弹出时,不能正确获取duration,需要加一行代码修正:

duration = (duration > 0 ? duration: 0.25);//已知,IOS5.0.1里面键盘弹出动画的0.25S的,瑕疵:如果这里动画时间不是0.25就有可能动画不同步了

 

【Updated at 2012-05-12】键盘处于显示状态的UIViewController被UINavigationController pop出去时,也会发出 UIKeyboardWillHideNotification通知,只不过这个键盘隐藏的轨迹是【从左到右的滑动】而不是从上到下的收起。所以,如果想在这个通知的响应代码里去调整UI(比如恢复底部工具条的origin.y使其始终居于底部),应该避免横向滑动键盘消失这种情况。可以通过以下响应代码来鉴别是否横向滑动导致键盘消失:

NSDictionary *info = [notification userInfo];

CGPoint kbEndOrigin = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin;

if(kbEndOrigtin.x > 0) {//横向滑动导致了键盘消失,不必调整UI

return;

}

//恢复UI显示

Multithreading with Core Data on iOS

This post is copied from http://cutecoder.org/programming/multithreading-core-data-ios/

A while ago I recommended not to multithread at all with Core Data. That was true during Snow Leopard’s days. But with the advent of context hierarchy and the pervasive use of blocks on Lion and iOS 5, multi-threading with Core Data becomes approachable.

As I was working on Resonate, I discovered a number of lessons on writing multithreaded applications on iOS. A lot of these lessons were discovered “the hard way” – through misguided attempts and many crashes. I’d thought I share this with you so that you don’t need to go through the same mistakes.

Even though I use the word “multithreading”, chances are you won’t need to deal with threads directly. Using operation queues is the way to go for most of your multiprocessing mechanisms. Simply package your algorithms into distinct units of work and then let NSOperationQueuemanage them for you. Don’t create NSThread instances directly unless you have a pretty damn good reason why.

Use UIManagedDocument for Core Data apps on iOS.

Really, when you’re writing iOS 5 applications that uses Core Data, you’ll want to use UIManagedDocument. At a bare minimum, use this class to manage your Core Data stack. That is, let core data manage your instances of NSManagedObjectContextNSPersistentStoreCoordinator, and other parts of the Core Data stack.

Even if you need to share your Core Data classes with your Mac app, you can still separate your entity classes that will work accross both platforms. If you think that UIManagedDocument isn’t good enough for your app, you’d better have a damn good reason why.

When you use UIManagedDocument, you’ll get a set of interrelated NSManagedObjectContext instances. Amain context that you use as per normal with your GUI objects and the root context, which is the main context’s parent that are used for asynchronously saving data to persistent storage. When dealing with object contexts created by UIManagedDocument you should not save them directly – you’ll bypass undo management and a lot of other behind-the-scenes stuff. UIManagedDocument will periodically save these for you in the correct order.

Use the managed object context hierarchy

From this building block, I go further to recommend a pattern for using the new context hierarchy. I discovered this works nicely on iOS when I was working on Resonate.

  • Use the root context for saving data obtained by network refreshes.
  • Use the main context for GUI components and others that needs to be in the main thread.
  • Create individual worker contexts as children of the main context for background data processing tasks.

Core data context use

Use the Root Context for Network Refreshes

Being a Twitter client, Resonate often need to ask Twitter for the latest tweets and other data. When Twitter returns and Resonate parsed the resulting JSON data, it then invokes the root context’s operation queue to store the parsed JSON data into managed objects.

You can use this pattern yourself. You run network operations asynchronously, parse the resulting data, and then when you’re ready to store it you call performBlock on the root context.

You can see the pattern in the sequence diagram below. Typically the user initiates the refresh from an action in the view controller. If you use ASIHTTPRequest for your network I/O, you can make it run asynchronously. When the request is complete, you pass the raw data into an operation queue for parsing (note that +[ASIHTTPRequest sharedQueue] is convenient for this). When the data is parsed, you make use of the root context’s private queue to update the data to your managed objects. Upon completion of the update, you pass the object IDs of the updated objects back to your view controller in the main thread. Please take care not to pass the actual managed object instances between operation queues as this will certainly cause problems.

Network Refresh Pattern

One caveat of this approach is that you need to separate network-sourced data with user-edited data. That is attributes that can be updated from the network should not be editable by the user. This is to prevent conflicts when UIManagedDocument tries to saves your contexts.

Use Multiple Child Contexts for Worker Queues

If you need to do some long-running data processing, you should run those in a background operation queue and not in the main thread. But really to make your app responsive, anything that may take longer than half a second should be taken off the main thread – especially important in iOS devices where the CPU is a lot slower than the one found in OS X machines.

Those background operations should use their own private NSManagedObjectContext instances. I also recommend that these contexts are set as children of the main context. Why? Because when the operation completes and the context is saved then the results are “pushed” into the main context. This also rescues the GUI from having to refresh its NSManagedObjectContext to get the updated objects. Since you create these contexts yourself, you are responsible for saving them – unlike the main and root contexts that are owned by UIManagedDocument.

How to use it? Refer to the interaction diagram below. Typically the view controller creates the worker operation class (which is an instance of NSOperation). As part of the worker’s initial setup regime, the view controller provides its context as the parent context for use by the worker object. Then when the worker starts it creates its own private NSManagedObjectContext instance and use that context as it’s scratchpad data store. Just before the worker completes, it saves the context to push its changes to the main thread’s context.

Core Data for Background Processing

Conclusion

You now know how to multi-thread effectively in Core Data applications. Although this article focuses on iOS, you should be able to apply the same principles to OS X. You have learned about:

  • Using UIManagedDocument for managing your Core Data stack
  • The new NSManagedObjectContext hierarchy (nested contexts)
  • How use each level in the context hierarchy for different operation types (network refresh, main/GUI thread, worker operation).

WRA a English learning iphone app.

https://itunes.apple.com/us/app/wra/id599894126?ls=1&mt=8

WRA(Weekly Radio Address) is a English learning application, which is easy-to-use and elegant. Using this app everyday will improve both your listening and reading skills. It also help you to correct your pronunciation.

It is featuring weekly discussion of current events and education of important issues by the President of the United States, one of best resources for English learning.  Updated every Saturday morning!

It can learn at any time, any place you like even in the absence of internet access by downloading the audio and transcript to your device.

◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆

★ Features

◆ Latest Weekly Radio Address News.

◆ Watching the video or listening the audio online

◆ Download audio and transcript for offline listening and reading.

◆ Management the download items.

◆ Share to Twitter, Facebook, Sina Weibo

◆ Load More items.

◆ Show download progress and can be cancelled.

◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆

This is ideal for

◆ learning current events and education of important issues in the US

◆ Self – Study English

◆ International visitors seeking to improve their American English language skills

◆ People considering studying in the United States

◆ ESL / English tutors

Thank you all for your continued support! 

If you have comments or suggestions to help us make it better, please let us know by leaving a review!

★ Notice

◆ The videos in the app are from YouTube. If you can’t connect YouTube in your region, the videos can’t play.

◆ If you don’t have enough free spaces on your device, iOS will automatically delete your downloaded audios, you have to  re-download them. This is the system rule!