問題:
今天想做UITextView的自適應高度,寫了個小demo,發現內容偏移了
可以看到上方有64的偏移,光標是無法到達的。
textView的實現代碼:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.textView];
[self makeContraints];
}
- (UITextView *)textView
{
if (!_textView) {
_textView = [[UITextView alloc] init];
_textView.backgroundColor = [UIColor grayColor];
_textView.scrollEnabled = NO;
_textView.font = [UIFont systemFontOfSize:20];
}
return _textView;
}
- (void)makeContraints
{
__weak typeof(self) weakSelf = self;
[self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(weakSelf.view);
make.top.mas_equalTo(100);
make.height.greaterThanOrEqualTo(@100);
}];
}
原因:
翻了好久的資料找到了問題。
下面說的UIScrollView包含其子類,UITableView,UICollectionView等
主要是demo中用的導航是透明的,起始座標是(0, 0),系統會自動偏移UIScrollView讓其初始狀態從(0,64)顯示,但是又能夠滑到導航來顯示蒙層效果效果如圖
- 初始狀態因爲被偏移了(0,64)所以能夠貼導航顯示
- 導航透明,UIScrollView的起始點在(0,0),所以可以滑動到導航欄顯示蒙層效果(
應該是iOS7時蘋果覺得這樣好看,所以至今默認效果還是這樣的
)
UITextView中的內容就是在一個UIScrollView上,所以系統對最底層對UIScrollView做了偏移。
爲什麼說是最底層的UIScrollView呢,因爲如果在一個UIScrollView中嵌套其他UIScrollView,被嵌套的UIScrollView是不再偏移的,只會偏移最底層那個UIScrollView。
解決方案:
1. 設置ScrollView不自動偏移
[self setAutomaticallyAdjustsScrollViewInsets:NO]
//self.automaticallyAdjustsScrollViewInsets = NO;//同上
iOS11:
在iOS11中UIViewController的automaticallyAdjustsScrollViewInsets
屬性被廢棄,不再起作用,
取而代之的是UIScrollView中新增的屬性contentInsetAdjustmentBehavior
//UITextView繼承自UIScrollView,所以也是設置contentInsetAdjustmentBehavior
//效果同iOS11前的self.automaticallyAdjustsScrollViewInsets = NO;
scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
2. 設置導航不透明
self.navigationController.navigationBar.translucent = NO;
3. 邊界延伸設置爲None
self.edgesForExtendedLayout = UIRectEdgeNone; //默認爲UIRectEdgeAll,會向上下左右偏移,偏移到(0,0)
//setf.extendedLayoutIncludesOpaqueBars = NO;//這裏系統默認就是NO,如果單設EdgesForExtendedLayout無效可以試試加上這句
4. 手動更改偏移
不建議使用,先不說代碼多,由系統設置引起的問題還是由更改設置來解決比較好。這樣解決就好像一個人引起的問題,讓另一個去解決,不符合代碼規範。而且當需要手動設置UIScrollView的contentOffset的時候也會產生衝突。
//循環出UIScrollView手動設置偏移的y爲0
for (UIScrollView *view in self.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
CGPoint offset = view.contentOffset;
if (offset.y != 0) {
offset.y = 0;
view.contentOffset = offset;
}
break;
}
}
瞎扯
- 這個問題不是太常見,因爲我們現在的導航基本都是不透明的,或者我們的UITextView都在其他UIScrollView上(
需要UITextView的一般都是比較長的視圖,比如意見反饋什麼的
),所以不會被偏移(前面提到了,只會偏移最底層的UIScrollView
) - 得找到問題的本質。這裏就是因爲iOS7引入的導航透明,計算座標爲(0,0)引起的系統自動偏移UIScrollView
- 問題解決了當然得寫篇博客,給別人參考了。減少別人再次翻找的麻煩,編程需要的就是共享精神,我們在編程時遇到問題還不是大部分靠前人的經驗處理嗎!!!所以希望大家能貢獻自己的力量。予人方便就是予己方便,因爲我們也需要從共享中獲益。