Ich habe einen einfachen tableViewCell-Build-Interface-Builder ..__, der eine UIView enthält, die ein Bild enthält ..__ Wenn ich nun die Zelle auswähle, wird der Standardhintergrund für die blaue Auswahl angezeigt, aber die Hintergrundfarbe meiner UIView ist weg.
Die UITableViewCell-Implementierungsdatei hat keine besonderen Auswirkungen. Es ist nur init's und kehrt selbst zurück und alles, was ich in setSelected mache, ist call super.
Wie kann ich meine UIView backgroundColor anzeigen lassen, wenn die tableView ausgewählt ist?
Das Problem hier ist, dass die 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 (was durch die Tatsache belegt wird, dass die Eigenschaften der Ansichtenebenen der Ansichtsebene geändert werden.)
Hier ist die Reihenfolge der Funktionsaufrufe, die sich aus dem Berühren einer Zelle ergibt
Also haben Sie die Wahl zu
Leider macht das erneute Durchsetzen 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: Gib eine großartige Beschreibung, wie setSelected überschrieben werden soll.
- (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;
}
Früher habe ich wie @ P5ycH0 gesagt (1x1 Bild gestreckt), aber nach @Brooks habe ich mir gedacht, dass das Überschreiben von -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
in meiner benutzerdefinierten UITableViewCell
-Implementierung und das Zurücksetzen der Hintergrundfarben nach dem Aufruf von [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;
}
Wenn Ihre UITableViewCell
ausgewählt ist, gibt es zwei Zustände, auf die Sie achten sollten: Highlighted
und Selected
.
In Szenarien, in denen Sie über eine benutzerdefinierte Zellklasse verfügen, die Unterklasse von UITableViewCell
ist, 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
}
}
Brooks hat eine großartige Erklärung dafür, warum dies passiert, aber ich denke, ich habe eine bessere Lösung.
Überschreiben Sie in Ihrer Unteransicht setBackgroundColor:
mit der gewünschten Farbe. Der Setter wird weiterhin aufgerufen, aber nur Ihre angegebene Farbe wird erzwungen.
- (void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:[UIColor whiteColor]];
}
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 oder entsprechenden Methoden aufrufen.UITableViewCellSelectionStyleNone
selectionStyle für Ihre benutzerdefinierte Zelle festlegen, um das standardmäßige 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();
}
Die Variable contentView
ist die Eigenschaft von UITableViewCell
, die in iOS 7 angezeigt wird. Beachten Sie, dass Sie stattdessen die untergeordnete Ansicht oder die eigene Ansicht Ihrer eigenen Zelle verwenden können.
Dieses Problem kann (endlich) in iOS 13 behoben werden. Fand diesen süßen Absatz in den Versionshinweisen zu iOS 13 Beta 3.
Die UITableViewCell-Klasse ändert nicht mehr die backgroundColor- oder isOpaque-Eigenschaften der contentView und ihrer Unteransichten, wenn Zellen hervorgehoben oder ausgewählt werden. Wenn Sie eine undurchsichtige Hintergrundfarbe für Unteransichten der Zelle innerhalb (und einschließlich) der Inhaltsansicht festlegen, wirkt sich dies möglicherweise auf das Erscheinungsbild aus, wenn die Zelle hervorgehoben oder ausgewählt wird. Die einfachste Möglichkeit, Probleme mit Ihren Unteransichten zu beheben, besteht darin, sicherzustellen, dass die backgroundColor-Eigenschaft auf null oder klar und die undurchsichtige Eigenschaft auf falsch gesetzt ist. Bei Bedarf können Sie jedoch die Methoden setHighlighted (: animated :) und setSelected (: animated :) überschreiben, um diese Eigenschaften in Ihren Unteransichten beim Verschieben manuell zu ändern zu oder von den markierten und ausgewählten Zuständen. (13955336)
Ok, die Hintergrundfarbe einer UIView-Klasse zu verlieren ist ein normales Verhalten, wenn sie in einer ausgewählten tableviewcell ..__ ist 1x1 weißes Pixel gestreckt . Hässlich imo, aber es funktioniert.
In Verbindung mit der Antwort von @ Brooks habe ich dies in Swift und iOS8/iOS9 funktionieren lassen.
setSelected
und setHighlighted
.contentView.backgroundColor
, da er sich nicht über die gesamte Breite der Zelle (d. H. Zubehör) erstrecken muss.Verwenden Sie backgroundColor
der Zelle selbst und stellen Sie es 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()
}
}
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()
})
}
}
Zusammenfassung
Diese Lösung lässt Sie sperren Sie einige Hintergrundfarben einer Zelle, während der Rest durch das Systemverhalten gesteuert wird.
Basierend auf mientus ' answer habe ich eine Lösung erstellt, mit der Sie angeben, welche Ansichten ihre Hintergrundfarbe beibehalten sollen.
Auf diese Weise können andere Unteransichten der Zelle beim Hervorheben/Auswählen entfernt werden. Dies ist die einzige Lösung, die in unserem Fall funktioniert (zwei Ansichten, die einen permanenten Hintergrund benötigen).
Ich habe einen protokollorientierten Ansatz verwendet, mit einem BackgroundLockable
-Protokoll, das die Liste der Ansichten enthält, die gesperrt werden sollen, und ein Schließen 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 die Auswahl überschreibt, um die Schließung des Protokolls auszuführen, um das Standardverhalten (super) 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
subclassieren oder das BackgroundLockable
-Protokoll in einer Zellklasse verwenden, um einigen Zellen das Sperrverhalten leicht 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]
}
}
Ich habe gerade etwas Zeit mit diesem seltsamen Thema verbracht. Ich wollte den UITableViewCellSelectionStyleNone-Stil nicht festlegen, um die Nice-Animation beizubehalten, wenn meine Zeile ausgewählt wurde. Aber keine der vorgeschlagenen Ideen hat sich für mich bewährt - ich habe versucht, setSelected und setHighlighted zu überschreiben und meine Hintergrundfarbe backgroundColor dort zu setzen - es wurde immer wieder von iOS zurückgesetzt und blinzelte immer noch (neue Farbe -> alte Farbe) recht einfach ... Wenn meine Zeile ausgewählt ist, wird ein anderer View-Controller gedrückt, der Benutzer wählt eine Option auf diesem Bildschirm aus, und der Delegat wird aufgerufen, wobei ich die Farbe aufgrund der Benutzerauswahl ändere. In diesem Delegierten mache ich einfach [cell setSelected: NO animated: NO] für meine Zelle. (Ich habe einen statischen UITableViewController und habe Auslässe zu Zellen.) . Sie könnten die Zelle in der didSelect-Methode wahrscheinlich abwählen, aber in meinem Fall verwende ich Segues.
Hier ist meine Meinung dazu. Ich habe eine Unterklasse, von der alle meine Zellen erben. Auf diese Weise vermeide ich die Hintergrundänderung in meinen UIImageViews:
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]
}
}
}
Dies behebt das Problem automatisch für alle UIImageView
.
In iOS 7 funktionierte es für mich, setSelected:animated:
in der UITableViewCell
-Unterklasse zu überschreiben, aber im Gegensatz zu @Brooks 'Tipp rief ich [super setSelected:selected animated:animated]
an.
- (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];
}
Dadurch kann ich die Standardauswahlanimation des Systems beibehalten, wenn der Benutzer auf die Zelle tippt, und die Auswahl in der Tabelle didSelectRowAtIndexPath:
des Delegierten der Tabellenansicht aufheben.
Sie können das Verhalten von tableViewCell ändern, indem Sie die Funktion setHighlighted in der UITableViewCell-Klasse ü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 auf grau, blau oder keinen ändern.
Da Sie sagten, Sie hätten eine tableViewCell mit IB erstellt, möchte ich prüfen, ob Sie Ihre Ansicht als Unteransicht von contentView
von UITableViewCell hinzufügen, nicht als view
. Die Inhaltsansicht ist die Standardübersicht für den von der Zelle angezeigten Inhalt.
Aus der Referenz:
Die Inhaltsansicht eines UITableViewCell-Objekts ist der Standardüberblick für den von der Zelle angezeigten Inhalt. Wenn Sie Zellen anpassen möchten, indem Sie einfach zusätzliche Ansichten hinzufügen, sollten Sie sie zur Inhaltsansicht hinzufügen, damit sie beim Übergang der Zelle in den Bearbeitungsmodus bzw. aus dem Bearbeitungsmodus entsprechend positioniert werden.
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
}