【发布时间】:2010-12-25 17:01:48
【问题描述】:
可能很简单!
有谁知道如何让 UIScrollView 的滚动条不断显示?
它在用户滚动时显示,因此他们可以看到他们所在的滚动视图的位置。
但我希望它不断显示,因为用户无法立即看到滚动可用
任何建议将不胜感激。
【问题讨论】:
标签: iphone objective-c uiscrollview scrollbar
可能很简单!
有谁知道如何让 UIScrollView 的滚动条不断显示?
它在用户滚动时显示,因此他们可以看到他们所在的滚动视图的位置。
但我希望它不断显示,因为用户无法立即看到滚动可用
任何建议将不胜感激。
【问题讨论】:
标签: iphone objective-c uiscrollview scrollbar
不,你不能让它们一直显示,但你可以让它们暂时闪烁。
[myScrollView flashScrollIndicators];
它们是滚动指示器,而不是滚动条。你不能用它们来滚动。
【讨论】:
my solution 一直显示滚动指示器
#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 位上会导致一些问题。更多详情请看here
【讨论】:
UIImageView setAlpha 方法的类别。它依赖于具有特定标签号的滚动视图指示器,这是一个私有的实现细节,可能会发生变化。
据我所知,这是不可能的。控制滚动指示器显示的唯一 API 调用是 showsVerticalScrollIndicator,它只能完全禁用显示指示器。
您可以在视图出现时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
我从这里得到了这个 sn-p:http://www.developers-life.com/scrollview-with-scrolls-indicators-which-are-shown-all-the-time.html
【讨论】:
斯威夫特 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
滚动指示器(第一个 for 循环中的垂直滚动指示器和第二个 for 循环中的水平滚动指示器)将始终在屏幕上。如果您只需要一个指标,请在代码中只留下这个 for 循环并删除另一个。
【讨论】:
对于第一个子视图是滚动视图的 webview,在最新的 SDK 中,如果 HTML 页面比框架长,则不会显示滚动条,并且如果 html 内容恰好与框架对齐,或者您在框架的底部有一个空格,它“看起来”就像不需要滚动,并且在该行下方没有任何内容。在这种情况下,我认为您绝对应该在代表的
中闪烁滚动条- (void)webViewDidFinishLoad:(UIWebView *)webView;
提醒用户“盒子外”还有更多东西的方法。
NSArray *subViews = [[NSArray alloc] initWithArray:[webView subviews]] ;
UIScrollView *webScroller = (UIScrollView *)[subViews objectAtIndex:0] ;
使用 HTML 时,水平内容会自动换行,因此请检查网页滚动条的高度。
if (webScroller.contentSize.height > webView.frame.size.height) {
[webScroller flashScrollIndicators];
}
flash 很短,并且在加载视图时发生,因此可以忽略。要解决这个问题,您还可以通过通用 UIView commitAnimations 稍微抖动或弹跳或滚动或缩放内容
【讨论】:
iOS 不提供 API。但是如果你真的想要这个,你可以添加你的自定义指示器来滚动视图并自己布局它,就像演示一样:
- (void)layoutSubviews { [超级布局子视图]; 如果(self.showsVerticalScrollIndicatorAlways){ scroll_indicator_position(self, k_scroll_indicator_vertical); } 如果(self.showsHorizontalScrollIndicatorAlways){ scroll_indicator_position(自我,k_scroll_indicator_horizontal); } }【讨论】:
ScrollBar 的功能就像 iOS 内置的一样,但你可以弄乱颜色和宽度。
-(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;
}
【讨论】:
斯威夫特 3
您可以使用 scrollView.subviews 访问滚动条并修改 alpha,如下所示。它对我有用。
extension UIScrollView {
override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for x in self.subviews {
x.alpha = 1.0
}
}
}
extension MyScrollViewDelegate : UIScrollViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
for x in scrollView.subviews {
x.alpha = 1.0
}
}
}
【讨论】: