Подвижность UITableViewCell исчезает при выборе ячейки
Я реализую представление таблицы color-chooser, где пользователь может выбрать, например, 10 цветов (в зависимости от продукта). Пользователь также может выбрать другие параметры (например, емкость жесткого диска,...).
Все цветовые параметры находятся внутри собственного раздела таблицы.
Я хочу показать небольшой квадрат слева от 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;
}
Это нормально отображается без проблем.
Моя единственная проблема заключается в том, что, когда я выбираю строку "color", во время анимации выделения fade-to-blue мой пользовательский UIView (colorThumb) скрыт. Он становится видимым снова сразу после окончания анимации выбора/отмены, но это вызывает уродливый артефакт.
Что мне делать, чтобы исправить это? Не вставлять ли подпункт в нужное место?
(Нет ничего особенного в didSelectRowAtIndexPath, я просто меняю принадлежность ячейки на флажок или ничего и отменяю выделение текущего indexPath).
Ответы
Ответ 1
UITableViewCell
меняет цвет фона всех подвыборов, когда ячейка выбрана или выделена, вы можете решить эту проблему, переопределив элемент 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
}
}
Ответ 2
Это потому, что ячейка просмотра таблицы автоматически изменяет цвет фона всех представлений внутри представления содержимого для выделенного состояния. Вы можете рассмотреть подклассификацию UIView
, чтобы нарисовать свой цвет или использовать UIImageView
с пользовательским растянутым изображением размером 1x1 px.
Ответ 3
Нашел довольно элегантное решение вместо того, чтобы возиться с методами выбора/выделения таблицы TableCellCell. Вы можете создать подкласс UIView, который игнорирует установку цвета фона для очистки цвета.
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:
@interface NeverClearView : UIView
@end
@implementation NeverClearView
- (void)setBackgroundColor:(UIColor *)backgroundColor {
if (CGColorGetAlpha(backgroundColor.CGColor) != 0) {
[super setBackgroundColor:backgroundColor];
}
}
@end
Ответ 4
Еще один способ справиться с проблемой - заполнить представление графическим градиентом, например:
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];
Ответ 5
Для Swift 2.2 это работает
cell.selectionStyle = UITableViewCellSelectionStyle.None
и причина объясняется @Andriy
Это потому, что ячейка просмотра таблицы автоматически изменяет цвет фона все представления внутри содержимого для выделенного состояния.
Ответ 6
Вы можете cell.selectionStyle = UITableViewCellSelectionStyleNone;
,
затем установите backgroundColor в - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
Ответ 7
Вдохновленный
Yatheesha B L
ответ
Я создал категорию/расширение 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 совместим с CocoaPod. Вы можете найти его на GitHub
Ответ 8
UITableViewCell по какой-либо причине меняет backgroundColor всех подзонов на выбор.
Это может помочь:
DVColorLockView
Используйте что-то подобное, чтобы остановить изменение UITableView во время выбора.
Ответ 9
Вдохновленный Yatheesha B L ответ.
Если вы вызываете super.setSelected(выбранный, анимированный: анимированный), , он очистит весь цвет фона, который вы установили. Таким образом, мы не будем называть супер метод.
В 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
}
}
Ответ 10
Нарисуйте представление вместо установки цвета фона
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);
}
}
}
Ответ 11
вот мое решение, используйте 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;
}
}
Ответ 12
Попробуйте следующий код:
-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
//Set your View Color here.
}
Ответ 13
На основании ответа Пола Гурова я реализовал следующее в Xamarin.iOS. Версия С#:
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()
{
}
}
Ответ 14
Не забудьте переопределить 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()
}
Ответ 15
Поместите этот код в свой подкласс 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)
}
}
Ответ 16
Это похоже на ответ Павла Гурова, но более гибкий, поскольку он позволяет любому цвету быть постоянным.
class PermanentBackgroundColorView: UIView {
var permanentBackgroundColor: UIColor? {
didSet {
backgroundColor = permanentBackgroundColor
}
}
override var backgroundColor: UIColor? {
didSet {
if backgroundColor != permanentBackgroundColor {
backgroundColor = permanentBackgroundColor
}
}
}
}
Ответ 17
Добавление другого решения, если вы используете раскадровки. Создайте подкласс UIView
, который не позволяет устанавливать backgroundColor
после того, как он был первоначально установлен.
@interface ConstBackgroundColorView : UIView
@end
@implementation ConstBackgroundColorView
- (void)setBackgroundColor:(UIColor *)backgroundColor {
if (nil == self.backgroundColor) {
[super setBackgroundColor:backgroundColor];
}
}
@end
Ответ 18
Если упомянутое выше фоновое решение не устраняет вашу проблему, ваша проблема может заключаться в вашем datasource
для вашего tableView.
Для меня я создавал экземпляр объекта DataSource (называемый BoxDataSource
) для обработки методов tableate делегата и dataSource, так:
//In cellForRowAtIndexPath, when setting up cell
let dataSource = BoxDataSource(delegate: self)
cell.tableView.dataSource = dataSource
return cell
Это вызывало освобождение dataSource всякий раз, когда ячейка была прослушена, и, следовательно, все содержимое исчезло. Причина заключается в том, что ARC освобождает/собирает мусор.
Чтобы исправить это, мне пришлось войти в пользовательскую ячейку, добавить переменную datasource:
//CustomCell.swift
var dataSource: BoxDataSource?
Затем вам необходимо установить источник данных в файл dataSource var
, который вы только что создали в cellForRow, поэтому это не освобождается от ARC.
cell.statusDataSource = BoxAssigneeStatusDataSource(delegate: self)
cell.detailsTableView.dataSource = cell.statusDataSource
return cell
Надеюсь, что это поможет.
Ответ 19
Я хотел сохранить поведение по умолчанию, за исключением одного поднабора ячеек, что я хотел игнорировать автоматическое изменение цвета фона. Но мне также нужно было изменить цвет фона в другое время.
Решение, с которым я столкнулся, заключалось в подклассе UIView
поэтому он игнорирует настройку цвета фона и добавляет отдельную функцию для обхода защиты.
Swift 4
class MyLockableColorView: UIView {
func backgroundColorOverride(_ color: UIColor?) {
super.backgroundColor = color
}
override var backgroundColor: UIColor? {
set {
return
}
get {
return super.backgroundColor
}
}
}
Ответ 20
Для случая может быть, это сентябрь, чтобы избежать получения серого цвета для всех элементов в ячейке (если вы используете пользовательскую ячейку таблицы таблиц):
-
Установите для параметра selectionStyle значение.none 👉 selectionStyle =.none
-
Переопределите этот метод.
func setHighlighted (_ выделено: Bool, animated: Bool)
-
Позвоните супер, чтобы получить преимущество супер-настройки.
super.setHighlighted (выделенный, анимированный: анимированный)
-
Сделайте то, что когда-либо выделяет логику, которую вы хотите.
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
// Your Highlighting Logic goes here...
}