iphone - tutorial - La subvista UITableViewCell desaparece cuando se selecciona la celda
uitableview ios (19)
Estoy implementando una vista de tabla de selección de color en la que el usuario puede seleccionar entre, por ejemplo, 10 colores (depende del producto). El usuario también puede seleccionar otras opciones (como la capacidad del disco duro, ...).
Todas las opciones de color están dentro de su propia sección de vista de tabla.
Quiero mostrar un pequeño cuadrado a la izquierda de la etiqueta de texto que muestra el color real.
Ahora estoy agregando un UIView cuadrado simple, le doy el color de fondo correcto, así:
- (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;
}
Esto se muestra bien sin problemas.
Mi único problema es que cuando selecciono una fila de "color", durante la animación de selección de fundido a azul, mi UIView personalizada (colorThumb) está oculta. Se vuelve a visualizar justo después de que finalizó la animación de selección / cancelación, pero esto produce un artefacto feo.
¿Qué debo hacer para corregir esto? ¿No inserto la subvista en el lugar correcto?
(No hay nada especial en didSelectRowAtIndexPath, simplemente cambio el accesorio de la celda a una casilla de verificación o nada, y deselecciono el actual indexPath).
Agregando otra solución si está usando storyboards. Cree una subclase de UIView
que no permita establecer el backgroundColor
una vez que se haya configurado inicialmente.
@interface ConstBackgroundColorView : UIView
@end
@implementation ConstBackgroundColorView
- (void)setBackgroundColor:(UIColor *)backgroundColor {
if (nil == self.backgroundColor) {
[super setBackgroundColor:backgroundColor];
}
}
@end
Basado en la respuesta de Paul Gurov implementé lo siguiente en Xamarin.iOS. Versión 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()
{
}
}
Coloque este código en su subclase de UITableViewCell
Sintaxis de 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)
}
}
Dibuje la vista en lugar de establecer el color de fondo
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);
}
}
}
Encontré una solución bastante elegante en lugar de jugar con los métodos de selección / resaltado tableViewCell. Puede crear una subclase de UIView que ignore establecer su color de fondo para borrar el color.
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
}
}
}
}
Versión Obj-C:
@interface NeverClearView : UIView
@end
@implementation NeverClearView
- (void)setBackgroundColor:(UIColor *)backgroundColor {
if (CGColorGetAlpha(backgroundColor.CGColor) != 0) {
[super setBackgroundColor:backgroundColor];
}
}
@end
Es porque la celda de vista de tabla cambia automáticamente el color de fondo de todas las vistas dentro de la vista de contenido para el estado resaltado. Puede considerar subclasificar a UIView
para dibujar su color o usar UIImageView
con una imagen personalizada de 1x1 px.
Esto es similar a la respuesta de Pavel Gurov, pero es más flexible ya que permite que cualquier color sea permanente.
class PermanentBackgroundColorView: UIView {
var permanentBackgroundColor: UIColor? {
didSet {
backgroundColor = permanentBackgroundColor
}
}
override var backgroundColor: UIColor? {
didSet {
if backgroundColor != permanentBackgroundColor {
backgroundColor = permanentBackgroundColor
}
}
}
}
Inspirado por la de , creé una categoría / extensión UITableViewCell que le permite activar y desactivar esta "función" de transparencia.
Rápido
let cell = <Initialize Cell>
cell.keepSubviewBackground = true // Turn transparency "feature" off
cell.keepSubviewBackground = false // Leave transparency "feature" on
C objetivo
UITableViewCell* cell = <Initialize Cell>
cell.keepSubviewBackground = YES; // Turn transparency "feature" off
cell.keepSubviewBackground = NO; // Leave transparency "feature" on
KeepBackgroundCell es compatible con CocoaPods. Puedes encontrarlo en GitHub
Inspirado por la respuesta de Yatheesha BL .
Si llama a super.setSelected (seleccionado, animado: animado), borrará todo el color de fondo que configure . Por lo tanto, no llamaremos supermétodo.
En 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
}
}
No olvides anular setSelected
así como 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()
}
Otra forma de gestionar el problema es llenar la vista con un degradado de gráficos centrales, como:
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];
Para Swift 2.2 esto funciona
cell.selectionStyle = UITableViewCellSelectionStyle.None
y la razón es explicada por @ Andriy
Es porque la celda de vista de tabla cambia automáticamente el color de fondo de todas las vistas dentro de la vista de contenido para el estado resaltado.
Prueba el siguiente código:
-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
//Set your View''s Color here.
}
Puede cell.selectionStyle = UITableViewCellSelectionStyleNone;
, luego configure backgroundColor en - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
Quería mantener el comportamiento de selección predeterminado a excepción de una subvista de celda que quería ignorar el cambio automático de color de fondo. Pero también necesitaba poder cambiar el color de fondo en otros momentos.
La solución que se me ocurrió fue subclasificar a UIView
por lo que ignora el ajuste del color de fondo normalmente y agrega una función separada para eludir la protección.
Swift 4
class MyLockableColorView: UIView {
func backgroundColorOverride(_ color: UIColor?) {
super.backgroundColor = color
}
override var backgroundColor: UIColor? {
set {
return
}
get {
return super.backgroundColor
}
}
}
Si la solución de fondo mencionada anteriormente no está solucionando su problema, su problema puede estar en su fuente de datasource
para su tableView.
Para mí, estaba creando una instancia de un objeto DataSource (llamado BoxDataSource
) para manejar los métodos delegate y dataSource tableView, así:
//In cellForRowAtIndexPath, when setting up cell
let dataSource = BoxDataSource(delegate: self)
cell.tableView.dataSource = dataSource
return cell
Esto causaba que el dataSource fuera desasignado cada vez que se tocaba la celda y, por lo tanto, todos los contenidos desaparecían. La razón es, es ARC la deslocalización / recolección de basura naturaleza.
Para solucionar esto, tuve que ir a la celda personalizada, agregar una variable de origen de datos:
//CustomCell.swift
var dataSource: BoxDataSource?
Luego, debe configurar el dataSource en la fuente dataSource de la celda que acaba de crear en cellForRow, por lo que no se desasignará con ARC.
cell.statusDataSource = BoxAssigneeStatusDataSource(delegate: self)
cell.detailsTableView.dataSource = cell.statusDataSource
return cell
Espero que ayude.
UITableViewCell cambia el color de fondo de todas las subvistas en la selección por algún motivo.
Esto podría ayudar:
Use algo así para evitar que UITableView cambie el color de su vista durante la selección.
aquí está mi solución, use contentView para mostrar selectionColor, funciona perfectamente
#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;
}
}
UITableViewCell
cambia el color de fondo de todas las vistas secundarias cuando se selecciona o resalta la celda. Puede resolver este problema anulando el color de fondo de vista de la celda de setSelected:animated
y setHighlighted:animated
restablecido.
En el Objetivo 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;
}
}
En 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
}
}