[[ともっくす alloc] init]

ともっくすの雑多な日記と技術的なメモ

UITableViewの2種類のデータをスクロール位置を保持したまま切り替えたい

タイトルそのまま.


やりたいこと:

  • UITableViewの2種類のデータをボタンを押すことで切り替えたい
  • 切り替えを戻したときにスクロール位置は前の状態のままにしたい

うん,日本語が難しい.

データの切り替え

これは簡単.

reloadData

を呼び出すだけ.


ここでは,2つのデータを用意する.

  1. 動物データ(_data1)
    • ヒト/犬/猫/猿/パンダ/キリン/やぎ
    • カラス/すずめ/鳩/インコ/オウム
    • たい/こい/めだか/まぐろ
  2. 国数データ(_data2)
    • 漢字/古典/長文読解/文法/敬語
    • 四則演算/方程式/幾何/三角関数/作図/証明/微積/行列/整数問題

なんで,こんなデータかというと,特に意味は無い.

それらをNSArrayに格納する.
_data1,_data2ともに,NSArray型の変数.

_data1 = @[@[@"ヒト", @"犬", @"猫", @"猿", @"パンダ", @"キリン", @"やぎ"], @[@"カラス", @"すずめ", @"鳩", @"インコ", @"オウム"], @[@"たい", @"こい", @"めだか", @"まぐろ"]];
_data2 = @[@[@"漢字", @"古典", @"長文読解", @"文法", @"敬語"], @[@"四則演算", @"方程式", @"幾何", @"三角関数", @"作図", @"証明", @"微積", @"行列", @"整数問題"]];


どちらのデータを表示するかを表すint型の変数_tableTypeを用意する.

_tableType=1のときが動物データ,_tabeleType=2のときが国数データとする.


で,適当にStoryBoardを使って,ボタンを2つ設置し,それぞれのアクションを設定する.
ボタン1が押されたら動物データを表示する.

プロパティとして,tableViewというUITableViewの変数があるとすると,

- (IBAction)press1:(id)sender
{
    if (_tableType == 2) {
        _tableType = 1;
        [self.tableView reloadData];
    }
}

って感じ.

これをボタン2が押されたときのも作る.


これで,ボタン1を押したら動物データ,ボタン2を押したら国数データが表示ってできる.


本当は,全体を更新するのではなく,見える部分だけを更新するのが良かったりするのかもしれない.
けど,わからない.

スクロール位置の保持

これも簡単だった.


現在のスクロール位置は,

contentOffset

で取得できる.

だから,切り替え時に,それを覚えておけばいい.


動物データのテーブルのスクロール位置を_point1,国数データのテーブルのスクロール位置を_point2として,さっきのpress1メソッドを書き換える(press2メソッドも):

- (IBAction)press1:(id)sender
{
    if (_tableType == 2) {
        _tableType = 1;
        _point2 = [self.tableView contentOffset];
        [self.tableView reloadData];
        [self.tableView setContentOffset:_point1];
    }
}

こんな感じ.

_point2 = [self.tableView contentOffset];

で,切り替え前のスクロール位置を保持し,

[self.tableView setContentOffset:_point1];

で,前のスクロール位置をセットする.


これで,スクロール位置を保持したまま,切り替えが可能になる.

まとめ

こんな感じ.

ついでに,タイトルも変更するようにしてみた.


SwitchTableViewController.h

#import <UIKit/UIKit.h>

@interface SwitchTableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end


SwitchTableViewController.m

#import "SwitchTableViewController.h"

@interface SwitchTableViewController ()

@end

@implementation SwitchTableViewController
{
    int _tableType;
    NSArray *_data1;
    NSArray *_data2;
    CGPoint _point1;
    CGPoint _point2;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    _tableType = 1;

    _data1 = @[@[@"ヒト", @"犬", @"猫", @"猿", @"パンダ", @"キリン", @"やぎ"], @[@"カラス", @"すずめ", @"鳩", @"インコ", @"オウム"], @[@"たい", @"こい", @"めだか", @"まぐろ"]];
    _data2 = @[@[@"漢字", @"古典", @"長文読解", @"文法", @"敬語"], @[@"四則演算", @"方程式", @"幾何", @"三角関数", @"作図", @"証明", @"微積", @"行列", @"整数問題"]];
    
    _point1 = CGPointMake(0, 0);
    _point2 = CGPointMake(0, 0);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    if (_tableType == 1) {
        return [_data1 count];
    } else {
        return [_data2 count];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (_tableType == 1) {
        return [_data1[section] count];
    } else {
        return [_data2[section] count];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }
    
    NSString *data;
    if (_tableType == 1) {
        data = _data1[indexPath.section][indexPath.row];
    } else {
        data = _data2[indexPath.section][indexPath.row];
    }
    cell.textLabel.text = data;
    
    return cell;
}

- (IBAction)press1:(id)sender
{
    if (_tableType == 2) {
        _tableType = 1;
        _point2 = [self.tableView contentOffset];
        self.title = @"動物";
        [self.tableView reloadData];
        [self.tableView setContentOffset:_point1];
    }
}

- (IBAction)press2:(id)sender
{
    if (_tableType == 1) {
        _tableType = 2;
        _point1 = [self.tableView contentOffset];
        self.title = @"国数";
        [self.tableView reloadData];
        [self.tableView setContentOffset:_point2];
    }
}

@end


storyboard


で,できたのが,こんな感じ.



切り替えが可能で,スクロール位置も覚えてくれている.

上のbackボタンは無視する感じで.