天天看點

ios 開發過程中遇到的問題(一)UITabBar隐藏、鍵盤隐藏、tap手勢和UItavleView點選沖突、cell背景色覆寫按鈕顔色

1、關于UITabBar的隐藏

剛開始一直是使用 [self.tabBarController.tabBar setHidden:NO]; 對tabBar 進行隐藏的,這個代碼在一般情況确實能實作隐藏的效果,但是什麼情況下會有問題呢?

當控件(比如button)靠近螢幕底部的時候,無法觸發事件,這個問題糾結了好久,也請教了許多前輩,後來我也上網差了些資料,終于,找到原因了. 就是tabBar 的隐藏問題導緻的.雖然tabBar欄被隐藏了,但在隐藏的區域會成為一片空白區,無法被其他視圖使用。這也就是為何button不響應時間的原因了.

解決辦法:self.hidesBottomBarWhenPushed = YES; (但是要注意使用的時機,應該在視圖push 前就設定隐藏,在pop 前設定為NO)

2、關于鍵盤遮擋輸入框的問題

首先推薦個第三方 IQKeyboardManager

鍵盤遮擋有三種情況:

  • 輸入框在view上面
  • 輸入框在UITableView上面
  • 點選輸入框鍵盤不需要出現

    針對第一種情況:

自定方法 ,用于移動視圖

-(void)moveInputBarWithKeyboardHeight:(float)_CGRectHeight withDuration:(NSTimeInterval)_NSTimeInterval;

注冊監聽

NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];

    [defaultCenter selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

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

實作方法

- (void)keyboardWillShow:(NSNotification *)notification {

    NSDictionary *userInfo = [notification userInfo];

    NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];

    CGRect keyboardRect = [aValue CGRectValue];

    NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];

    NSTimeInterval animationDuration;

    [animationDurationValue getValue:&animationDuration];

    if(nil==self.myTextView) return;//    self.editTextView 為被鍵盤遮擋住的控件

    CGRect rect = self.myTextView.frame;

    float textY = rect.origin.y + rect.size.height; 

    float bottomY = SCREENHEIGHT - textY;//得到下邊框到底部的距離  SCREENHEIGHT 為目前裝置的高度

    if(bottomY >=keyboardRect.size.height ){//鍵盤預設高度,如果大于此高度,則直接傳回

        return;

    }

    float moveY = keyboardRect.size.height - bottomY;

    [self moveInputBarWithKeyboardHeight:moveY withDuration:animationDuration];

}



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

    NSDictionary* userInfo = [notification userInfo];

    NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];

    NSTimeInterval animationDuration;

    [animationDurationValue getValue:&animationDuration];

    [self moveInputBarWithKeyboardHeight: withDuration:animationDuration];

}

 //根據相差的高度進行輸入框的移動
-(void)moveInputBarWithKeyboardHeight:(float)_CGRectHeight withDuration:(NSTimeInterval)_NSTimeInterval{

  CGRect rect1 = self.view.frame;

    [UIView beginAnimations:nil context:NULL];

    [UIView setAnimationDuration:_NSTimeInterval];

    rect1.origin.y = -_CGRectHeight;//view往上移動

    self.view.frame = rect1;

    [UIView commitAnimations];

}
           

第二種情況,原理就是改變tableView的高度

_oY=_rightTableView.frame.size.height;//記錄初始化的時候tableView 的高度

//鍵盤出現的時候

- (void)keyboardWillShow:(NSNotification *)notification {

    CGRect initialFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];    

    CGRect convertedFrame = [self.view convertRect:initialFrame fromView:nil];

    CGRect tvFrame = _rightTableView.frame;

    tvFrame.size.height = convertedFrame.origin.y;

    _rightTableView.frame = tvFrame;

}

 //隐藏鍵盤

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

    CGRect tvFrame = _rightTableView.frame;

    tvFrame.size.height =_oY;    

    _rightTableView.frame = tvFrame;

}
           

第三種情況,點選UITextField的時候不需要彈出鍵盤,則隻要在uitextField的代理方法- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    //    如果需要彈出鍵盤的話,傳回yes,不需要的話傳回NO;
    if (textField == _confirmField) {
        HGAlertViewController * alertViewController = [HGAlertViewController alertControllerWithTitle:@"提示" message:@"點選彈出對話框" preferredStyle:(UIAlertControllerStyleAlert)];
        alertViewController.addAction(@"确定",^(UIAlertAction *action){
            NSLog(@"點選了确定按鈕");
        }).addAction(@"取消",^(UIAlertAction *action){
            NSLog(@"點選了取消按鈕");
        });
        return NO;
    }else{
        return YES;
    }
}
           

3、處理彈窗中uitableView的點選事件和背景tap手勢沖突

點選cell的時候,NSStringFromClass(touch.view)傳回的是UITableViewCellContentView

OC類方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
//    擷取點選視圖的類型
    NSString * touchClass = NSStringFromClass([touch.view class]);
//    判斷點選視圖的類型是不是UITableView的cell類型
    if ([touchClass isEqualToString:@"UITableViewCellContentView"]) {
//        如果是,傳回false
        return false;
    }else{
//        如果不是傳回true
        return true;
    }
}
           

swift類方法

//這是點選的代理協定,需要遵循UIGestureRecognizerDelegate,處理點選沖突問題
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    //擷取點選視圖類型的字元串
        let touchClass = NSStringFromClass((touch.view?.classForCoder)!)
        //判斷點選視圖是不是目前的彈框,如果不是,則表明點選的是背景隐藏彈框,如果是表明點選的UITableview的cell;
        //self.classForCoder傳回的是uiview,touchClass也是傳回uiview
        if touchClass != NSStringFromClass(self.classForCoder) {
            return false
        }
        return true
    }
           

說道這個問題,則引起另外一個問題:

ios 點選子視圖的時候會響應父視圖的點選事件

解決方法:

  • 讓你的類繼承 UIGestureRecognizerDelegate
  • tap.delegate = self;
  • 實作gestureRecognizer:shouldReceiveTouch:方法:

//Object-C:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isDescendantOfView:subView])  {
        return NO;
    }
    return YES;
} 
           

//Swift:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool  {
    if touch.view.isDescendantOfView(subView){
        return false
    }
    return true
}
           

4、Cell背景色覆寫按鈕的顔色

cell預設選中行的顔色是灰色的,如果cell上有按鈕等控件,會讓自身的顔色被灰色覆寫

解決方法: 在自定義的cell中實作如下兩個方法即可:

-(void)setSelected:(BOOL)selected animated:(BOOL)animated {
     [super setSelected:selected animated:animated];
     被覆寫的控件名.backgroundColor = UIColor.redColor;
  }

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
    [super setHighlighted:highlighted animated:animated];
     被覆寫的控件名.backgroundColor = UIColor.redColor;
 }