UIView backgroundColor disappears when UITableViewCell is selected

前端 未结 17 816
谎友^
谎友^ 2020-11-30 17:49

I have a simple tableViewCell build in interface builder. It contains a UIView which contains an image. Now, when I select the cell, the default blue selection background is

相关标签:
17条回答
  • 2020-11-30 18:23

    You can change the behavior of the tableViewCell by overriding the function setHighlighted in UITableViewCell class (you will need to inherit from it). Example of my code where I change the background image of my cell :

    // 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"]; 
        }
    }
    

    You can also change the selection mode to gray, blue or none in the interface builder.

    0 讨论(0)
  • 2020-11-30 18:26

    Add this to your UITableViewCell

    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()
            })
        }
    }
    
    0 讨论(0)
  • 2020-11-30 18:28

    When your UITableViewCell is selected, there are two states you should pay attention to: Highlighted and Selected.

    So, for scenarios that you have a custom cell class which is subclass of UITableViewCell, you can easily override these two methods to avoid this situation(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
        }
    
    }
    
    0 讨论(0)
  • 2020-11-30 18:28

    Summary

    This solution let's you lock some of a cell's background colors, while the remainder are controlled by system behaviour.


    Based on mientus' answer, I have created a solution which allows you to specify which views should keep their background color.

    This still allows other cell subviews to have their background removed on highlighting/selection, and is the only solution which works in our case (two views needing a permanent background).

    I used a protocol-oriented approach, with a BackgroundLockable protocol containing the list of views to lock, and running a closure while keeping the colors:

    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
            }
        }
    }
    

    Then I have a subclass of UITableViewCell, which overrides highlighting and selection to run the protocol's closure around calling the default (super) behaviour:

    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)
           }
        }
    }
    

    Now I just have to subclass LockableBackgroundTableViewCell or use the BackgroundLockable protocol in a cell class to easily add locking behaviour to some cells!

    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]
        }
    }
    
    0 讨论(0)
  • 2020-11-30 18:29

    You need to override the next two methods in your custom cell:

    - (void) setSelected:(BOOL)selected animated:(BOOL)animated;
    - (void) setHighlighted:(BOOL)highlighted animated:(BOOL)animated;
    

    Note that:

    • you should call [super setSelected:animated:] and [super setHighlighted:animated:] in the beginning of your custom implementation or correspond methods;
    • you should set the UITableViewCellSelectionStyleNone selectionStyle for your custom cell, to disable any default UITableViewCell styling;

    Here the example of the implementation:

    - (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();
    }
    

    The contentView is the property of UITableViewCell that is appeared in iOS 7. Note that you can use your own cell's child view or views instead of it.

    0 讨论(0)
  • 2020-11-30 18:31

    Ok, loosing the background color of a UIView class is normal behavior when its in a selected tableviewcell. I couldn't figure out how to prevent that. Now I've just replaced the UIView with an UIImageView containing a stretched 1x1 white pixel. Ugly imo, but it works.

    0 讨论(0)
提交回复
热议问题