objective-c UIScrollView - 显示滚动条
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1888647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIScrollView - showing the scroll bar
提问by Tom G
Possibly a simple one!
可能是一个简单的!
Does anyone know how to get the scroll bar of a UIScrollView to constantly show?
有谁知道如何让 UIScrollView 的滚动条不断显示?
It displays when the user is scrolling, so they can see what position of the scroll view they are in.
它在用户滚动时显示,因此他们可以看到他们在滚动视图的哪个位置。
BUT I would like it to constantly show because it is not immediately obvious to the user that scrolling is available
但我希望它不断显示,因为滚动可用对用户来说并不是很明显
Any advice would be highly appreciated.
任何建议将不胜感激。
回答by Mongus Pong
No, you can't make them always show, but you can make them temporarily flash.
不,你不能让它们一直显示,但你可以让它们暂时闪烁。
[myScrollView flashScrollIndicators];
They are scroll indicators, not scroll bars. You can't use them to scroll.
它们是滚动指示器,而不是滚动条。你不能用它们来滚动。
回答by SAKrisT
my solutionfor show scroll indicators all the time
#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
UPDATE: This solution cause some issues on 64-bit. For more detail look here
更新:此解决方案在 64 位上引起了一些问题。欲了解更多详情,请看这里
回答by Ben S
As far as I know, this isn't possible. The only API call which controls displaying the scroll indicator is showsVerticalScrollIndicatorand that can only disable displaying the indicator altogether.
据我所知,这是不可能的。控制显示滚动指示器的唯一 API 调用是showsVerticalScrollIndicator并且只能完全禁用显示指示器。
You could flashScrollIndicatorswhen the view appears so that the user knows where in the scroll view they are.
您可以flashScrollIndicators在视图出现时让用户知道他们在滚动视图中的位置。
回答by sciasxp
This one worked for me:
这个对我有用:
#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
I got this snippet from here: http://www.developers-life.com/scrollview-with-scrolls-indicators-which-are-shown-all-the-time.html
我从这里得到了这个片段:http: //www.developers-life.com/scrollview-with-scrolls-indicators-which-are-shown-all-the-time.html
回答by Accid Bright
I want to offer my solution. I don't like the most popular variant with category (overriding methods in category can be the reason of some indetermination what method should be called in runtime, since there is two methods with the same selector). I use swizzling instead. And also I don't need to use tags.
我想提供我的解决方案。我不喜欢最流行的带有类别的变体(覆盖类别中的方法可能是不确定在运行时应该调用什么方法的原因,因为有两个方法具有相同的选择器)。我用 swizzling 代替。而且我不需要使用标签。
Add this method to your view controller, where you have scroll view (self.categoriesTableViewproperty is a table view where I want to show scroll bars)
将此方法添加到您有滚动视图的视图控制器中(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];
}
Add new class
添加新班级
@interface AlwaysOpaqueImageView : UIImageView
@end
@implementation AlwaysOpaqueImageView
- (void)setAlpha:(CGFloat)alpha {
[super setAlpha:1.0];
}
@end
The scroll indicator (vertical scroll indicator in first forcycle and horizontal in second forcycle) will be always at the screen. If you need only one indicator, left only this forcycle in code and remove another one.
滚动指示器(第一个for循环中的垂直滚动指示器和第二个for循环中的水平滚动指示器)将始终显示在屏幕上。如果您只需要一个指标,for在代码中只留下这个循环并删除另一个。
回答by Alfred
Swift 3
斯威夫特 3
You can access the scrollbar using scrollView.subviews and modify the alpha as shown here. It works for me.
您可以使用 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
}
}
}
回答by AbhinayMe
Swift 3+
斯威夫特 3+
1) Timer
1) 定时器
var timerForShowScrollIndicator: Timer?
2) Methods
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) Use
3) 使用
startTimerForShowScrollIndicator in viewDidAppear
viewDidAppear 中的 startTimerForShowScrollIndicator
stopTimerForShowScrollIndicator in viewDidDisappear
viewDidDisappear 中的 stopTimerForShowScrollIndicator
回答by PapaSmurf
For webviews, where the first subview is a scrollview, in the latest SDK, if an HTML page is longer than the frame, no scroll bar is shown, and if the html content happens to line up with the frame, or you have a whitespace at the bottom of the frame, it 'looks' like there is no scroll needed and nothing below the line. In this case, I think you should definately flash the scroll bars in the delegate's
对于webview,第一个subview是scrollview,在最新的SDK中,如果HTML页面比frame长,则不显示滚动条,如果html内容恰好与frame对齐,或者你有空格在框架的底部,它“看起来”不需要滚动,线下也没有任何东西。在这种情况下,我认为您肯定应该在代表的滚动条中闪烁
- (void)webViewDidFinishLoad:(UIWebView *)webView;
method to alert the user that there is more stuff 'outside the box'.
提醒用户“盒子外”还有更多东西的方法。
NSArray *subViews = [[NSArray alloc] initWithArray:[webView subviews]] ;
UIScrollView *webScroller = (UIScrollView *)[subViews objectAtIndex:0] ;
With HTML, the horizontal content is wrapped automatically, so check the webscroller height.
使用 HTML,水平内容会自动换行,因此请检查 webscroller 高度。
if (webScroller.contentSize.height > webView.frame.size.height) {
[webScroller flashScrollIndicators];
}
The flash is so short, and happens while over views are loading, that it can be overlooked. To work around that, you could also jiggle or bounce or scroll or scale the content a little via the generic UIView commitAnimations
Flash 很短,并且在加载过视图时发生,因此可以忽略。要解决这个问题,您还可以通过通用 UIView commitAnimations 稍微摇晃或弹跳或滚动或缩放内容
回答by flexih
iOS does not offer the API. But if you really want this, you can add your custom indicator to scroll view and layout it yourself, just as the demo does:
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);
}
}
The link is https://github.com/flexih/MazeScrollView
回答by HannahCarney
ScrollBar that functions just like the iOS built in one, but you can mess with the color and width.
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;
}

