如何让UITextView默认显示滚动条
问题:当文字内容超过textview时,希望默认显示滚动条,UITextView继承自UIScrollView,滚动条自在滚动手势追踪的时候才会出现,怎样让滚动条一直显示呢?
通过UI堆栈可以看到,滚动视图是一个UIImageView,隐藏的时候alpha为0,所以可以通过category的方式重新实现UIImageView的setAlpha方法,当父视图为需要默认显示滚动条的视图时,始终设置图片的alpha为1
具体步骤:1、定义一个默认显示滚动条的子类MRATextView,继承自UITextView。tag赋特殊值、定义一个属性从外部接收滚动条的高度、重写flashScrollIndicators方法(可滚动时设置滚动视图alpha为1,并且调整frame)。
2、使用分类来重写UIImageView的setAlpha和setFrame方法,保证alpha不会被设置为0,frame正常可见。
具体代码:
1、MRATextView
// MRATextView.h
@interface MRATextView : UITextView @property(nonatomic) CGFloat verticalScrollBarH; @end
// MRATextView.m
#import "MRATextView.h" #import "FBKVOController.h" #import "UIImageView+MRAScrollView.h" @implementation MRATextView -(instancetype)init{ self = [super init]; if (self) { self.tag = 836913; } return self; } -(void)flashScrollIndicators{ [super flashScrollIndicators]; if (self.scrollEnabled) { [self showScrollBar]; } } -(void)showScrollBar{ for(UIView *img in [self subviews]){ if ([img isKindOfClass:[UIImageView class]] && img.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin){ UIImageView *scollBar = (UIImageView *)img; CGRect frame = scollBar.frame; frame.origin.y = 0; [scollBar setFrame:frame]; [scollBar setAlpha:1]; } } } @end
img.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin保证拿到的视图是竖直方向的滚动条。
2、UIImageView+MRAScrollView
// UIImageView+MRAScrollView.h
@interface UIImageView(MRAScrollView) @end
// UIImageView+MRAScrollView.m
#import "UIImageView+MRAScrollView.h" #import "MRATextView.h" @implementation UIImageView(MRAScrollView) - (void)setAlpha:(CGFloat)alpha { if (self.superview.tag == noDisableVerticalScrollTag) { if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) { if (self.frame.size.width < 10 && self.frame.size.height > self.frame.size.width) { UIScrollView *sc = (UIScrollView*)self.superview; if (sc.frame.size.height < sc.contentSize.height) { return; } } } } if (self.superview.tag == noDisableHorizontalScrollTag) { if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) { if (self.frame.size.height < 10 && self.frame.size.height < self.frame.size.width) { UIScrollView *sc = (UIScrollView*)self.superview; if (sc.frame.size.width < sc.contentSize.width) { return; } } } } [super setAlpha:alpha]; } -(void)setFrame:(CGRect)frame{ MRATextView *superView = (MRATextView *)self.superview; if (superView.tag == noDisableVerticalScrollTag && superView.scrollEnabled) { if (self.frame.origin.y < 0) { frame.origin.y = 0; } frame.size.height = superView.verticalScrollBarH; } [super setFrame: frame]; } @end
使用时直接
_textView = [[MRATextView alloc]init]; 即可。
低版本系统兼容问题:1、iOS8号不可滑动,且默认展示滚动条。
原因:1、iOS8中需要手动设置contentsize,否则contentSize为(0,0)。
2、iOS中UIScrollView的某些特性,会掠过setAlpha方法,直接设置_alpha为0,所以重写UIImageview的setAlpha不能起到拦截作用。
解决办法:1、设置textView内容时,手动设置一下contentSize。
2、在didMoveToWindow方法中重新设置一下滚动条的alpha和frame,使之可见,代码可以加在didMoveToWindow方法中。
-(void)didMoveToWindow{ [super didMoveToWindow]; [_textView flashScrollIndicators]; }