寫在前面
我們應該都有用過這個功能,你的朋友微信給你分享了一個淘寶里面的商品鏈接,然后當你復制這個鏈接打開淘寶APP的時候,就會彈出一個彈窗,像這樣:
example.PNG
這個功能想必大家都挺熟悉,受這個啟發(fā)我們產(chǎn)品也想在我們APP上添加這樣一個功能,與這個不一樣的是,當我們復制一段網(wǎng)址的時候打開我們的APP會彈出框填一些信息后上傳到我們的“資源庫”。大體功能就這樣,所以記錄一下實現(xiàn)的過程。
一、彈窗視圖功能
.h中:兩個信號一個是確定信號一個是取消信號
兩個方法,一個顯示一個隱藏方法
@property (nonatomic, strong) RACSubject *uploadSureSignal;//確定上傳信號
@property (nonatomic, strong) RACSubject *hideSucSignal;//隱藏
- (void)show;
- (void)hide;
.m中:主要是兩個textview,還有涉及到在keywindow上,IQKeyboard的一些操作
@property (nonatomic, assign) CGFloat keyboardHeight;//鍵盤高度
@property (nonatomic, strong) CustomUITextView *nameTV;
@property (nonatomic, strong) CustomUITextView *desTV;
因為發(fā)現(xiàn)IQKeyboard在這個彈出界面有問題,所以在顯示這個界面的時候,將IQKeyboard禁用取之使用系統(tǒng)的keyboard監(jiān)聽方法
在(void)show方法中:
-(void)show {
//鍵盤通知
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self selector:@selector(keyboardWillShowOrHide:) name:UIKeyboardWillShowNotification object:nil];
[defaultCenter addObserver:self selector:@selector(keyboardWillShowOrHide:) name:UIKeyboardWillHideNotification object:nil];
}
//監(jiān)聽方法
- (void)keyboardWillShowOrHide:(NSNotification *)notification {
//獲取通知名
NSString *notificationName = notification.name;
//獲取通知內(nèi)容
NSDictionary *keyboardInfo = notification.userInfo;
//鍵盤彈出時,讓畫面整體稍稍上移,并伴隨動畫
//鍵盤回收時反之
CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat height = keyboardFrame.size.height;
self.keyboardHeight = height;
//動畫結(jié)束后self.view的frame值
CGRect selfViewFrame = self.bgView.frame;
//通過通知名字判斷彈出還是回收
if ([notificationName isEqualToString:UIKeyboardWillShowNotification]) {
selfViewFrame.origin.y = SCREEN_HEIGHT - PANELHEIGHT - height;
} else {
selfViewFrame.origin.y = SCREEN_HEIGHT - PANELHEIGHT;
}
//取出動畫時長
NSTimeInterval duration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
//使用動畫更改self.view.frame
[UIView animateWithDuration:duration animations:^{
//這里填入一些view的最終狀態(tài)屬性設置,即會自動產(chǎn)生過渡動畫
self.bgView.frame = selfViewFrame;
}];
}
同時在show方法中顯示keyWindow,進而改變界面的frame進行顯示
- (void)show {
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
[keyWindow addSubview:self];
CGRect frame = self.bgView.frame;
if (frame.origin.y == SCREEN_HEIGHT) {
frame.origin.y = SCREEN_HEIGHT - PANELHEIGHT;
[UIView animateWithDuration:0.4 animations:^{
self.bgView.frame = frame;
}];
}
hide方法這里要考慮到鍵盤彈出后將self.bgView向上提高后frame的變化。
CGRect selfFrame = self.bgView.frame;
if (selfFrame.origin.y == SCREEN_HEIGHT - PANELHEIGHT || selfFrame.origin.y == SCREEN_HEIGHT - PANELHEIGHT - self.keyboardHeight) {
[self resignFirstResponder];
selfFrame.origin.y = SCREEN_HEIGHT;
[UIView animateWithDuration:0.4 animations:^{
self.bgView.frame = selfFrame;
} completion:^(BOOL finished) {
[IQKeyboardManager sharedManager].enable = YES;
[[NSNotificationCenter defaultCenter] removeObserver:self];
// [self.hideSucSignal sendNext:nil];
[self removeFromSuperview];
}];
}
delegate中的操作
這里首先要弄懂APPdelegate中的這幾個代理方法的意思:
//App已經(jīng)啟動
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
//App掛起狀態(tài)
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
//APP進入后臺
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
//APP將重新回到前臺
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
//APP進入活躍狀態(tài)
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
//系統(tǒng)時間發(fā)生改變時執(zhí)行
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
在上面的這些代理方法中,我們需要用到的是 applicationDidBecomeActive方法。在這個方法中我們?nèi)z查系統(tǒng)的粘貼板UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
if (pasteboard.string) {
NSLog(@"string:%@", pasteboard.string);
NSString *urlStr = pasteboard.string;
if ([urlStr hasPrefix:@"https://"] || [urlStr hasPrefix:@"http://"]) {
//如果粘貼板中的字符串包含https或http字段,我們?nèi)z查當前的控制器 如果當前的控制器是我們彈出做操作的控制器的話 isPopVC = NO;
BOOL isPopVC = NO;
UIViewController * Rootvc = self.window.rootViewController;
if ([Rootvc isKindOfClass:[UINavigationController class]]) {
UINavigationController * nav = (UINavigationController *)Rootvc;
UIViewController * v = [nav.viewControllers lastObject];
if ([v isKindOfClass:[UploadResCofingVC class]]) {
isPopVC = YES;
}
}
//如果popView == nil 并且isPopVC == NO 彈出popView彈窗視圖 進行操作
if (!self.popView && !isPopVC) {
UploadResourcesPopupView *popView = [UploadResourcesPopupView new];
[popView show];
self.popView = popView;
[self.popView.hideSucSignal subscribeNext:^(id x) {
@strongify(self);
self.popView = nil;
}];
}
}
}
}
總結(jié)
以上大體就是實現(xiàn)這個功能的基本思路,細節(jié)方面因項目而異了,比如我們需要判斷當前用戶的角色,當前用戶是否登錄,對彈窗視圖后續(xù)的一些操作。當然并不完美,歡迎批評指正。