web-dev-qa-db-ja.com

複数のデータソースとテーブルビューを共有するために、プログラムでUIScrollViewにスクロールを停止させます

ユーザーがセグメント化されたコントロールにタッチすると、データソースとデリゲートがいくつかのカスタムデータソースオブジェクト間で切り替えられるUITableViewがあります(アプリストアアプリの「トップペイド」と「トップフリー」を考えてください)。

各データソースオブジェクトは、最後のスクロールコンテンツオフセットを保存し、次の手順を実行して、テーブルビューのアクティブなデータソースになったときに復元します。

tableView.contentOffset = CGPointMake(0, savedScrollPosition);

これは、テーブルが静止しているときにユーザーがデータソースを切り替えるときにうまく機能しますが、テーブルがまだ移動している(つまり減速している)ときにユーザーがセグメント化されたコントロールを押すと、テーブルビューは古いオフセットから減速し続け、効果的に私のcontentOffsetの割り当て。

ContentOffsetを設定したときにテーブルビューのスクロール/減速を強制的に停止する方法、またはこのタイプの切り替え可能なデータソーステーブルビューを機能させる別の方法はありますか?

25
Daniel Dickison

これらの2つの方法を試しましたか?

それらは実際には、コンテンツのオフセットだけでなく、「スクロール」にも適用されます。

[self.tableView  scrollToRowAtIndexPath:savedIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];

または:

[self.tableView  scrollRectToVisible:savedFrame animated:NO];

それらは実際には、画面に表示されているものだけでなく、スクロール、ひいてはテーブルの加速に影響を与えるはずです。

19
Corey Floyd

[view setContentOffset: offset animated: YES]を使ってみましたか?

13
Ben Gottlieb

これは私にとってうまく機能しました:

if (self.tableView.isDecelerating) {
        NSArray *paths = [self.tableView indexPathsForVisibleRows];
        [self.tableView scrollToRowAtIndexPath:[paths objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

    }
5
timelapse

UIScrollViewを停止する方法を探しているのを見つけました-いくつかのサブビューを移動する必要がありましたが、ユーザーが画面をフリックしてまだ減速している場合、この傷は正しく見えません。

とにかく-scrollRectToVisibleは私には機能しませんでした(おそらく私はテーブルビューを使用していないためですか??)が、これは完全に機能しました:

[mainScrollView setContentOffset:CGPointMake(mainScrollView.contentOffset.x, mainScrollView.contentOffset.y) animated:NO];

そうすれば、心配することなくサブビューを実行できます。

4
Ben Robinson

Coreyのアプローチを使用しました。辞書表現を使用して四角形を保存および復元します。また、明らかではないかもしれませんが、保存および復元するためのrectは、UITableViewのboundsです。

// Save the current tableview bounds
CGRect contentRect = self.listTableView.bounds;
if (!!oldScope) [_contentRects setObject:(NSObject *)CGRectCreateDictionaryRepresentation(contentRect) forKey:oldScope];

// Restore if possible
CFDictionaryRef restoredFrameDict = (CFDictionaryRef)[_contentRects objectForKey:newScope];
if (!restoredFrameDict) restoredFrameDict = CGRectCreateDictionaryRepresentation(CGRectZero);
CGRectMakeWithDictionaryRepresentation(restoredFrameDict, &contentRect);

// Switch over to new datasource
self.listTableView.dataSource = [self dataSourceForScope:newScope];
[self.listTableView reloadData];

// Restore content offset for "newScope"; Also stops scrolling
[self.listTableView scrollRectToVisible:contentRect animated:NO];

CFDictionaryRefNSDictionary *の互換性のある使用に注意してください

2
ohhorob

'decelerating'プロパティがNOになるのを待って(たとえば、KVOを使用して)、その後切り替えることができます。

0
Nikolai Ruhe

テーブルのセレクターとしてUISwitchを使用していたとき、それは私の問題でした。しかし、セグメント化されたコントロールでは、問題はありません。たぶんあなたはテーブルをリロードしなかったのですか?これは私の作業コードです:

NSIndexPath *exPath = [[subTable indexPathsForVisibleRows] lastObject]; 

isMatchOn = [whatList selectedSegmentIndex] == 0 ? YES : NO;  //table source will make the choice looking at this BOOL  

[subTable reloadData];  // here tables actually flip

if (lastPosition) {
    [subTable scrollToRowAtIndexPath:lastPosition atScrollPosition:UITableViewScrollPositionBottom animated:NO];   //I scroll to saved index
    }
self.lastPosition = exPath;  //here I save the current position
0
Jim75

明らかな回避策の1つは、スワップアウトされる2つの個別のテーブルビューを用意し、各データソースをテーブルビューの1つに永続的に接続することです。これはちょっとした記憶の無駄のように思えましたが、おそらく私はそれを考えすぎています。

0
Daniel Dickison

特定のself.tableView.isScrollEnabled = true/false値に達したときにtableView.contentOffset.yを実行することもできます

0
Zack Shapiro