ユーザーが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を選択解除します)。
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
}
}
これは、テーブルビューセルが、強調表示された状態のコンテンツビュー内のすべてのビューの背景色を自動的に変更するためです。 UIView
をサブクラス化して色を描画するか、UIImageView
を使用してカスタム1x1ピクセルのストレッチ画像を使用することを検討できます。
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
問題を管理する別の方法は、次のようなコアグラフィックスグラデーションでビューを塗りつぶすことです。
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];
Swift 2.2の場合、これは機能します
cell.selectionStyle = UITableViewCellSelectionStyle.None
そして、理由は@ Andriy で説明されています
これは、テーブルビューセルが、強調表示された状態のコンテンツビュー内のすべてのビューの背景色を自動的に変更するためです。
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で
cell.selectionStyle = UITableViewCellSelectionStyleNone;
してから、- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
でbackgroundColorを設定できます
場合によっては、これはセル内のすべてのアイテムの灰色を取得しないようにするセプツです(カスタムテーブルビューセルを使用している場合):
SelectionStyleを.noneに設定します???? selectionStyle = .none
このメソッドをオーバーライドします。
func setHighlighted(_強調表示:Bool、アニメーション:Bool)
スーパーを呼び出して、スーパーセットアップの利点を取得します。
super.setHighlighted(強調表示、アニメーション:アニメーション)
必要なロジックを強調表示します。
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
// Your Highlighting Logic goes here...
}
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
}
}
UITableViewCellは、何らかの理由で選択時にすべてのサブビューのbackgroundColorを変更します。
これは役立つかもしれません:
そのようなものを使用して、選択中にUITableViewがビューの色を変更しないようにします。
背景色を設定する代わりにビューを描画します
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);
}
}
}
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()
}
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()
{
}
}
自動背景色の変更を無視したい1つのセルサブビューを除き、デフォルトの選択動作を維持したかった。しかし、他のときに背景色を変更できるようにする必要もありました。
私が思いついた解決策はUIView
をサブクラス化することで、通常は背景色の設定を無視し、別の機能を追加して保護をバイパスしました。
Swift 4
class MyLockableColorView: UIView {
func backgroundColorOverride(_ color: UIColor?) {
super.backgroundColor = color
}
override var backgroundColor: UIColor? {
set {
return
}
get {
return super.backgroundColor
}
}
}
SIMPLESTアニメーションにバグがなく(最高評価の回答のように)、サブクラス化と描画なしのソリューション-backgroundColorの代わりにレイヤーの境界線の色を設定し、非常に大きな境界線の幅を設定します。
colorThumb.layer.cornerRadius = 6
colorThumb.layer.borderWidth = colorThumb.frame.width
colorThumb.layer.borderColor = value.color
このコードを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)
}
}
ここに私のソリューションがあり、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;
}
}
次のコードを試してください:
-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
//Set your View's Color here.
}
ストーリーボードを使用している場合は、別のソリューションを追加します。 UIView
のサブクラスを作成します。このサブクラスは、backgroundColor
を最初に設定した後に設定することを許可しません。
@interface ConstBackgroundColorView : UIView
@end
@implementation ConstBackgroundColorView
- (void)setBackgroundColor:(UIColor *)backgroundColor {
if (nil == self.backgroundColor) {
[super setBackgroundColor:backgroundColor];
}
}
@end
上記のバックグラウンドソリューションで問題が解決しない場合、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
お役に立てば幸いです。
これはPavel Gurovの答えに似ていますが、任意の色を永続的にすることができるという点でより柔軟です。
class PermanentBackgroundColorView: UIView {
var permanentBackgroundColor: UIColor? {
didSet {
backgroundColor = permanentBackgroundColor
}
}
override var backgroundColor: UIColor? {
didSet {
if backgroundColor != permanentBackgroundColor {
backgroundColor = permanentBackgroundColor
}
}
}
}