셀을 선택하면 UITableViewCell 서브 뷰가 사라짐


178

사용자가 10 가지 색상 중에서 선택할 수있는 색상 선택기 테이블보기를 구현하고 있습니다 (제품에 따라 다름). 사용자는 다른 옵션 (하드 드라이브 용량 등)을 선택할 수도 있습니다.

모든 색상 옵션은 자체 테이블 뷰 섹션 내에 있습니다.

실제 색상을 보여주는 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를 선택 취소하면됩니다).


upadteCell은 무엇에 관한 것입니까?
Idan

updateCell은 확인 표시 설정 여부, 가용성에 따라 텍스트 색상 선택 등의 약간의 조정을 수행하지만 셀 자체 또는 colorThumb와 관련된 실제 변경은 없습니다.
Cyrille

허용 된 답변으로 해결책을 제공하지 않습니다. 해결책에 대한 아래 답변을 참조하십시오
Pavel Gurov

답변:


227

UITableViewCell셀을 선택하거나 강조 할 때 재정의 tableview 세포의이 문제를 해결할 수있는, 모든 서브 뷰의 배경색을 변경 setSelected:animated하고 setHighlighted:animated볼의 배경 색상을 재설정.

목표 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;
    }
}

스위프트 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
    }
}

우리는 필요하십니까 if (highlighted)if (selected)조건을? 그러한 조건이 없다면 효과가 있다고 생각합니다.
Rishabh Tayal

@RishabhTayal 기본적으로 같은 값으로 변수를 재정의하는 것을 피하는 것입니다.
cameloper

1
항목을 선택하는 동안 배경색을 변경하면 항목을 선택하지 않으면 이전 (잘못된) 색이 복원 될 수 있습니다. 이 경우 if (강조 표시) 및 if (선택) 조건을 제거하십시오.
Marcel W

이 방법은 애니메이션을 취소하므로 의미가 없습니다. 셀 선택 스타일을 .none으로 설정하는 것이 좋습니다.
Alexander Danilov 2014 년

122

테이블 뷰 셀은 강조 표시된 상태를 위해 컨텐츠 뷰 내의 모든 뷰의 배경색을 자동으로 변경하기 때문입니다. UIView색상을 그리거나 UIImageView사용자 정의 1x1 px 확장 이미지와 함께 사용하기 위해 서브 클래 싱 을 고려할 수 있습니다 .


1
바보 야 물론, 선택 애니메이션이 올바르게 발생할 수 있도록 서브 뷰는 투명해야합니다. 감사!
Cyrille

52
또는 배경색 재정의 setHighlighted:animated:setSelected:animated:
재설정

1
어떻게 든 배경색을 재설정하지 못했습니다 (iOS 8.1에서 실행). 대신 내 뷰를 서브 클래 싱하고 setBackgroundColor를 [super setBackgroundColor : [UIColor whiteColor]]로 재정 의하여이 문제를 해결했습니다.
bizz84

44

tableViewCell 선택 / 하이라이트 방법을 사용하는 대신 매우 우아한 솔루션을 찾았습니다. 배경색을 명확한 색으로 설정하는 것을 무시하는 UIView의 서브 클래스를 작성할 수 있습니다.

스위프트 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

사랑 스럽습니다. "배지"또는 "태그"와 같이 재사용 가능한 뷰가 있으면 배경이 명확하지 않아야합니다. :: rant :: 셀 선택을 할 때 모든 자식 뷰를 투명하게 설정하는 @UIKit의 혼란스러운 솔루션. 셀의 전체 높이 또는 너비 또는 N 깊이의 하위 뷰로 최소한 제한하십시오.
SimplGy

@SimplGy 강조의 깊이는 실제로 달콤한 옵션이지만, 이봐-이것은 UIKit입니다, 나는 이것보다 훨씬 더 나쁜 것을 보았습니다 =)
Pavel Gurov

3
나는 CGColorGetAlpha (! backgroundColor로 .CGColor) == 0이 clearColor 등가가 아닌 같은 경우 변경 후 나를 위해 일한
piltdownman7

9

문제를 관리하는 또 다른 방법은 다음과 같이 핵심 그래픽 그래디언트로 뷰를 채우는 것입니다.

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];

흠, 나는이 정확한 코드를 시도하고 있으며 전혀 영향을 미치지 않습니다. 내 하위보기는 cell.contentView의 하위보기로 추가 된 UILabel이며 중요한 경우 iOS 6.0.1에서 테스트합니다.
Joe Strout 2016 년

위의 코드를 무엇에 적용합니까? 그리고 단순히 셀보기에 레이블을 추가하려고 했습니까?
Agat

이것은 내 의견으로는 완벽한 솔루션입니다. 완벽한 유연성을 유지하면서 레이어를 사용하여 문제를 완벽하게 해결합니다. UIImageView를 사용하는 솔루션이 마음에 들지 않습니다. 그라데이션이나 색상을 조정하는 것이 더 어렵 기 때문에 (매번 새 이미지를 만들어야 함) UIView를 서브 클래 싱하는 것이 과도하게 보입니다.
Erik van der Neut

@Lyida, 저는 스위프트 개발자가 아닙니다. (나는 더 많은 C # -one). 그러나 내가 본 것에서 그것은 언어에 국한된 것이 아니라 대부분 Cocoa / iOS Frameworks 논리입니다. 따라서 아이디어는 요청에 따라 결과를 얻기 위해 거의 투명한 CAGradientLayer를 뷰에 배치하는 것입니다.
Agat

9

대한 스위프트 2.2 이 작품

cell.selectionStyle = UITableViewCellSelectionStyle.None

그리고 이유는 @ Andriy에 의해 설명됩니다

테이블 뷰 셀은 강조 표시된 상태를 위해 컨텐츠 뷰 내의 모든 뷰의 배경색을 자동으로 변경하기 때문입니다.


8

Yatheesha BL답변에서 영감을 얻어이 투명도 "기능"을 켜고 끌 수있는 UITableViewCell 범주 / 확장을 만들었습니다.

빠른

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

목표 -C

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

KeepBackgroundCell은 CocoaPods와 호환됩니다. GitHub에서 찾을 수 있습니다


7

cell.selectionStyle = UITableViewCellSelectionStyleNone;다음에서 backgroundColor를 설정할 수 있습니다 .- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath


4

Yatheesha BL 의 답변에서 영감을 얻었습니다 .

super.setSelected (selected, animated : animated)를 호출 하면 설정 한 모든 배경색이 지워 집니다. 따라서 슈퍼 메소드를 호출하지 않습니다 .

스위프트에서 :

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
    }
}

1
솔루션 주셔서 감사합니다. +1 ishiglighted 변수와 sethighlighted 메소드를 재정의하는 것은 다릅니다. 정답은 메소드를 대체하는 것입니다.
Numan Karaaslan

4

경우에 따라, 이것은 셀의 모든 항목에 대해 회색을 피하기위한 Septs입니다 (사용자 정의 테이블 뷰 셀을 사용하는 경우).

  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...
    }

3

UITableViewCell은 어떤 이유로 든 선택시 모든 서브 뷰의 backgroundColor를 변경합니다.

도움이 될 수 있습니다.

DVColorLockView

이와 같은 것을 사용하여 선택하는 동안 UITableView가 뷰 색상을 변경하지 못하게하십시오.


1

배경색을 설정하는 대신보기를 그립니다.

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

애니메이션에 버그가없고 (최고 등급 답변에서와 같이) 서브 클래 싱 및 드로잉이없는 가장 간단한 솔루션 -backgroundColor 대신 레이어의 테두리 색상을 설정하고 매우 큰 테두리 너비를 설정합니다.

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

0

다음 코드를 시도하십시오.

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

0

무시하고 무시 setSelected하는 것을 잊지 마십시오setHighlighted

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

이것은 Pavel Gurov의 대답과 비슷하지만 모든 색상을 영구적으로 사용할 수 있다는 점에서 더 유연합니다.

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

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

0

자동 배경색 변경을 무시하려는 하나의 셀 하위 뷰를 제외하고 기본 선택 동작을 유지하고 싶었습니다. 그러나 다른 시간에 배경색을 변경할 수 있어야했습니다.

내가 생각해 낸 해결책은 서브 클래스였습니다. UIView 사용하여 배경색을 정상적으로 설정하는 것을 무시하고 보호를 우회하는 별도의 기능을 추가합니다.

스위프트 4

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

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

-1

여기 내 솔루션입니다, 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;
    }
}

-1

이 코드를 하위 클래스에 배치하십시오. UITableViewCell

스위프트 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)
    }
}

-1

스토리 보드를 사용하는 경우 다른 솔루션 추가 하위 클래스를 작성하여 초기 설정 후 설정을 UIView허용하지 않습니다 backgroundColor.

@interface ConstBackgroundColorView : UIView

@end

@implementation ConstBackgroundColorView

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

@end

-1

위에서 언급 한 백그라운드 솔루션으로 문제가 해결되지 않으면 datasourcetableView 에 문제가있을 수 있습니다 .

나를 BoxDataSource위해 델리게이트 및 dataSource tableView 메서드를 처리하기 위해 DataSource 객체 ( ) 인스턴스를 만들었습니다 .

//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를 varcellForRow에서 방금 만든 셀의 dataSource로 설정해야 하므로 ARC와 할당이 해제되지 않습니다.

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

희망이 도움이됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.