IT Share you

UIScrollView-스크롤 막대 표시

shareyou 2021. 1. 7. 19:55
반응형

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 비트에서 일부 문제를 일으 킵니다. 자세한 내용은 여기 를 참조 하십시오.


내가 아는 한 이것은 불가능합니다. 스크롤 표시기 표시를 제어하는 ​​유일한 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

나는 여기 에서이 스 니펫을 얻었습니다 : http://www.developers-life.com/scrollview-with-scrolls-indicators-which-are-shown-all-the-time.html


내 솔루션을 제공하고 싶습니다. 카테고리에서 가장 인기있는 변형이 마음에 들지 않습니다 (카테고리의 메서드를 재정의하는 것은 동일한 선택기를 가진 두 개의 메서드가 있기 때문에 런타임에서 어떤 메서드를 호출해야하는지 결정하지 못하는 이유 일 수 있습니다). 나는 대신 swizzling을 사용합니다. 또한 태그를 사용할 필요가 없습니다.

스크롤 뷰가있는 뷰 컨트롤러에이 메서드를 추가합니다 ( 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사이클 코드에 남겨두고 다른 지표를 제거하십시오.


첫 번째 하위보기가 스크롤보기 인 웹보기의 경우, 최신 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];
        }

플래시는 너무 짧고 오버뷰가로드되는 동안 발생하므로 간과 할 수 있습니다. 이 문제를 해결하려면 일반 UIView commitAnimations를 통해 콘텐츠를 조금 흔들거나 바운스하거나 스크롤하거나 크기를 조정할 수도 있습니다.


iOS는 API를 제공하지 않습니다. 하지만 정말로 이것을 원한다면, 데모처럼 스크롤 뷰와 레이아웃을 위해 커스텀 인디케이터를 추가 할 수 있습니다 :

-(무효) layoutSubviews
{
    [슈퍼 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


ScrollBar that functions just like the iOS built in one, but you can mess with the color and width.

-(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 3

You can access the scrollbar using scrollView.subviews and modify the alpha as shown here. It works for me.

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
        }
    }
}

Swift 3+

1) Timer

var timerForShowScrollIndicator: Timer?

2) Methods

/// 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

startTimerForShowScrollIndicator in viewDidAppear

stopTimerForShowScrollIndicator in viewDidDisappear

ReferenceURL : https://stackoverflow.com/questions/1888647/uiscrollview-showing-the-scroll-bar

반응형