おそらくシンプルなものです!
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
[〜#〜] update [〜#〜]:このソリューションは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
ソリューションを提供したい。私はカテゴリで最も人気のあるバリアントが好きではありません(カテゴリ内のメソッドをオーバーライドすると、同じセレクタを持つ2つのメソッドがあるため、実行時にどのメソッドを呼び出すべきかが不確定になる場合があります)。代わりにスウィズリングを使用します。また、タグを使用する必要もありません。
このメソッドをビュービューコントローラーに追加します。スクロールビュー(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
サイクルの垂直スクロールインジケーターと2番目のfor
サイクルの水平スクロールインジケーター)は常に画面に表示されます。インジケーターが1つだけ必要な場合は、このfor
サイクルのみをコードに残し、別のインジケーターを削除します。
組み込みの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;
}
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); } }
リンクは---(https://github.com/flexih/MazeScrollView です
Swift
ScrollView.subviewsを使用してスクロールバーにアクセスし、ここに示すようにアルファを変更できます。わたしにはできる。
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)タイマー
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
最新のSDKの最初のサブビューがスクロールビューであるWebビューの場合、HTMLページがフレームより長い場合、スクロールバーは表示されず、HTMLコンテンツがフレームと並んでいる場合、または空白がある場合フレームの下部では、スクロールは不要で、行の下には何もないように見えます。この場合、デリゲートのスクロールバーを確実にフラッシュする必要があると思います
- (void)webViewDidFinishLoad:(UIWebView *)webView;
より多くのものが「箱の外」にあることをユーザーに警告する方法。
NSArray *subViews = [[NSArray alloc] initWithArray:[webView subviews]] ;
UIScrollView *webScroller = (UIScrollView *)[subViews objectAtIndex:0] ;
HTMLでは、水平コンテンツが自動的にラップされるため、webscrollerの高さを確認してください。
if (webScroller.contentSize.height > webView.frame.size.height) {
[webScroller flashScrollIndicators];
}
フラッシュは非常に短く、オーバービューの読み込み中に発生するため、見逃す可能性があります。これを回避するには、汎用のUIView commitAnimationsを使用してコンテンツを少し揺らしたり、バウンスしたり、スクロールしたり、スケールしたりすることもできます。