Iphone 是否使滚动条在UIScrollView上始终可见?
我需要使一个滚动条在viewDidLoad上始终可见,以便用户能够理解有要滚动的内容。我做了以下工作:Iphone 是否使滚动条在UIScrollView上始终可见?,iphone,ios,cocoa-touch,uiscrollview,uikit,Iphone,Ios,Cocoa Touch,Uiscrollview,Uikit,我需要使一个滚动条在viewDidLoad上始终可见,以便用户能够理解有要滚动的内容。我做了以下工作: [myscrollView flashScrollIndicators]; 但是,滚动条只在viewDidLoad之后出现一段时间,然后再次消失,直到用户触摸屏幕时才重新出现 我需要使滚动条始终可见。我该怎么做呢?我不知道这是否行得通。但给你一个提示 Scrollview中的滚动条是一个Imageview。哪个是UIScrollview的子视图 因此,获取UIscrollview的滚动条Im
[myscrollView flashScrollIndicators];
但是,滚动条只在viewDidLoad之后出现一段时间,然后再次消失,直到用户触摸屏幕时才重新出现
我需要使滚动条始终可见。我该怎么做呢?我不知道这是否行得通。但给你一个提示 Scrollview中的滚动条是一个Imageview。哪个是UIScrollview的子视图 因此,获取UIscrollview的滚动条Imageview。然后尝试将“图像隐藏”属性设置为“否”或更改Alpha值
static const int UIScrollViewHorizontalBarIndexOffset = 0;
static const int UIScrollViewVerticalBarIndexOffset = 1;
-(UIImageView *)scrollbarImageViewWithIndex:(int)indexOffset
{
int viewsCount = [[yourScrollview subviews] count];
UIImageView *scrollBar = [[yourScrollview subviews] objectAtIndex:viewsCount - indexOffset - 1];
return scrollBar;
}
-(void) viewDidLoad
{
//Some Code
//Get Scrollbar
UIImageView *scrollBar = [self scrollbarImageViewWithIndex: UIScrollViewVerticalBarIndexOffset];
//The try setting hidden property/ alpha value
scrollBar.hidden=NO;
}
从苹果公司得到的参考间接地阻止了在他们的屏幕上不断显示滚动指示器,但这些指南只是出于一个原因的指南,它们并不能解释所有场景,有时你可能需要礼貌地忽略它们 任何内容视图的滚动指示器都是这些内容视图的子视图。这意味着您可以访问
UIScrollView
的滚动指示器,就像访问其任何其他子视图(即myScrollView.subview
)一样,并修改滚动指示器,就像访问任何UIImageView
(例如scrollIndicatorImageView.backgroundColor=[UIColor redColor];
)
最流行的解决方案似乎是以下代码:
#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
其他SO参考资料:
- 我想提供我的解决方案。我不喜欢使用category的最流行的变体(在category中重写方法可能是不确定在运行时应该调用什么方法的原因,因为有两个方法具有相同的选择器)。
我用swizzling代替。而且我不需要使用标签
将此方法添加到您的视图控制器中,您可以在其中使用滚动视图(
self.categoriesTableView
)
滚动指示器(本例中为垂直滚动指示器)将始终位于屏幕上
更新日期:2019年11月
从iOS 13开始,更改子类。现在滚动指示器继承自UIView
,并有自己的私有类,名为\u UIScrollViewScrollIndicator
。这意味着,它们现在不是UIImageView
的子类,所以旧方法不再有效
此外,我们无法实现\u UIScrollViewScrollIndicator
的子类,因为它是私有类,我们无权访问它。因此,唯一的解决方案是使用运行时。现在要支持iOS 13及更早版本,请执行以下步骤:
self.categoriesTableView
)UIScrollView
子类)AlwaysPaquesScrollIndicator
的\uUIScrollViewScrollIndicator
的子类,并将setAlpha:
方法实现切换到AlwaysPaques\u setAlpha:
别忘了加上
#导入
添加到已插入此代码的文件。感谢@Smartcat提醒您注意这一点这是@Accid Bright的Swift版本:
class AlwaysPaqueImageView:UIImageView{
覆盖变量alpha:CGFloat{
迪塞特{
α=1
}
}
静态函数setScrollbarToAlwaysVisible(来自scrollView:UIScrollView){
//旋转滚动指示灯是否始终打开
//使用滚动指示器图像在tableView子视图中搜索正确的子视图
用于scrollView.subview中的视图{
如果view.isKind(of:UIImageView.self),
view.alpha==0&&view.autoresizingMask==UIView.autoresizingMask.flexibleLeftMargin,
view.frame.size.width<10&&view.frame.size.height>view.frame.size.width,
scrollView.frame.size.height
一个区别是设置滚动条是作为静态方法提取出来的。Cudnt understand u,触摸屏上是否显示滚动视图??滚动条是如何消失的?是的,当我使用[myscrollView flashScrollIndicators]时,滚动视图显示在触摸屏上;它们出现在viewLoad上,几秒钟后就消失了。我想让它们始终可见。不,我不会来回走动。检查这个,这样你就不想让它们消失了吗?实际上,在你给出的示例中,我已经检查过了。这是关于更改滚动条的颜色。但我需要它们不断显示(始终可见)在视图上我知道..jst获取该视图的提示。既然你得到了scrolbar对象..只需通过调整隐藏属性或alpha值对其进行操作..这样它就会一直显示。我尝试了隐藏属性。但那不起作用..你能告诉我如何使用alpha值吗?仅供参考。这可以为你尝试。既然你获取scrollbar对象。尝试修改它。但是,当scrollbar中发生操作时,所有属性都将被修改。因此,请在操作结束时对scrollbar进行修改。我要警告的是,它依赖于私有实现细节(指示器是
UIImageView
对象)这可能并不总是正确的。事实上,这是sod定律,当你最不经意的时候,它总是会被打破,诺玛
- (void)viewDidAppear:(BOOL)animate
{
[super viewDidAppear:animate];
[self.scrollView flashScrollIndicators];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Do swizzling to turn scroll indicator always on
// Search correct subview with 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;
}
}
}
}
}
// 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)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Do swizzling to turn scroll indicator always on
// Search correct subview with 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;
}
}
}
} else if ([NSStringFromClass(view.class) isEqualToString:@"_UIScrollViewScrollIndicator"]) {
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 scroll indicator, (be sure to create AlwaysOpaqueScrollIndicator in runtime earlier!)
// Current implementation is in AlwaysOpaqueScrollTableView class
object_setClass(view, NSClassFromString(@"AlwaysOpaqueScrollIndicator"));
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)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Create child class from _UIScrollViewScrollIndicator since it is private
Class alwaysOpaqueScrollIndicatorClass = objc_allocateClassPair(NSClassFromString(@"_UIScrollViewScrollIndicator"), "AlwaysOpaqueScrollIndicator", 0);
objc_registerClassPair(alwaysOpaqueScrollIndicatorClass);
// Swizzle setAlpha: method of this class to custom
Class replacementMethodClass = [self class];
SEL originalSelector = @selector(setAlpha:);
SEL swizzledSelector = @selector(alwaysOpaque_setAlpha:);
Method originalMethod = class_getInstanceMethod(alwaysOpaqueScrollIndicatorClass, originalSelector);
Method swizzledMethod = class_getInstanceMethod(replacementMethodClass, swizzledSelector);
BOOL didAddMethod =
class_addMethod(alwaysOpaqueScrollIndicatorClass,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(alwaysOpaqueScrollIndicatorClass,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
- (void)alwaysOpaque_setAlpha:(CGFloat)alpha {
[self alwaysOpaque_setAlpha:1.0];
}
class AlwaysOpaqueImageView: UIImageView {
override var alpha: CGFloat {
didSet {
alpha = 1
}
}
static func setScrollbarToAlwaysVisible(from scrollView: UIScrollView) {
// Do swizzling to turn scroll indicator always on
// Search correct subview with scroll indicator image across tableView subviews
for view in scrollView.subviews {
if view.isKind(of: UIImageView.self),
view.alpha == 0 && view.autoresizingMask == UIView.AutoresizingMask.flexibleLeftMargin,
view.frame.size.width < 10 && view.frame.size.height > view.frame.size.width,
scrollView.frame.size.height < scrollView.contentSize.height {
// Swizzle class for found imageView, that should be scroll indicator
object_setClass(view, AlwaysOpaqueImageView.self)
break
}
}
// Ask to flash indicator to turn it on
scrollView.flashScrollIndicators()
}
}