2011-03-07 77 views
58

我有一個簡單的tableViewCell構建在界面生成器中。 它包含一個包含圖像的UIView。 現在,當我選擇單元格時,會顯示默認的藍色選擇背景,但我的UIView的backgroundColor已消失。UIView backgroundColor當UITableViewCell被選中時消失

我的UITableViewCell的實現文件沒有做任何特別的事情。它只是初始化的&返回self,我在setSelected中做的所有操作都是超級調用。

如何獲取我的UIView backgroundColor以顯示何時選擇tableView?

+0

還有哪些其他的界面元素的視圖中,即得到由小區選擇顏色覆蓋? – hennes 2011-03-07 17:48:53

+0

目前這只是一個圖像。這是爲了使圖像看起來像一張照片。稍後,我還會在那裏添加一個標籤。 – P5ycH0 2011-03-07 18:21:20

回答

96

這裏的問題是,[超級]實施

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

將所有的背景顏色中的UITableViewCell到RGBA(0,0,0,0)。爲什麼?也許讓我們都汗流?背?

這並不是說整個的看法消失

這裏(的事實,如果你改變了看法層邊框屬性,這些被保留作爲證據)是函數的調用序列,從觸摸細胞

結果
  1. setHighlighted
  2. touchesEnded
  3. layoutSubviews
  4. willSelectRowAtIndexPath(委託側)
  5. setSelected(!!!這是你的所有觀察背景色被告知消失)
  6. didSelectRowAtIndexPath方法(委託方)
  7. 的setSelected(再次)(有趣的是背景顏色不清除此調用。該超法裏面是怎麼回事什麼奇怪?)
  8. layoutSubviews(再次)

所以,你的選擇是

  1. 覆蓋- (空)的setSelected:選擇動畫(BOOL)(布爾)ANI配合;沒有致電[super setSelected:選擇動畫:動畫]。這會給你最正確的技術實現,因爲a)代碼被包裝在UITableViewCell子類中,b)因爲它只在需要的時候被調用(在需要的時候會被調用兩次,但也許有解決方法)。不利的一面是你必須重新實現setSelected的所有必要功能(而不是不必要的顏色清除功能)。現在不要問我如何正確覆蓋setSelected了。你的猜測和我現在一樣好(耐心等待,一旦我弄明白了,我會編輯這個答案)。
  2. 重新斷言didSelectRowAtIndexPath中的背景顏色。這不是太好,因爲它將實例代碼放在實例外。它有一個好處,它只在需要時才被調用,而不是...
  3. 重新斷言背景顏色layoutSubviews。這並不好,因爲layoutSubviews被稱爲百萬倍!每次餐桌刷新時,每次滾動時,都會調用它,每當祖母得到燙髮時......就像是認真的,一百萬次。這意味着有很多不必要的背景重新斷言和大量額外的處理開銷。好的一面是它將代碼放在UITableViewCell子類中,這很好。

不幸的是重新斷言在setHighlighted背景顏色不執行任何操作,因爲之前所有的背景顏色都將置到setHighlighted稱爲[R:0 B:0 G:0:0]由第一次調用的setSelected。

// TODO:給如何重寫的setSelected一個偉大的說明(敬請關注)

+1

之前,背景顏色似乎已被清除。非常有意義!我會繼續關注覆蓋;-) – P5ycH0 2012-02-21 09:40:16

+0

只是跟進。我已經搞砸了這一點,但仍然沒有找到我會稱爲重寫setSelected的乾淨,通用的解決方案。如果/當我這樣做,我會發布更多的信息.​​...快樂的編碼 – Brooks 2012-05-15 20:46:53

+0

感謝光明日增加壓力! – amcc 2013-04-24 19:40:44

0

從你說你使用IB構建了一個tableViewCell,我想檢查你是否將你的視圖添加爲UITableViewCell的contentView的子視圖,而不是view。內容視圖是單元格顯示內容的默認超級視圖。

從參考:

一個UITableViewCell對象的內容視圖是由該單元所顯示的內容的缺省上海華。如果您想通過簡單地添加附加視圖來自定義單元格,則應該將它們添加到內容視圖中,以便在單元格進入和退出編輯模式時適當定位它們。

+0

我在InterfaceBuilders中查看hierachie UITableViewCell是TableViewCell> View> ImageView。如果我使用代碼構建tableViewCell,我可能會錯誤地將視圖添加到tableviewcell的視圖而不是contentView中,但我不明白我如何在IB中犯這個錯誤...請注意,我的圖像正在顯示,但父視圖元素不是。 – P5ycH0 2011-03-07 18:41:05

3

好吧,丟失UIView類的背景顏色是正常的行爲,當它在一個選定的tableviewcell。 我無法弄清楚如何防止這種情況。 現在我剛剛用包含拉伸的1x1白色像素的UIImageView替換了UIView。 醜陋的imo,但它的作品。

0

您可以通過覆蓋UITableViewCell類中的setHighlighted函數(您將需要繼承它)來更改tableViewCell的行爲。我的代碼,我改變我的手機背景圖片示例:

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

您也可以改變選擇模式爲灰色,在界面生成器的藍色或無。

+0

是的,我知道。但那不是我的問題。我想知道,如果在選定的tableviewcell上,我可以防止丟失基於UIView的元素的背景顏色。我通過使用imageview而不是視圖找到了解決方法。 – P5ycH0 2011-03-11 21:38:20

+0

還有更多信息:在我最近的測試中,我發現每次選擇一個單元格後,背景顏色都會被清除,而不僅僅是在初始化之後或你有什麼。事件序列似乎是1)setHighlighted調用2)touchesEnded調用3)layoutSubviews調用4)didSelectRowAtIndexPath調用4)layoutSubviews再次調用。在didSelectRowAtIndexPath – Brooks 2012-02-17 20:30:13

4

布魯克斯爲什麼發生這種情況的很好的解釋,但我想我有一個更好的解決方案。

在您的子視圖中,將setBackgroundColor:覆蓋爲您想要的顏色。二傳手仍將被調用,但只有您指定的顏色將被強制執行。

- (void)setBackgroundColor:(UIColor *)backgroundColor { 
    [super setBackgroundColor:[UIColor whiteColor]]; 
} 
12

此前我已經照@ P5ycH0說(1x1圖片拉伸),但以下@Brooks我想通覆蓋在我的自定義UITableViewCell實施-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated,並呼籲[super setHighlighted:highlighted animated:animated];後重置的背景顏色使我的背景色當小區被選擇/高亮

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { 
    [super setHighlighted:highlighted animated:animated]; 
    myView.backgroundColor = myColor; 
} 
+0

這對我來說算得了。 – 2013-11-15 16:33:12

+1

最佳解決方案 – 2014-04-15 22:59:07

+0

感謝您搜索了2天 – sanjeev 2014-05-17 07:07:34

2

你需要重寫你的自定義單元格的下兩種方法:

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

需要注意的是:

  • 你應該調用[super setSelected:animated:][super setHighlighted:animated:]在自定義開始實施或對應的方法;
  • 您應該爲您的自定義單元格設置UITableViewCellSelectionStyleNone selectionStyle,以禁用任何默認的UITableViewCell樣式;

這裏執行的例子:

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

contentView是出現在iOS的7需要注意的是,你可以用自己的細胞的子視圖或觀點,而不是它的UITableViewCell財產。

62
- (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; 
} 
+0

偉大的解決方案。比所有子類和CALayer解決方案都要乾淨得多。 – Joel 2014-09-15 04:23:12

+0

謝謝!您的解決方案是最好的! – Insider 2016-04-29 12:17:48

+0

這對我來說是最有用的答案。 [修改](https://stackoverflow.com/a/45882764/991856)稍微爲我的用例(多個單元格帶有多個鎖定的背景視圖),但工作解決方案的榮譽! – Yasir 2017-08-25 13:43:45

0

在iOS系統7,什麼工作對我來說是在UITableViewCell子類覆蓋setSelected:animated:,但違背@Brooks'尖,我叫[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]; 
} 

這讓我保持系統的默認選擇動畫當用戶點擊該單元格,也可以取消選擇在表視圖委託的didSelectRowAtIndexPath:

0

剛在這個奇怪的問題上花了一些時間。我不想設置UITableViewCellSelectionStyleNone樣式,以在選中我的行時保留漂亮的動畫。但沒有任何建議的想法爲我工作 - 我試圖覆蓋setSelected和setHighlighted並設置我的子視圖backgroundColor那裏 - 它保持iOS重置,並仍然閃爍(新顏色 - >舊顏色)。 對我來說修復很簡單。 當我的行被選中時,推動了另一個視圖控制器,用戶在該屏幕上選擇一些選項,並在基於用戶選擇改變顏色的地方調用委託。在這個代表中,我只爲我的手機做了[cell setSelected:NO animated:NO]。 (我有靜態的UITableViewController,並有單元格出口)。 你可能可以在didSelect方法中取消選中單元格,但在我的情況下,我正在使用segues。

1

這對你的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() 
     }) 
    } 
} 
1

相關添加到@布魯克斯的答案,這是我做的,使其在斯威夫特和iOS8上/ iOS9工作。

  • 重寫setSelectedsetHighlighted
  • 不要叫超級
  • 清除出contentView.backgroundColor,因爲它不具有跨越細胞(即配件)的整個寬度。
  • 使用單元格本身的backgroundColor,並相應地設置它。

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

當選擇你的UITableViewCell,還有你要注意兩種狀態:HighlightedSelected

所以,你有一個自定義單元格類是UITableViewCell子類的場景,你可以很容易地覆蓋這兩個方法來避免這種情況(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

swift的最佳答案 – sleepwalkerfx 2016-10-18 07:08:27

0

以下是一張就可以了。我有我的所有細胞從繼承的子類,所以這是我這樣做是爲了避免在我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] 
     } 
    } 
} 

這程序自動修復該問題的所有UIImageView

0

摘要

這個解決方案讓我們你鎖定某些單元格的背景顏色,其餘由系統行爲的控制。


基於mientus' answer,我創建了一個解決方案,它可以讓你指定哪些意見應保持其背景顏色

這仍然允許其他單元格子視圖在突出顯示/選擇時刪除其背景,並且是在我們的案例中工作的唯一解決方案(需要永久背景的兩個視圖)。

我使用的面向協議的方法,用含有視圖鎖定列表中,並運行一個閉合,同時保持顏色的BackgroundLockable協議:

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

然後我具有UITableViewCell一個子類,其覆蓋突出顯示和選擇奔波調用默認(超)行爲協議的終止:

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

現在我只需要繼承LockableBackgroundTableViewCell或使用BackgroundLockable原在一個單元格類中添加鎖定行爲,以便輕鬆添加到某些單元格中

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

斯威夫特4

在你的UITableViewCell類:

override func setSelected(_ selected: Bool, animated: Bool) { 
    myView.backgroundColor = UIColor.blue 
} 

override func setHighlighted(_ highlighted: Bool, animated: Bool) { 
    myView.backgroundColor = UIColor.blue 
} 
相關問題