Ich habe einen einfachen tableViewCell Build in Interface Builder. Es enthält eine UIView, die ein Bild enthält. Wenn ich nun die Zelle auswähle, wird der standardmäßige blaue Auswahlhintergrund angezeigt, aber die Hintergrundfarbe meiner UIView ist nicht mehr vorhanden.
Die Implementierungsdatei von UITableViewCell macht nichts Besonderes. Es ist nur init's & gibt sich selbst zurück und alles was ich in setSelected mache ist call super.
Wie kann ich meine UIView backgroundColor anzeigen lassen, wenn tableView ausgewählt ist?
ios
uitableview
uiview
interface-builder
Tycho Pandelaar
quelle
quelle
Antworten:
Das Problem hierbei ist, dass die [super] Implementierung von
- (void) setSelected:(BOOL) selected animated:(BOOL) animated;
Setzt alle Hintergrundfarben in der UITableViewCell auf rgba (0,0,0,0). Warum? Vielleicht, um uns alle ins Schwitzen zu bringen?
Es ist nicht so, dass ganze Ansichten verschwinden (wie durch die Tatsache belegt wird, dass diese beibehalten werden, wenn Sie die Rahmeneigenschaften der Ansichtsebene beibehalten).
Hier ist die Reihenfolge der Funktionsaufrufe, die sich aus dem Berühren einer Zelle ergibt
Sie haben also die Wahl
Leider bewirkt das erneute Aktivieren der Hintergrundfarben in setHighlighted nichts, da setHighlighted aufgerufen wird, bevor alle Hintergrundfarben beim ersten Aufruf von setSelected auf [r: 0 b: 0 g: 0 a: 0] gesetzt werden.
// TODO: Geben Sie eine gute Beschreibung, wie setSelected überschrieben werden kann (bleiben Sie dran)
quelle
selectionStyle
zuUITableViewCellSelectionStyleNone
, und es wird nicht Hintergründe löschen. Der einzige Nachteil ist, dass dieselectedBackgroundView
Eigenschaft ignoriert wird .- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { UIColor *backgroundColor = self.channelImageView.backgroundColor; [super setHighlighted:highlighted animated:animated]; self.channelImageView.backgroundColor = backgroundColor; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { UIColor *backgroundColor = self.channelImageView.backgroundColor; [super setSelected:selected animated:animated]; self.channelImageView.backgroundColor = backgroundColor; }
quelle
Wenn Sie
UITableViewCell
ausgewählt sind, sollten Sie auf zwei Zustände achten:Highlighted
undSelected
.In Szenarien, in denen Sie eine benutzerdefinierte Zellklasse haben, zu der eine Unterklasse gehört
UITableViewCell
, können Sie diese beiden Methoden leicht überschreiben, um diese Situation zu vermeiden (Swift):class MyCell: UITableViewCell { @IBOutlet var myView: UIView! override func setHighlighted(highlighted: Bool, animated: Bool) { let myViewBackgroundColor = myView.backgroundColor super.setHighlighted(highlighted, animated: animated) myView.backgroundColor = myViewBackgroundColor } override func setSelected(selected: Bool, animated: Bool) { let myViewBackgroundColor = myView.backgroundColor super.setSelected(selected, animated: animated) myView.backgroundColor = myViewBackgroundColor } }
quelle
Früher habe ich getan, wie @ P5ycH0 sagte (1x1 Bild gestreckt), aber nach @Brooks stellte ich fest, dass das Überschreiben
-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
in meiner benutzerdefiniertenUITableViewCell
Implementierung und das Zurücksetzen der Hintergrundfarben nach dem Aufruf[super setHighlighted:highlighted animated:animated];
meine Hintergrundfarben beibehält, wenn die Zelle ausgewählt / hervorgehoben wird-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; myView.backgroundColor = myColor; }
quelle
setHighlighted
Funktion wurde erstellt, um benutzerdefiniertes Verhalten hinzuzufügen, wenn Zelle ausgewählt wird, übrigens gute ArbeitDieses Problem kann (endlich) in iOS 13 behoben werden. Dieser süße Absatz wurde in den Versionshinweisen zu iOS 13 Beta 3 gefunden.
https://developer.apple.com/documentation/ios_ipados_release_notes/ios_ipados_13_beta_3_release_notes
quelle
selectedBackgroundView
obsolet :( weil es verborgen bleiben könnteBrooks hat eine gute Erklärung dafür, warum dies passiert, aber ich denke, ich habe eine bessere Lösung.
Überschreiben
setBackgroundColor:
Sie in Ihrer Unteransicht die gewünschte Farbe. Der Setter wird weiterhin aufgerufen, aber nur die angegebene Farbe wird erzwungen.- (void)setBackgroundColor:(UIColor *)backgroundColor { [super setBackgroundColor:[UIColor whiteColor]]; }
quelle
Ok, das Verlieren der Hintergrundfarbe einer UIView-Klasse ist normal, wenn sie sich in einer ausgewählten Tabellenansichtszelle befindet. Ich konnte nicht herausfinden, wie ich das verhindern konnte. Jetzt habe ich gerade das UIView durch ein UIImageView ersetzt, das ein gestrecktes 1x1 weißes Pixel enthält. Hässlich imo, aber es funktioniert.
quelle
Sie müssen die nächsten beiden Methoden in Ihrer benutzerdefinierten Zelle überschreiben:
- (void) setSelected:(BOOL)selected animated:(BOOL)animated; - (void) setHighlighted:(BOOL)highlighted animated:(BOOL)animated;
Beachten Sie, dass:
[super setSelected:animated:]
und[super setHighlighted:animated:]
zu Beginn Ihrer benutzerdefinierten Implementierung Methoden oder entsprechende Methoden aufrufen .UITableViewCellSelectionStyleNone
Auswahlstil für Ihre benutzerdefinierte Zelle festlegen , um das Standard-UITableViewCell
Styling zu deaktivieren .Hier das Beispiel der Implementierung:
- (void) setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; [self setHighlightedSelected:highlighted animated:animated]; } - (void) setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; [self setHighlightedSelected:selected animated:animated]; } - (void) setHighlightedSelected:(BOOL)selected animated:(BOOL)animated { void(^selection_block)(void) = ^ { self.contentView.backgroundColor = selected ? SELECTED_BACKGROUND_COLOR : NORMAL_BACKGROUND_COLOR; }; if(animated) { [UIView animateWithDuration:SELECTION_ANIMATION_DURATION delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:selection_block completion:NULL]; } else selection_block(); }
Dies
contentView
ist die EigenschaftUITableViewCell
, die in iOS 7 angezeigt wird. Beachten Sie, dass Sie stattdessen die untergeordnete Ansicht oder die Ansichten Ihrer eigenen Zelle verwenden können.quelle
Fügen Sie dies Ihrer UITableViewCell hinzu
override func setHighlighted(highlighted: Bool, animated: Bool) { super.setHighlighted(false, animated: animated) if highlighted { self.backgroundColor = UIColor.blueColor() }else{ UIView.animateWithDuration(0.2, animations: { self.backgroundColor = UIColor.clearColor() }) } }
quelle
Im Zusammenhang mit der Antwort von @ Brooks habe ich Folgendes getan, damit es in Swift und iOS8 / iOS9 funktioniert.
setSelected
undsetHighlighted
contentView.backgroundColor
, da es sich nicht über die gesamte Breite der Zelle erstrecken muss (dh Zubehör).Verwenden Sie die
backgroundColor
der Zelle selbst und stellen Sie sie entsprechend ein.class AwesomeTableViewCell: UITableViewCell { private struct Constants { static var highlightedColor = UIColor.greenColor() static var selectedColor = UIColor.redColor() static let animationTime = NSTimeInterval(0.2) } override func awakeFromNib() { super.awakeFromNib() contentView.backgroundColor = UIColor.clearColor() backgroundColor = AppContext.sharedInstance.theme.colors.background } override func setHighlighted(highlighted: Bool, animated: Bool) { if animated { UIView.animateWithDuration(Constants.animationTime, animations: { () -> Void in self.setHighlighted(highlighted) }) } else { self.setHighlighted(highlighted) } } override func setSelected(selected: Bool, animated: Bool) { if animated { UIView.animateWithDuration(Constants.animationTime, animations: { () -> Void in self.setSelected(selected) }) } else { self.setSelected(selected) } } private func setHighlighted(highlighted: Bool) { backgroundColor = highlighted ? Constants.highlightedColor : UIColor.whiteColor() } private func setSelected(selected: Bool) { backgroundColor = selected ? Constants.selectedColor : UIColor.whiteColor() } }
quelle
Zusammenfassung
Mit dieser Lösung können Sie einige Hintergrundfarben einer Zelle sperren , während der Rest vom Systemverhalten gesteuert wird.
Basierend auf der Antwort von mientus habe ich eine Lösung erstellt, mit der Sie festlegen können, welche Ansichten ihre Hintergrundfarbe behalten sollen .
Dies ermöglicht weiterhin, dass der Hintergrund anderer Zellen-Unteransichten beim Hervorheben / Auswählen entfernt wird, und ist die einzige Lösung, die in unserem Fall funktioniert (zwei Ansichten benötigen einen permanenten Hintergrund).
Ich habe einen protokollorientierten Ansatz verwendet, bei dem ein
BackgroundLockable
Protokoll die Liste der zu sperrenden Ansichten enthält und ein Abschluss ausgeführt wird, während die Farben beibehalten werden:protocol BackgroundLockable { var lockedBackgroundViews: [UIView] { get } func performActionWithLockedViews(_ action: @escaping () -> Void) } extension BackgroundLockable { func performActionWithLockedViews(_ action: @escaping () -> Void) { let lockedViewToColorMap = lockedBackgroundViews.reduce([:]) { (partialResult, view) -> [UIView: UIColor?] in var mutableResult = partialResult mutableResult[view] = view.backgroundColor return mutableResult } action() lockedViewToColorMap.forEach { (view: UIView, color: UIColor?) in view.backgroundColor = color } } }
Dann habe ich eine Unterklasse von
UITableViewCell
, die das Hervorheben und Auswählen überschreibt, um den Abschluss des Protokolls auszuführen, um das Standardverhalten (Superverhalten) aufzurufen:class LockableBackgroundTableViewCell: UITableViewCell, BackgroundLockable { var lockedBackgroundViews: [UIView] { return [] } override func setHighlighted(_ highlighted: Bool, animated: Bool) { performActionWithLockedViews { super.setHighlighted(highlighted, animated: animated) } } override func setSelected(_ selected: Bool, animated: Bool) { performActionWithLockedViews { super.setSelected(selected, animated: animated) } } }
Jetzt muss ich nur noch
LockableBackgroundTableViewCell
dasBackgroundLockable
Protokoll in einer Zellklasse unterordnen oder verwenden, um einigen Zellen auf einfache Weise ein Sperrverhalten hinzuzufügen!class SomeCell: LockableBackgroundTableViewCell { @IBOutlet weak var label: UILabel! @IBOutlet weak var icon: UIImageView! @IBOutlet weak var button: UIButton! override var lockedBackgroundViews: [UIView] { return [label, icon] } }
quelle
Swift 4
In Ihrer UITableViewCell- Klasse:
override func setSelected(_ selected: Bool, animated: Bool) { myView.backgroundColor = UIColor.blue } override func setHighlighted(_ highlighted: Bool, animated: Bool) { myView.backgroundColor = UIColor.blue }
quelle
Nachdem Sie gesagt haben, dass Sie eine tableViewCell mit IB erstellt haben, möchte ich überprüfen, ob Sie Ihre Ansicht als Unteransicht
contentView
von UITableViewCell hinzufügen, nichtview
. Die Inhaltsansicht ist die Standardübersicht für Inhalte, die von der Zelle angezeigt werden.Aus der Referenz:
quelle
Sie können das Verhalten von tableViewCell ändern, indem Sie die in der UITableViewCell-Klasse festgelegte Funktion setHighlighted überschreiben (Sie müssen davon erben). Beispiel für meinen Code, bei dem ich das Hintergrundbild meiner Zelle ändere:
// animate between regular and highlighted state - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated; { [super setHighlighted:highlighted animated:animated]; //Set the correct background Image UIImageView* backgroundPicture = (UIImageView*)[self viewWithTag:HACK_BACKGROUND_VIEW_TAG]; if (highlighted) { backgroundPicture.image = [UIImage imageNamed:@"FondSelected.png"]; } else { backgroundPicture.image = [UIImage imageNamed:@"Fond.png"]; } }
Sie können den Auswahlmodus im Interface Builder auch in Grau, Blau oder Keine ändern.
quelle
In iOS 7 hat es für mich funktioniert,
setSelected:animated:
dieUITableViewCell
Unterklasse zu überschreiben , aber entgegen dem Tipp von @Brooks habe ich angerufen[super setSelected:selected animated:animated]
.- (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Reassert the background color of the color view so that it shows // even when the cell is highlighted for selection. self.colorView.backgroundColor = [UIColor blueColor]; }
Auf diese Weise kann ich die Standardauswahlanimation des Systems beibehalten, wenn der Benutzer auf die Zelle tippt, und sie auch in den Delegierten der Tabellenansicht abwählen
didSelectRowAtIndexPath:
.quelle
Ich habe gerade einige Zeit mit diesem seltsamen Thema verbracht. Ich wollte den UITableViewCellSelectionStyleNone-Stil nicht festlegen, um eine schöne Animation zu erhalten, wenn meine Zeile ausgewählt wurde. Aber keine der vorgeschlagenen Ideen hat bei mir funktioniert - ich habe versucht, setSelected und setHighlighted zu überschreiben und dort meine Unteransicht backgroundColor festzulegen - sie wurde von iOS immer wieder zurückgesetzt und blinkte immer noch (neue Farbe -> alte Farbe). Für mich war die Lösung ganz einfach. Wenn meine Zeile ausgewählt ist, wird ein anderer Ansichts-Controller gedrückt. Der Benutzer wählt eine Option auf diesem Bildschirm aus und der Delegat wird aufgerufen, wobei ich die Farbe basierend auf der Benutzerauswahl ändere. In diesem Delegaten mache ich einfach [cell setSelected: NO animiert: NO] für meine Zelle. (Ich habe statischen UITableViewController und habe Ausgänge zu Zellen). Sie könnten wahrscheinlich die Auswahl der Zelle in der didSelect-Methode aufheben, aber in meinem Fall verwende ich Segues.
quelle
Hier ist meine Meinung dazu. Ich habe eine Unterklasse, von der alle meine Zellen erben. So mache ich das, um die Hintergrundänderung in meinen UIImageViews zu vermeiden:
override func setHighlighted(highlighted: Bool, animated: Bool) { var backgroundColors = [UIView: UIColor]() for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { backgroundColors[imageView] = imageView.backgroundColor } } super.setHighlighted(highlighted, animated: animated) for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { imageView.backgroundColor = backgroundColors[imageView] } } } override func setSelected(selected: Bool, animated: Bool) { var backgroundColors = [UIView: UIColor]() for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { backgroundColors[imageView] = imageView.backgroundColor } } super.setSelected(selected, animated: animated) for view in contentView.subviews as [UIView] { if let imageView = view as? UIImageView { imageView.backgroundColor = backgroundColors[imageView] } } }
Dadurch wird das Problem automatisch für alle behoben
UIImageView
.quelle