web-dev-qa-db-ja.com

iOS7でセルを選択すると、UITableView区切り線が消える

TableViewで、セル間に区切り線を設定します。複数のセルを選択できます。選択したセルの背景色を設定するための私のコードは次のとおりです。

UIView *cellBackgroundColorView = [[UIView alloc] initWithFrame:cell.frame];
[cellBackgroundColorView setBackgroundColor:[UIColor darkGray]];
[cell setSelectedBackgroundView:cellBackgroundColorView];

問題は、2つの隣接するセルが選択された場合、iOS7には(予想どおり)存在するのに対し、iOS7にはそれらの間に区切り線がないことです。

cellBackgroundColorViewのフレームの高さをcell.frame - 1.0、しかしそれも機能しません。

何か案は?

48
artooras

私はまだその最下部に到達していません(一見iOS 7のバグのように見えます)。しかし、私は回避策を見つけました。 tableView:didSelectRowAtIndexPathで、以下の両方のメッセージを送信すると、問題が視覚的に解決されます(おそらくパフォーマンスコストがかかります)。

[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

これが機能するには(私にとって)、deselectRowAtIndexPath:animated:にanimated:YESが含まれている必要があります。 reloadRowsAtIndexPaths:withRowAnimation:に使用されるアニメーションは重要ではありません。

37
Mark

indexpathの行のセルにこのコードを追加します

cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.backgroundColor = [UIColor clearColor];
24
srivatasa

私の場合、私は行をアニメートしていたので、このようなものを置く必要がありました:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

[tableView beginUpdates];
[tableView deselectRowAtIndexPath:indexPath animated:NO]; 
//if you are doing any animation you have deselect the row here inside. 
[tableView endUpdates];
} 
15
GOrozco58

@samvermetteの answer は問題を解決しましたが、選択した行を最初に選択解除する必要がありました。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath  {

    //Deselect Row
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];

    // fix for separators bug in iOS 7
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; }
12
Jamal Zafar

この問題は、セルの選択スタイルをプログラムでnoneに設定し、プログラムでテーブルセルを選択したときに発生しました。

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell!
    if tableView == self.jobLevelTableView {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! CheckboxCell

        // for testing purposes
        let checked = true

        // I used M13Checkbox here, in case anybody was wondering
        cell.checkbox.setCheckState(checked ? .checked : .unchecked, animated: false) 

        if checked {
            tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        }

        // CULPRIT
        cell.selectionStyle = .none
        return cell
    }

    cell = UITableViewCell()
    return cell
}

ストーリーボードで選択スタイルを設定すると(および同等のコードを削除すると)、問題はなくなりました!

Storyboard is useful

5
remingtonchan

これはiOS 7.0.3の時点ではまだ問題のようですが、セパレータを偽造するための洗練されていない手段でそれを回避しました。

最初にUITableViewの区切りスタイルをUITableViewCellSeparatorStyleNoneに設定します。その後、カスタムUITableViewCellサブクラスを使用して、選択状態と非選択状態の両方のセル間のセパレーターを偽造できます。

@implementation MyTableViewCellSubclass

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {

        CGRect frame = self.bounds;
        frame.Origin.y = frame.size.height - 1.f;
        frame.size.height = 1.f;

        // Selected background view
        //
        UIView * separatorView = [[UIView alloc] initWithFrame:frame];
        separatorView.backgroundColor = [UIColor darkGrayColor];
        separatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin;

        UIView * selectedView = [[UIView alloc] initWithFrame:self.bounds];
        selectedView.backgroundColor = [UIColor lightGrayColor];
        [selectedView addSubview:separatorView];

        self.selectedBackgroundView = selectedView;

        // Add separator view to content view for unselected state
        //
        UIView * separatorView2 = [[UIView alloc] initWithFrame:frame];
        separatorView2.backgroundColor = [UIColor darkGrayColor];
        separatorView2.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin;

        [self.contentView addSubview:separatorView2];


    }
    return self;
}


@end
4
sho

この簡単な呼び出しは、iOS 8でそれを実現しました。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // ....
    [tableView deselectRowAtIndexPath:indexPath animated:YES]

    // ....
}
4

UITableViewCellクラスに貼り付けます。

override func layoutSubviews() {
    super.layoutSubviews()

    subviews.forEach { (view) in
        if type(of: view).description() == "_UITableViewCellSeparatorView" {
            view.alpha = 1.0
        }
    }
}
3
Morgachev

これは、iOSにデフォルトの選択されたセルスタイルを適用させる場合にのみ発生します。私がこれまでに見つけた最善の回避策は、選択したプロパティの実装をオーバーライドすることです。

セルのサブクラスの実装:

    @synthesize selected = _selected;

初期化メソッドで:

    // problem actually is caused when you set following 
    // to UITableViewCellSelectionStyleDefault, so:

    [self setSelectionStyle:UITableViewCellSelectionStyleNone]; 

メソッドのオーバーライド:

    - (BOOL)selected 
    {
        return _selected;
    }
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated 
    {
        _selected = selected
        if (selected) {

            // apply your own selected style

        }
        else {

            // apply your own deselected style

        }
    }
3
believesInSanta

選択したセルだけでなく、そのすぐ上のセルもリロードすることで、この問題を(ハックして)解決しました。上記の他のソリューションはどれも私にとってはうまくいきませんでした。

    NSIndexPath *indexPathOfCellAbove = [NSIndexPath indexPathForRow:(indexPath.row - 1) inSection:indexPath.section];

    if (indexPath.row > 0)
        [self.tableView reloadRowsAtIndexPaths:@[indexPathOfCellAbove, indexPath] withRowAnimation:UITableViewRowAnimationNone];
    else
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
2
BigSauce

-cellForRowAtIndexPath

Create two separator views (sv1, sv2)

[cell addsubview:sv1];
[cell.selectedBackgroundView addsubview:sv2];

-didSelectRowAtIndexPath

[tableView deselectRowAtIndexPath:indexPath animated:NO];
2
Praveen Matanam

私にとっては、プログラムで設定したときに起こりました。

cell.selectionStyle = UITableViewCellSelectionStyleNone;

ストーリーボードでこのプロパティを設定すると、うまく機能します。

1
Patrick Haaser

これを使って:

-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath 
 {
 UITableViewCell * cell =(UITableViewCell *)[tableView cellForRowAtIndexPath:indexPath]; 
 UIView * selectionColor = [[UIView alloc] init]; 
 selectionColor.backgroundColor = [UIColor clearColor]; 
 cell.selectedBackgroundView = selectionColor; 
 // 71 
 UIView * separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0、71、320、2)]; ///必要に応じてサイズを変更します。ここで-71-y座標、320-重量、2-高さ
 // separatorLineView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@ "divider_goriz.png"]]; //ここに画像を配置することもできます
 separatorLineView.backgroundColor = [UIColor redColor]; 
 [cell.selectedBackgroundView addSubview:separatorLineView]; 
 return YES; 
} 
0
c-villain

私にとって問題を解決したのは、beginUpdatesとendUpdatesの後にデータをリロードすることでした:

    private func animateCellHeighChangeForTableView(tableView: UITableView, withDuration duration: Double) {
        UIView.animateWithDuration(duration) { () -> Void in
           tableView.beginUpdates();
           tableView.endUpdates();
           tableView.reloadData();
        }
    }
0
Ali M

ここでの解決策は私を助けませんでした。ほとんどの場合、選択範囲を削除することが提案されましたが、セルの選択状態を維持する必要がありました。そのため、デフォルトの区切り線を無効にし、独自の区切り線を使用するという考え方です。私はこれを試しましたが、問題がありました(詳細についてはこちらを参照してください こちら )。主な問題は、accessoryViewエリアに線を引くことでした。 iOS 8でしか機能しませんでしたが、iOS 7のソリューションも必要でした。

私の要件は次のとおりです。

  • 選択を維持する必要があります
  • 行が消えてはいけません(特にセルが選択された場合)
  • 選択したセルの上の区切り線も消えないはずです

特に3番目のポイントは、iOSがUITableViewCellの次への交差に一種のアンチエイリアス効果を使用するため、問題を引き起こしました。私が見つけたように、それはiPadでのみ発生します。各方向(現在選択されているセル、上のセル)に約1ポイントのサイズがあるため、セル自体に描画されてもセル上の線は消えます(使用されているデフォルトのセルではありません)。この行が選択したセルの上または上のセルにある場合、違いはありません。この特別なレンダリング効果により、線が非表示になります。

solutionは次のようになります。

  1. backgroundViewを使用して、2本の線を描画します。上に1本(iPadではy方向に+1ポイント、iPhoneではy方向に0ポイント)と下に1本です。そのため、選択効果によってカバーされることはありません。
  2. 作成された背景ビューは、選択された状態(cell.selectedBackgroundView = selectedBackground)。他のセルではデフォルトの区切り線が有効になっています。

C#コードを使用した実例が掲載されています here ニーズに合わせて調整する必要があります。これで、選択の問題がなくなりました!

0
testing

わくわくして、この問題を解決しました。カスタムセルに次のメソッド呼び出しを追加し、カラーセパレーターとフレームを設定します。セルセパレーターを非表示にしてから、スーパービューのロードセパレーターでビューをカスタマイズします。この問題が解決されると、影響分離セルが選択されます

@interface MyCustomTableViewCell(){
   UIView *customSeparatorView;
   CGFloat separatorHight;
}
@property (nonatomic,weak)UIView *originSeparatorView;
@end

-(void)setSeparatorWithInset:(UIEdgeInsets)insets{

if (customSeparatorView) {
    customSeparatorView.frame = CGRectMake(insets.left, insets.top,self.width - insets.left - insets.right, self.originSeparatorView.height-insets.bottom - insets.top);
    self.originSeparatorView.hidden = YES;
    self.originSeparatorView.alpha = 0;
}else{
    for (int i = ([self.contentView.superview.subviews count] - 1); i >= 0; i--) {
        UIView *subView = self.contentView.superview.subviews[i];
        if ([NSStringFromClass(subView.class) hasSuffix:@"SeparatorView"]) {
            self.originSeparatorView = subView;
            subView.hidden = YES;
            subView.alpha = 0;
            subView.frame = CGRectMake(insets.left, insets.top,self.width - insets.left - insets.right, subView.height-insets.bottom - insets.top);

            customSeparatorView = [[subView superview] viewWithTag:separatorViewTag];
            if (!customSeparatorView) {
                customSeparatorView = [[UIView alloc] initWithFrame:subView.frame];

                customSeparatorView.tag = separatorViewTag;
                [[subView superview] addSubview:customSeparatorView];
                customSeparatorView.backgroundColor = [subView backgroundColor];
            }
            [[subView superview] bringSubviewToFront:customSeparatorView];
            break;
        }
    }
  }
}


-(void)setSeparatorColorWithColor:(UIColor *)sepColor{
if (customSeparatorView) {
    customSeparatorView.backgroundColor = sepColor;

    self.originSeparatorView.hidden = YES;
    self.originSeparatorView.alpha = 0;
}else {
    for (int i = ([self.contentView.superview.subviews count] - 1); i >= 0; i--) {
        UIView *subView = self.contentView.superview.subviews[i];
        if ([NSStringFromClass(subView.class) hasSuffix:@"SeparatorView"]) {
           self.originSeparatorView = subView;

            if (sepColor) {
                subView.hidden = YES;
                subView.alpha = 0;
                subView.backgroundColor = sepColor;

                customSeparatorView = [[subView superview] viewWithTag:separatorViewTag];
                if (!customSeparatorView) {
                    customSeparatorView = [[UIView alloc] initWithFrame:subView.frame];

                    customSeparatorView.tag = separatorViewTag;
                    [[subView superview] addSubview:customSeparatorView];
                    customSeparatorView.backgroundColor = [subView backgroundColor];
                }
                [[subView superview] bringSubviewToFront:customSeparatorView];
            }
            break;
        }
    }
  }
}

 -(void)layoutSubviews{
    [super layoutSubviews];
    [self setSeparatorWithInset:UIEdgeInsetsMake(0, 0, 0, 0)];
    [self setSeparatorColorWithColor:[UIColor colorWithRed:31/255.0 green:32/255.0f blue:35/255.0 alpha:0.2]];
 }

この問題は、単一セルの選択にも存在します。

別の解決策は、テーブルビューをリロードし、選択してから選択解除することです。

self.selectedIndex = inIndexPath.row;
[inTableView reloadData];
[inTableView selectRowAtIndexPath:inIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[inTableView deselectRowAtIndexPath:inIndexPath animated:YES];

これは、Markのソリューションで見た微妙なグラフィカル選択の不具合を取り除きます。

0
Morrowless

次のものが必要でした:

「ユーザーが行を選択すると、選択の背景色は透明/白/何でもいいし、区切り線は消えない」

次の問題の解決策も探しました。

「テーブル(プレーンタイプのテーブル)で行を選択すると、選択色がグレーになり、cell.selectionStyleをnoneに設定すると、セル間のセパレータが消えました。」

Xcode-9.2バージョン

次の解決策が見つかりました。

  1. in 'tableView(.... cellForRowAT ...)' let colorView = UIView(frame: CGRect(x: 0.0, y: 3.0, width: cell.frame.width, height: cell.frame.height - 1.0)) colorView.backgroundColor = UIColor.white UITableViewCellClass.appearance().selectedBackgroundView = colorView

UITableViewCellClass-プロトタイプセルクラスで、選択色を白に変更できます

  1. in 'tableView(... didSelectRowAt)' cell.selectionStyle = .none

  2. uITableViewCellClass(プロトタイプセルクラス)

    func layoutSubviews()をオーバーライドします{super.layoutSubviews()

    subviews.forEach { (view) in
        if type(of: view).description() == "_UITableViewCellSeparatorView" {
            view.alpha = 1.0
        }
    }
    

    }

選択した行をチェックマークで維持し、すべての区切り文字を配置できます。

0
Anton Romanov

私がしたことはこれでした:

  1. セルのコンテンツビューの下に新しいサブビューを追加します。
  2. これをselectedBackgroundViewとしてセルから接続します。
  3. 新しく選択した背景ビューのサブビューを追加します。左から16ピクセルで開始し、残りの幅をカバーするように設定します。高さは1ピクセル、上から1ピクセル、背景色は90%白です。

私の場合、選択時に行をまったくシェーディングしたくないので、選択した背景ビューをクリアのままにしましたが、好きな色に変更できます。

また、自動レイアウトを使用していないため、サイズを適切に設定してください。自動レイアウトでは、適切な制約を設定する必要があると思います。

私にとっては、これで問題は完全に解決しました(これは本当にiOS 7のバグのようです)。

0
Gideon King

とにかく、このソリューションは自分のセルでbackgroundViewを使用していない人には役に立たないでしょう:

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [cell setBackgroundColor:[UIColor grayColor]];
    }

これにより、テーブルをリロードすることなく、迷惑な視覚効果が大幅に削減されます。もちろん、あなたの場合の結果を改善するのに役立つものでgrayColorを変更できます

0
Fabio Napodano

セパレーターのインセットを0に設定することもできます。私はそれを行い、問題を解決しましたが、インセットの見栄えが良くないというトレードオフがあります。

0
skantner