web-dev-qa-db-ja.com

セルを選択するとUITableViewCellサブビューが消えます

ユーザーが10色(製品によって異なる)の中から選択できる色選択テーブルビューを実装しています。ユーザーは、他のオプション(ハードドライブの容量など)も選択できます。

すべての色オプションは、独自のTableViewセクション内にあります。

TextLabelの左側に、実際の色を示す小さな正方形を表示したい。

今、私は単純な正方形のUIViewを追加し、次のように正しい背景色を与えます:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RMProductAttributesCellID];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:RMProductAttributesCellID] autorelease];
        cell.indentationWidth = 44 - 8;

        UIView *colorThumb = [[[UIView alloc] initWithFrame:CGRectMake(8, 8, 28, 28)] autorelease];
        colorThumb.tag = RMProductAttributesCellColorThumbTag;
        colorThumb.hidden = YES;
        [cell.contentView addSubview:colorThumb];
    }

    RMProductAttribute *attr = (RMProductAttribute *)[_product.attributes objectAtIndex:indexPath.section];
    RMProductAttributeValue *value = (RMProductAttributeValue *)[attr.values objectAtIndex:indexPath.row];
    cell.textLabel.text = value.name;
    cell.textLabel.backgroundColor = [UIColor clearColor];

    UIView *colorThumb = [cell viewWithTag:RMProductAttributesCellColorThumbTag];
    colorThumb.hidden = !attr.isColor;
    cell.indentationLevel = (attr.isColor ? 1 : 0);

    if (attr.isColor) {
        colorThumb.layer.cornerRadius = 6.0;
        colorThumb.backgroundColor = value.color;
    }

    [self updateCell:cell atIndexPath:indexPath];

    return cell;
}

これは問題なく表示されます。

私の唯一の問題は、「色」行を選択すると、青へのフェード選択アニメーション中に、カスタムUIView(colorThumb)が非表示になることです。選択/選択解除アニメーションが終了した直後に再び表示されますが、これはいアーティファクトを生成します。

これを修正するにはどうすればよいですか?サブビューを適切な場所に挿入しませんか?

(didSelectRowAtIndexPathには特別なものはありません。セルのアクセサリをチェックボックスに変更するか、何も変更せずに、現在のindexPathを選択解除します)。

176
Cyrille

UITableViewCellは、セルが選択または強調表示されるときにすべてのサブビューの背景色を変更します。TableviewセルのsetSelected:animatedおよびsetHighlighted:animatedをオーバーライドし、ビューの背景色をリセットすると、この問題を解決できます。

Objective Cの場合:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
   UIColor *color = self.yourView.backgroundColor;        
   [super setSelected:selected animated:animated];

    if (selected){
        self.yourView.backgroundColor = color;
    }
}

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{
    UIColor *color = self.yourView.backgroundColor;        
    [super setHighlighted:highlighted animated:animated];

    if (highlighted){
        self.yourView.backgroundColor = color;
    }
}

Swift 3.1で:

override func setSelected(_ selected: Bool, animated: Bool) {
    let color = yourView.backgroundColor         
    super.setSelected(selected, animated: animated)

    if selected {
        yourView.backgroundColor = color
    }
}

override func setHighlighted(_ highlighted: Bool, animated: Bool) {
    let color = yourView.backgroundColor
    super.setHighlighted(highlighted, animated: animated)

    if highlighted {
        yourView.backgroundColor = color
    }
}
224
Yatheesha B L

これは、テーブルビューセルが、強調表示された状態のコンテンツビュー内のすべてのビューの背景色を自動的に変更するためです。 UIViewをサブクラス化して色を描画するか、UIImageViewを使用してカスタム1x1ピクセルのストレッチ画像を使用することを検討できます。

121
Andriy

TableViewCellの選択/強調表示メソッドをいじるのではなく、かなりエレガントなソリューションを見つけました。背景色をクリアカラーに設定することを無視するUIViewのサブクラスを作成できます。

Swift 3/4:

class NeverClearView: UIView {
    override var backgroundColor: UIColor? {
        didSet {
            if backgroundColor != nil && backgroundColor!.cgColor.alpha == 0 {
                backgroundColor = oldValue
            }
        }
    }
}

スイフト2:

class NeverClearView: UIView {
    override var backgroundColor: UIColor? {
        didSet {
            if CGColorGetAlpha(backgroundColor!.CGColor) != 0 {
                backgroundColor = oldValue
            }
        }
    }
}

Obj-Cバージョン:

@interface NeverClearView : UIView

@end

@implementation NeverClearView

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    if (CGColorGetAlpha(backgroundColor.CGColor) != 0) {
        [super setBackgroundColor:backgroundColor];
    }
}

@end
43
Pavel Gurov

問題を管理する別の方法は、次のようなコアグラフィックスグラデーションでビューを塗りつぶすことです。

CAGradientLayer* gr = [CAGradientLayer layer];
gr.frame = mySubview.frame;
gr.colors = [NSArray arrayWithObjects:
                     (id)[[UIColor colorWithRed:0 green:0 blue:0 alpha:.5] CGColor]
                     ,(id)[[UIColor colorWithRed:0 green:0 blue:0 alpha:.5] CGColor]
                     , nil];

gr.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0],[NSNumber numberWithFloat:1],nil];

[mySubview.layer insertSublayer:gr atIndex:0];
9
Agat

Swift 2.2の場合、これは機能します

cell.selectionStyle = UITableViewCellSelectionStyle.None

そして、理由は@ Andriy で説明されています

これは、テーブルビューセルが、強調表示された状態のコンテンツビュー内のすべてのビューの背景色を自動的に変更するためです。

9
swiftBoy

Yatheesha B L 's answer に触発されて、この透明度の「機能」をオン/オフできるUITableViewCellカテゴリ/拡張機能を作成しました。

Swift

let cell = <Initialize Cell>
cell.keepSubviewBackground = true  // Turn  transparency "feature" off
cell.keepSubviewBackground = false // Leave transparency "feature" on

Objective-C

UITableViewCell* cell = <Initialize Cell>
cell.keepSubviewBackground = YES;  // Turn  transparency "feature" off
cell.keepSubviewBackground = NO;   // Leave transparency "feature" on

KeepBackgroundCellはCocoaPodsと互換性があります。あなたはそれを見つけることができます GitHubで

8
Tim Bodeit

cell.selectionStyle = UITableViewCellSelectionStyleNone;してから、- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPathでbackgroundColorを設定できます

7
gumpwang

場合によっては、これはセル内のすべてのアイテムの灰色を取得しないようにするセプツです(カスタムテーブルビューセルを使用している場合):

  1. SelectionStyleを.noneに設定します???? selectionStyle = .none

  2. このメソッドをオーバーライドします。

    func setHighlighted(_強調表示:Bool、アニメーション:Bool)

  3. スーパーを呼び出して、スーパーセットアップの利点を取得します。

    super.setHighlighted(強調表示、アニメーション:アニメーション)

  4. 必要なロジックを強調表示します。

    override func setHighlighted(_ highlighted: Bool, animated: Bool) {
          super.setHighlighted(highlighted, animated: animated)
          // Your Highlighting Logic goes here...
    }
    
4
Abo3atef

Yatheesha B L の答えに触発されました。

Super.setSelected(selected、animated:animated)を呼び出すと、設定したすべての背景色がクリアされます。そのため、スーパーメソッドを呼び出しません

In Swift:

override func setSelected(selected: Bool, animated: Bool) {    
    if(selected)  {
        contentView.backgroundColor = UIColor.red 
    } else {
        contentView.backgroundColor = UIColor.white
    }
}

override func setHighlighted(highlighted: Bool, animated: Bool) {
    if(highlighted) {
        contentView.backgroundColor = UIColor.red 
    } else {
        contentView.backgroundColor = UIColor.white
    }
}
3
Milan Kamilya

UITableViewCellは、何らかの理由で選択時にすべてのサブビューのbackgroundColorを変更します。

これは役立つかもしれません:

DVColorLockView

そのようなものを使用して、選択中にUITableViewがビューの色を変更しないようにします。

3
DylanVann

背景色を設定する代わりにビューを描画します

import UIKit

class CustomView: UIView {

    var fillColor:UIColor!

    convenience init(fillColor:UIColor!) {
        self.init()
        self.fillColor = fillColor
    }

    override func drawRect(rect: CGRect) {
        if let fillColor = fillColor {
            let context = UIGraphicsGetCurrentContext()
            CGContextSetFillColorWithColor(context, fillColor.CGColor);
            CGContextFillRect (context, self.bounds);

        }
    }


}
1
PeiweiChen

setSelectedsetHighlightedをオーバーライドすることを忘れないでください

override func setHighlighted(highlighted: Bool, animated: Bool) {

    super.setHighlighted(highlighted, animated: animated)
    someView.backgroundColor = .myColour()
}

override func setSelected(selected: Bool, animated: Bool) {

    super.setSelected(selected, animated: animated)
    someView.backgroundColor = .myColour()
}
0
Magoo

Paul Gurovの回答に基づいて、Xamarin.iOSに次のコードを実装しました。 C#バージョン:

NeverClearView.cs

public partial class NeverClearView : UIView
{
    public NeverClearView(IntPtr handle) : base(handle)
    {
    }

    public override UIColor BackgroundColor
    {
        get
        {
            return base.BackgroundColor;
        }
        set
        {
            if (value.CGColor.Alpha == 0) return;

            base.BackgroundColor = value;
        }
    }
}

NeverClearView.designer.cs

[Register("NeverClearView")]
partial class NeverClearView
{
    void ReleaseDesignerOutlets()
    {
    }
}
0
Citroenfris

自動背景色の変更を無視したい1つのセルサブビューを除き、デフォルトの選択動作を維持したかった。しかし、他のときに背景色を変更できるようにする必要もありました。

私が思いついた解決策はUIViewをサブクラス化することで、通常は背景色の設定を無視し、別の機能を追加して保護をバイパスしました。

Swift 4

class MyLockableColorView: UIView {
    func backgroundColorOverride(_ color: UIColor?) {
            super.backgroundColor = color
    }

    override var backgroundColor: UIColor? {
        set {
            return
        }
        get {
            return super.backgroundColor
        }
    }
}
0
zekel

SIMPLESTアニメーションにバグがなく(最高評価の回答のように)、サブクラス化と描画なしのソリューション-backgroundColorの代わりにレイヤーの境界線の色を設定し、非常に大きな境界線の幅を設定します。

colorThumb.layer.cornerRadius = 6
colorThumb.layer.borderWidth = colorThumb.frame.width
colorThumb.layer.borderColor = value.color
0

このコードをUITableViewCellのサブクラスに配置します

Swift 3構文

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    if(selected) {
        lockerSmall.backgroundColor = UIColor.init(red: 233/255, green: 106/255, blue: 49/255, alpha: 1.0)
    }
}


override func setHighlighted(_ highlighted: Bool, animated: Bool) {
    super.setHighlighted(highlighted, animated: animated)

    if(highlighted) {
        lockerSmall.backgroundColor = UIColor.init(red: 233/255, green: 106/255, blue: 49/255, alpha: 1.0)
    }
}
0
Jay Mayu

ここに私のソリューションがあり、contentViewを使用してselectionColorを表示し、完璧に機能します

#import "BaseCell.h"

@interface BaseCell ()
@property (nonatomic, strong) UIColor *color_normal;
@property (nonatomic, assign) BOOL needShowSelection;
@end


@implementation BaseCell
@synthesize color_customSelection;
@synthesize color_normal;
@synthesize needShowSelection;

- (void)awakeFromNib
{
    [super awakeFromNib];
    [self setup];
}

- (void)setup
{
    //save normal contentView.backgroundColor
    self.color_normal = self.backgroundColor;
    if (self.color_normal == nil) {
        self.color_normal = [UIColor colorWithRGBHex:0xfafafa];
    }
    self.color_customSelection = [UIColor colorWithRGBHex:0xF1F1F1];
    self.accessoryView.backgroundColor = [UIColor clearColor];
    if (self.selectionStyle == UITableViewCellSelectionStyleNone) {
        needShowSelection = NO;
    }
    else {
        //cancel the default selection
        needShowSelection = YES;
        self.selectionStyle = UITableViewCellSelectionStyleNone;
    }
}

/*
 solution is here
 */
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    if (needShowSelection) {
        self.contentView.backgroundColor = self.backgroundColor = color_customSelection;
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];
    if (needShowSelection) {
        self.contentView.backgroundColor = self.backgroundColor = color_normal;
    }
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (needShowSelection) {
        UIColor *color  = selected ? color_customSelection:color_normal;
        self.contentView.backgroundColor = self.backgroundColor = color;
    }
}
0
Nick

次のコードを試してください:

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{     
[super setHighlighted:highlighted animated:animated];
//Set your View's Color here.
}
0
Mehul Thakkar

ストーリーボードを使用している場合は、別のソリューションを追加します。 UIViewのサブクラスを作成します。このサブクラスは、backgroundColorを最初に設定した後に設定することを許可しません。

@interface ConstBackgroundColorView : UIView

@end

@implementation ConstBackgroundColorView

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    if (nil == self.backgroundColor) {
        [super setBackgroundColor:backgroundColor];
    }
}

@end
0
mofojed

上記のバックグラウンドソリューションで問題が解決しない場合、tableViewのdatasourceに問題がある可能性があります。

私の場合、デリゲートおよびdataSource tableViewメソッドを処理するために、DataSourceオブジェクト(BoxDataSourceと呼ばれる)のインスタンスを作成していました。

//In cellForRowAtIndexPath, when setting up cell
let dataSource = BoxDataSource(delegate: self)
cell.tableView.dataSource = dataSource
return cell

これにより、セルがタップされるたびにdataSourceの割り当てが解除され、すべてのコンテンツが消えていました。その理由は、ARCの割り当て解除/ガベージコレクションの性質です。

これを修正するには、カスタムセルに移動し、データソース変数を追加する必要がありました。

//CustomCell.Swift
var dataSource: BoxDataSource?

次に、dataSourceをcellForRowで作成したセルのdataSource varに設定する必要があるため、これはARCで割り当て解除されません。

cell.statusDataSource = BoxAssigneeStatusDataSource(delegate: self)
cell.detailsTableView.dataSource = cell.statusDataSource
return cell

お役に立てば幸いです。

0
Josh O'Connor

これはPavel Gurovの答えに似ていますが、任意の色を永続的にすることができるという点でより柔軟です。

class PermanentBackgroundColorView: UIView {
    var permanentBackgroundColor: UIColor? {
        didSet {
            backgroundColor = permanentBackgroundColor
        }
    }

    override var backgroundColor: UIColor? {
        didSet {
            if backgroundColor != permanentBackgroundColor {
                backgroundColor = permanentBackgroundColor
            }
        }
    }
}
0
user3352495