2011-07-19 2 views
139

Tôi đang triển khai chế độ xem bảng chọn màu, trong đó người dùng có thể chọn trong số 10 màu (phụ thuộc vào sản phẩm). Người dùng cũng có thể chọn các tùy chọn khác (như dung lượng ổ cứng, ...).Chế độ xem phụ UITableViewCell biến mất khi ô được chọn

Tất cả các tùy chọn màu đều nằm trong phần xem bảng của riêng họ.

Tôi muốn hiển thị một hình vuông nhỏ ở bên trái của dòng văn bảnNhãn hiển thị màu thực tế.

Ngay bây giờ tôi thêm một UIView vuông đơn giản, cung cấp cho nó màu nền đúng, như thế này:

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

này hiển thị tốt mà không có vấn đề.

Vấn đề duy nhất của tôi là khi tôi chọn hàng "màu", trong hoạt ảnh chọn màu mờ dần, tùy chỉnh UIView (colorThumb) của tôi bị ẩn. Nó được hiển thị một lần nữa ngay sau khi hoạt ảnh lựa chọn/bỏ chọn kết thúc, nhưng điều này tạo ra một tạo tác xấu xí.

Tôi nên làm gì để sửa lỗi này? Tôi không chèn subview vào đúng nơi?

(Không có gì đặc biệt trong didSelectRowAtIndexPath, tôi chỉ thay đổi phụ kiện của ô thành hộp kiểm hoặc không có gì và bỏ chọn chỉ mục hiện tại).

+0

upadteCell là gì tất cả về? – Idan

+0

updateCell thực hiện một số chỉnh sửa nhỏ như thiết lập dấu kiểm hoặc không, chọn màu văn bản tùy thuộc vào tính khả dụng, ... nhưng không có thay đổi thực sự liên quan đến chính ô đó hoặc colorThumb. – Cyrille

+0

câu trả lời được chấp nhận không cung cấp giải pháp, xem câu trả lời của tôi dưới đây cho giải pháp –

Trả lời

162

UITableViewCell thay đổi màu nền của tất cả các chế độ xem phụ khi ô được chọn hoặc được đánh dấu, bạn có thể giải quyết vấn đề này bằng cách ghi đè số setSelected:animatedsetHighlighted:animated của ô xem bảng và đặt lại màu nền xem.

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

Trong 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 
    } 
} 
+1

Đây phải là câu trả lời. –

+0

Chúng ta có cần điều kiện 'if (được đánh dấu)' và 'if (đã chọn)' không? Tôi nghĩ rằng nó sẽ làm việc nếu chúng ta không có những điều kiện đó. –

+0

@Cyrille rly này nên được chấp nhận là giải pháp tốt nhất. – arts777

120

Đó là vì ô xem bảng tự động thay đổi màu nền của tất cả các chế độ xem bên trong chế độ xem nội dung cho trạng thái được đánh dấu. Bạn có thể xem xét phân lớp UIView để vẽ màu hoặc sử dụng UIImageView với hình ảnh kéo dài 1x1 px tùy chỉnh.

+1

Câm tôi. Tất nhiên đó là nó, các cuộc phỏng vấn phải minh bạch để các hoạt hình lựa chọn có thể xảy ra đúng cách. Cảm ơn! – Cyrille

+49

Hoặc bạn có thể đặt lại màu nền ghi đè 'setHighlighted: animated:' và 'setSelected: animated:' – pt2ph8

+0

Cảm ơn các bạn, tôi đã gặp phải vấn đề tương tự và điều đó thực sự hữu ích. – ratsimihah

9

Một cách khác để quản lý vấn đề là để điền vào quan điểm với độ dốc lõi đồ họa, như:

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

+1 bởi vì đó là những gì tôi đã làm gần đây. – Cyrille

+0

Hmm, tôi đang thử mã chính xác này và nó không có hiệu ứng gì cả. Subview của tôi là một UILabel được thêm vào như là một subview của cell.contentView, và thử nghiệm theo iOS 6.0.1, trong trường hợp có vấn đề. –

+0

Bạn áp dụng mã ở trên để làm gì? Và bạn đã cố gắng thêm nhãn đơn giản vào chế độ xem ô? – Agat

3

UITableViewCell thay đổi backgroundColor của tất cả các subviews về lựa chọn đối với một số lý do.

này có thể giúp:

DVColorLockView

Sử dụng một cái gì đó như thế để ngăn chặn UITableView từ việc thay đổi màu sắc nhìn của bạn trong lựa chọn.

0

đây là giải pháp của tôi, sử dụng contentView để hiển thị selectionColor, nó làm việc một cách hoàn hảo

#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; 
    } 
} 
3

Lấy cảm hứng từ Yatheesha B L 's answer Tôi tạo ra một thể loại UITableViewCell/extension cho phép bạn để bật và tắt tính năng "minh bạch" này.

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 là CocoaPods tương thích. Bạn có thể tìm thấy nó on GitHub

+0

làm việc cho tôi lưu loát! –

6

Bạn có thể cell.selectionStyle = UITableViewCellSelectionStyleNone;, sau đó đặt backgroundColor tại - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath

22

Tìm thấy một giải pháp khá thanh lịch thay vì can thiệp vào lựa chọn tableViewCell/làm nổi bật phương pháp. Bạn có thể tạo một lớp con của UIView bỏ qua thiết lập màu nền của nó để xóa màu.

Swift 3/4:

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

Swift 2:

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

obj-C phiên bản:

@interface NeverClearView : UIView 

@end 

@implementation NeverClearView 

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

@end 
+0

Điều này thật đáng yêu. Dễ dàng là giải pháp tốt nhất nếu bạn có một số chế độ xem có thể sử dụng lại như "huy hiệu" hoặc "thẻ" chỉ nên không bao giờ có nền tảng rõ ràng. :: rant :: một giải pháp gây nhầm lẫn @UIKit, thiết lập tất cả các chế độ xem con thành minh bạch khi bạn thực hiện lựa chọn ô. Ít nhất giới hạn đối với các chế độ xem con có chiều cao hoặc chiều rộng đầy đủ của ô hoặc ở độ sâu N. – SimplGy

+0

@SimplGy Độ sâu của đánh dấu sẽ thực sự là một lựa chọn ngọt ngào, nhưng hey - đây là UIKit, tôi đã nhìn thấy những thứ SO tồi tệ hơn nhiều hơn này =) –

+3

Làm việc cho tôi sau khi tôi thay đổi nếu để CGColorGetAlpha (backgroundColor! .CGColor) = = 0 vì nó không bằng clearColor – piltdownman7

1

Vẽ màn hình thay vì thiết lập màu nền

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

     } 
    } 


} 
6

Đối Swift 2.2 làm việc này

cell.selectionStyle = UITableViewCellSelectionStyle.None 

và lý do được giải thích bởi @Andriy

Đó là bởi vì xem bảng tế bào tự động thay đổi màu nền của tất cả các quan điểm bên trong xem nội dung cho nhà nước nhấn mạnh.

+1

Ngắn và đơn giản, hoạt động như một sự quyến rũ. Cảm ơn :) –

+1

làm việc dễ dàng và hoàn hảo –

0

Thử Sau mã:

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

Dựa trên câu trả lời Paul Gurov của tôi thực hiện những điều sau đây trong Xamarin.iOS. C# phiên bản:

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

Đừng quên ghi đè setSelected cũng như 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

Nơi mã này trong lớp con lại UITableViewCell

Swift 3 cú pháp

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

T tương tự như câu trả lời của Pavel Gurov, nhưng linh hoạt hơn ở chỗ nó cho phép bất kỳ màu nào là vĩnh viễn.

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

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

Thêm giải pháp khác nếu bạn đang sử dụng bảng phân cảnh. Tạo một lớp con của UIView không cho phép backgroundColor được đặt sau khi thiết lập ban đầu.

@interface ConstBackgroundColorView : UIView 

@end 

@implementation ConstBackgroundColorView 

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

@end 
0

Nếu giải pháp nền được đề cập ở trên không khắc phục được sự cố của bạn, sự cố của bạn có thể nằm trong số datasource cho tableView của bạn.

Đối với tôi, tôi đã tạo ra một thể hiện của một đối tượng DataSource (gọi tắt là BoxDataSource) để xử lý các đại biểu và các phương pháp dataSource tableView, như vậy:

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

này đã gây ra dataSource được deallocated bất cứ khi nào các tế bào đã được khai thác, và do đó tất cả các nội dung biến mất. Lý do là, là ARC deallocating/rác thu thập bản chất.

Để khắc phục điều này, tôi đã phải đi vào tế bào tùy chỉnh, thêm một biến nguồn dữ liệu:

//CustomCell.swift 
var dataSource: BoxDataSource? 

Sau đó, bạn cần phải thiết lập các nguồn dữ liệu để dataSource của tế bào var bạn vừa tạo trong cellForRow, vì vậy đây isnt deallocated với ARC.

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

Hy vọng điều đó sẽ hữu ích.

2

Lấy cảm hứng từ câu trả lời của Yatheesha B L.

Nếu bạn gọi super.setSelected (đã chọn, hoạt ảnh: hoạt ảnh), , nó sẽ xóa tất cả màu nền bạn đặt. Vì vậy, chúng tôi sẽ không gọi phương thức siêu.

Trong 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 
    } 
} 
+0

Cảm ơn bạn đã giải pháp. +1 Ghi đè biến ishiglighted và phương pháp sethighlighted là những thứ khác nhau. câu trả lời đúng là ghi đè phương thức. –

0

Tôi muốn giữ các hành vi lựa chọn mặc định ngoại trừ một subview tế bào mà tôi muốn bỏ qua các thay đổi màu nền tự động. Nhưng tôi cũng cần thiết để có thể thay đổi màu nền vào những lúc khác.

Giải pháp mà tôi đưa ra là phân lớp UIView để nó bỏ qua việc đặt màu nền bình thường và thêm chức năng riêng biệt để bỏ qua bảo vệ.

Swift 4

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

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