也许是一个简单的问题!
有人知道如何使UIScrollView的滚动条始终显示吗?
当用户滚动时,它会显示出来,这样他们可以看到滚动视图中的位置。
但是我想让它始终显示,因为对于用户来说并不立即明显他们可以滚动。
任何建议将不胜感激。
也许是一个简单的问题!
有人知道如何使UIScrollView的滚动条始终显示吗?
当用户滚动时,它会显示出来,这样他们可以看到滚动视图中的位置。
但是我想让它始终显示,因为对于用户来说并不立即明显他们可以滚动。
任何建议将不胜感激。
不,你不能让它们总是显示,但你可以让它们暂时闪烁。
[myScrollView flashScrollIndicators];
它们是滚动指示器,而不是滚动条。您无法使用它们进行滚动。
我的解决方案:始终显示滚动指示器的滚动视图。
#define noDisableVerticalScrollTag 836913
#define noDisableHorizontalScrollTag 836914
@implementation UIImageView (ForScrollView)
- (void) setAlpha:(float)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];
}
@end
更新: 这种解决方案在64位系统上可能会出现一些问题。详细信息请参考此处
UIImageView
setAlpha
方法的类别。它依赖于滚动视图指示器具有特定的标记号码,这是一个私有实现细节,可能会发生变化。 - lxtshowsVerticalScrollIndicator
,但它只能禁用整个指示器的显示。flashScrollIndicators
,以便用户知道他们在滚动视图中的位置。这个方法对我有效:
#define noDisableVerticalScrollTag 836913
#define noDisableHorizontalScrollTag 836914
@implementation UIImageView (ForScrollView)
- (void) setAlpha:(float)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];
}
@end
Swift 3+
1) 定时器
var timerForShowScrollIndicator: Timer?
2) 方法
/// Show always scroll indicator in table view
func showScrollIndicatorsInContacts() {
UIView.animate(withDuration: 0.001) {
self.tableView.flashScrollIndicators()
}
}
/// Start timer for always show scroll indicator in table view
func startTimerForShowScrollIndicator() {
self.timerForShowScrollIndicator = Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(self.showScrollIndicatorsInContacts), userInfo: nil, repeats: true)
}
/// Stop timer for always show scroll indicator in table view
func stopTimerForShowScrollIndicator() {
self.timerForShowScrollIndicator?.invalidate()
self.timerForShowScrollIndicator = nil
}
3) 使用
在 viewDidAppear 中使用 startTimerForShowScrollIndicator
在 viewDidDisappear 中使用 stopTimerForShowScrollIndicator
self.categoriesTableView
属性是一个表视图,在其中我想显示滚动条)。- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Do swizzling to turn scroll indicator always on
// Search correct subview with vertical scroll indicator image across tableView subviews
for (UIView * view in self.categoriesTableView.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
if (view.alpha == 0 && view.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
if (view.frame.size.width < 10 && view.frame.size.height > view.frame.size.width) {
if (self.categoriesTableView.frame.size.height < self.categoriesTableView.contentSize.height) {
// Swizzle class for found imageView, that should be scroll indicator
object_setClass(view, [AlwaysOpaqueImageView class]);
break;
}
}
}
}
}
// Search correct subview with horizontal scroll indicator image across tableView subviews
for (UIView * view in self.categoriesTableView.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
if (view.alpha == 0 && view.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
if (view.frame.size.height < 10 && view.frame.size.height < view.frame.size.width) {
if (self.categoriesTableView.frame.size.width < self.categoriesTableView.contentSize.width) {
// Swizzle class for found imageView, that should be scroll indicator
object_setClass(view, [AlwaysOpaqueImageView class]);
break;
}
}
}
}
}
// Ask to flash indicator to turn it on
[self.categoriesTableView flashScrollIndicators];
}
@interface AlwaysOpaqueImageView : UIImageView
@end
@implementation AlwaysOpaqueImageView
- (void)setAlpha:(CGFloat)alpha {
[super setAlpha:1.0];
}
@end
- (void)webViewDidFinishLoad:(UIWebView *)webView;
提示用户有更多的内容“超出了框架”的方法。
NSArray *subViews = [[NSArray alloc] initWithArray:[webView subviews]] ;
UIScrollView *webScroller = (UIScrollView *)[subViews objectAtIndex:0] ;
if (webScroller.contentSize.height > webView.frame.size.height) {
[webScroller flashScrollIndicators];
}
闪光灯非常短暂,而且发生在视图加载时,很容易被忽略。为了解决这个问题,您还可以通过通用的UIView commitAnimations来微调、弹跳、滚动或缩放内容。
这是一个类似于iOS内置ScrollBar的控件,但你可以自定义颜色和宽度。
-(void)persistantScrollBar
{
[persistantScrollBar removeFromSuperview];
[self.collectionView setNeedsLayout];
[self.collectionView layoutIfNeeded];
if (self.collectionView.contentSize.height > self.collectionView.frame.size.height + 10)
{
persistantScrollBar = [[UIView alloc] initWithFrame:(CGRectMake(self.view.frame.size.width - 10, self.collectionView.frame.origin.y, 5, (self.collectionView.frame.size.height /self.collectionView.contentSize.height) * self.collectionView.frame.size.height))];
persistantScrollBar.backgroundColor = [UIColor colorWithRed:207/255.f green:207/255.f blue:207/255.f alpha:0.5f];
persistantScrollBar.layer.cornerRadius = persistantScrollBar.frame.size.width/2;
persistantScrollBar.layer.zPosition = 0;
[self.view addSubview:persistantScrollBar];
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect rect = persistantScrollBar.frame;
rect.origin.y = scrollView.frame.origin.y + (scrollView.contentOffset.y *(self.collectionView.frame.size.height/self.collectionView.contentSize.height));
rect.size.height = (self.collectionView.frame.size.height /self.collectionView.contentSize.height) * self.collectionView.frame.size.height;
if ( scrollView.contentOffset.y <= 0 )
{
rect.origin.y = scrollView.frame.origin.y;
rect.size.height = rect.size.height + (scrollView.contentOffset.y);
}
else if (scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height)
{
rect.size.height = rect.size.height - ((scrollView.contentOffset.y + scrollView.frame.size.height) - scrollView.contentSize.height);
rect.origin.y = (self.collectionView.frame.origin.y + self.collectionView.frame.size.height - 5) - rect.size.height;
}
persistantScrollBar.frame = rect;
}
浏览了这些答案,它们大部分都很可怕。使用以下代码可以在Swift 5中实现该功能。仍然依赖于滚动视图使用具有类"_UIScrollViewScrollIndicator"的子视图-但至少没有交换或应用程序范围的类别。
class IndicatorScrollView: UIScrollView {
weak var indicatorTimer: Timer?
override func didMoveToSuperview() {
super.didMoveToSuperview()
setupIndicatorTimer()
}
override func removeFromSuperview() {
super.removeFromSuperview()
indicatorTimer?.invalidate()
}
deinit {
indicatorTimer?.invalidate()
}
func setupIndicatorTimer() {
indicatorTimer?.invalidate()
indicatorTimer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(showIndicators), userInfo: nil, repeats: true)
}
@objc func showIndicators() {
subviews.forEach {
if String(describing: type(of: $0)).contains("ScrollIndicator") {
$0.alpha = 1
}
}
}
}
iOS没有提供API。但是如果您真的想要这个功能,您可以将自定义指示器添加到滚动视图并自行布局,就像演示中所做的那样:
- (void)layoutSubviews { [super layoutSubviews];
if (self.showsVerticalScrollIndicatorAlways) { scroll_indicator_position(self, k_scroll_indicator_vertical); }
if (self.showsHorizontalScrollIndicatorAlways) { scroll_indicator_position(self, k_scroll_indicator_horizontal); } }