UITableViewCell
タップすると選択されるものがあります。この選択された状態の間に、ユーザーがセルをもう一度タップした場合、セルの選択を解除します。
ヒットしているデリゲートコールが見つかりません。これを実装する方法はありますか?それは本当にジェスチャー認識機能になるのでしょうか?
UITableViewCell
タップすると選択されるものがあります。この選択された状態の間に、ユーザーがセルをもう一度タップした場合、セルの選択を解除します。
ヒットしているデリゲートコールが見つかりません。これを実装する方法はありますか?それは本当にジェスチャー認識機能になるのでしょうか?
これは、デリゲートメソッドを使用して実際に行うことができますwillSelectRowAtIndexPath:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isSelected]) {
// Deselect manually.
[tableView.delegate tableView:tableView willDeselectRowAtIndexPath:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView.delegate tableView:tableView didDeselectRowAtIndexPath:indexPath];
return nil;
}
return indexPath;
}
deselectRowAtIndexPath:
デリゲートメソッドは自動的に呼び出されないため、手動で呼び出す必要があることに注意してください。
Swift 4:
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if let indexPathForSelectedRow = tableView.indexPathForSelectedRow,
indexPathForSelectedRow == indexPath {
tableView.deselectRow(at: indexPath, animated: false)
return nil
}
return indexPath
}
「複数選択」モードを使用している場合、すでに選択されている行をクリックしても「didSelectRowAtIndexPath」は呼び出されません。「単一選択」モードでもプログラムで複数の行を選択でき、すべてのクリックで行がdidSelectRowAtIndexPathをトリガーします。
同じ問題を抱えていた人に向かってください。
さらにクリーンなソリューションは次のとおりです。
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[tableView indexPathForSelectedRow] isEqual:indexPath]) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
return nil;
}
return indexPath;
}
単一選択モードをオンのままにしますが、次のような機能をオーバーライドします。
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false {
tableView.deselectRow(at: indexPath, animated: true)
return nil
}
return indexPath
}
override func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
return nil
}
セルを選択すると、このデリゲートメソッドがトリガーされます。
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *theUITableViewCell = [tableView cellForRowAtIndexPath:path];
if (theUITableViewCell.selected == YES){
self.tableView deselectRowAtIndexPath:<#(NSIndexPath *)#> animated:<#(BOOL)#>
// Do more thing
}else{
// By default, it is highlighted for selected state
}
}
擬似コードです。
ブルーのセレクションカラーを使ってトグルすると変な印象になるのではないかと思います。チェックマークのようなアクセサリーを使ってみませんか?これは、選択を切り替えるためのはるかに馴染みのある手法です(マルチセルまたはシングルセル)。
詳細については、この回答を参照してください: UITableView複数選択
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isSelected]) {
// Deselect manually.
if ([tableView.delegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]) {
[tableView.delegate tableView:tableView willDeselectRowAtIndexPath:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([tableView.delegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]) {
[tableView.delegate tableView:tableView didDeselectRowAtIndexPath:indexPath];
}
return nil;
}
return indexPath;
}
あなたはこれを試すことができます、それは私のために働きます(単一の選択または複数の選択のために):
A.次のようにviewDidLoadにプライベートNSMutableArrayを割り当てます。
@interface XXXViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
NSMutableArray * selectedZoneCellIndexPaths;
}
- (void)viewDidLoad
{
selectedZoneCellIndexPaths = [[NSMutableArray alloc] init];
}
B. UITableViewDelegate didSelectRowに、次の行を追加します
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for (NSIndexPath * iter in selectedZoneCellIndexPaths)
{
if (indexPath.section == iter.section && indexPath.row == iter.row)
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[selectedZoneCellIndexPaths removeObject:iter];
return;
}
}
[selectedZoneCellIndexPaths addObject:indexPath];
return;
}
prisonerjohnの答えの迅速なバージョン:
public func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell?.selected ?? false) {
// Deselect manually.
tableView.delegate!.tableView?(tableView, willDeselectRowAtIndexPath: indexPath)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
tableView.delegate!.tableView?(tableView, didDeselectRowAtIndexPath: indexPath)
return nil
}
return indexPath;
}
@prisonerjohnから、Swift 3で、@ Patrickが言ったように、デリゲートがセレクターに応答するかどうかを確認する方法を誰かが疑問に思った場合に備えて:
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
guard let cell = tableView.cellForRow(at: indexPath) else {
// Handle invalid cell
...
}
if cell.isSelected {
if let respond = tableView.delegate?.responds(
to: #selector(tableView(_:willDeselectRowAt:))),
respond == true {
tableView.delegate?.tableView!(tableView, willDeselectRowAt: indexPath)
}
tableView.deselectRow(at: indexPath, animated: true)
if let respond = tableView.delegate?.responds(
to: #selector(tableView(_:didDeselectRowAt:))),
respond == true {
tableView.delegate?.tableView!(tableView, didDeselectRowAt: indexPath)
}
return nil
}
return indexPath
}
スウィフト5。
では、UITableViewDelegate
次のように簡単です。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
私は同じことを求めていましたが、@occulusの答えは私が欠けていたヒントを私に提供しました。
これを行う方法は、テーブルビューで複数選択できるようにし、デリゲートメソッドの1つを使用して新しい行が選択されたときに、以前に選択した行を手動で選択解除することです。
単一選択モードでは、テーブルビューが1つの行を可能な限り選択したままにしようとするため、選択した行をタップしても選択が解除されないのは非常に自然なことのようです。
たぶん私の質問は十分に具体的ではありませんでしたが、2つの答えは私が求めていたものより少し広いです。
これは不可能のようです。セルのジェスチャ認識機能を使用して、選択済み/非選択状態を手動で設定しました。