簡體   English   中英

設備旋轉后UITableView校正滾動位置

[英]UITableView correcting scroll position after device rotation

我正在為一本書建立類似讀者的東西。 當用戶旋轉手機時,我想增加字體大小。 我正在使用UITableView來顯示文本塊。

問題是,增加字體大小會增加表視圖中行的高度,如果我在縱向模式下讀取段落320,我在橫向模式下會得到280或類似的東西。

我已使用以下代碼設置了旋轉通知偵聽器:

    UIDevice *device = [UIDevice currentDevice];                
    [device beginGeneratingDeviceOrientationNotifications];
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self                                
           selector:@selector(orientationChanged:)
               name:UIDeviceOrientationDidChangeNotification
             object:device];

並嘗試在旋轉之前保存最后一個段落索引,然后在旋轉后向下滾動到它,但我似乎無法達到預期的效果。

什么是處理這種情況的最佳方法,我在哪里實際實現“之前”和“之后”輪換狀態?

我希望它可以在iOS 4+上運行。

Swift 3版本的Said Ali Samed的答案( willRotateToInterfaceOrientationdidRotateFromInterfaceOrientation已棄用):

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    coordinator.animate(alongsideTransition: { context in
            // Save the visible row position
            self.visibleRows = self.tableView.indexPathsForVisibleRows!
            context.viewController(forKey: UITransitionContextViewControllerKey.from)
        }, completion: { context in
            // Scroll to the saved position prior to screen rotate
            self.tableView.scrollToRow(at: self.visibleRows[0], at: .top, animated: false)
        })
}

使用委托方法willRotateToInterfaceOrientation:將可見單元存儲在數組中,然后使用UITableView的另一個委托方法didRotateFromInterfaceOrientation:滾動到先前存儲在數組中的可見索引路徑。 這是推薦的,您不必依賴於在不同線程中的不一致0.2秒等待來處理后旋轉事件。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // Save the visible row position
    visibleRows = [tableview indexPathsForVisibleRows];
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    // Scroll to the saved position prior to screen rotate
    [tableView scrollToRowAtIndexPath:[visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

一個簡單的方法是存儲頂部可見單元格的索引路徑,更改字體大小然后恢復頂部單元格:

NSIndexPath* topCellIndexPath = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];
//Insert code to change font size here
[_tableView scrollToRowAtIndexPath:topCellIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];

此代碼可以放在方向更改時運行的任何方法中,例如您在問題中放置的orientationChanged:方法。

這不會考慮在單元格中間向下滾動,因此如果單元格的高度很大,則無法正常工作,並且需要使用內容偏移的更復雜的方法。 如果是這種情況,請告訴我。

由於我無法得到一個好的答案,我會回答自己。 我到處尋找,但找不到辦法做我想要的,所以我只是使用了shouldAutorotateToInterfaceOrientation方法來增加字體的大小,然后啟動一個休眠0.2秒的小線程,之后滾動到所需的行。 謝謝你的幫助。

編輯:使用委托方法willRotateToInterfaceOrientation:將可見單元格存儲在數組中,然后使用委托方法didRotateFromInterfaceOrientation:滾動到您在數組中記錄的可見索引路徑。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // Save the visible row position
    visibleRows = [tableview indexPathsForVisibleRows];
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    // Scroll to the saved position prior to screen rotate
    [tableView scrollToRowAtIndexPath:[visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

首先,要重新加載所有表格單元格,請使用[self.tableView reloadData]

其次,在( UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中添加負責收縮的代碼行。

例:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Some identifier and recycling stuff

if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
    //Make labels smaller
}
else {
    //Make them bigger
}
}

或者您可以在制作時調用updateCellForRotate:forRow:方法。 但我不確定這個功能是如何工作的,所以我不能太具體。

  - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)
fromInterfaceOrientation 
{
NSLog(@"didRotateFromInterfaceOrientation:%d",fromInterfaceOrientation);
[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
}

然后我建議將interfaceOrientation數或簡單的表寬添加到出隊單元名稱,這樣tableView知道一次旋轉中的單元格與另一次旋轉中的單元格不同。 像這樣:

- (UITableViewCell *)tableView:(UITableView *)tv
     cellForRowAtIndexPath:(NSIndexPath *)indexPath
     withType:(NSString *)s_type
{

UITableViewCell *cell = nil;
// add width of table to the name so that rotations will change the cell dequeue names
s_cell = [s_cell stringByAppendingString:
          [NSString stringWithFormat:@"%@%d",@"Width",(int)tv.bounds.size.width]
          ];

NSLog(@"%@",s_cell);
cell = [tv dequeueReusableCellWithIdentifier:s_cell];
if( cell == nil ) { 
    cell = [[[UITableViewCell alloc]
             initWithFrame:CGRectZero reuseIdentifier:s_cell] autorelease];
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM