I want to refresh tableView appearance after I press "Dark mode".But it looks like this:
Before press"Dark mode"
After press"Dark mode"
How can I refresh this tableView after I changed it's appearance
Mycode:
#IBAction func setDarkMode(sender: UISwitch) {
UIView.animateWithDuration(0.5, delay:0,options:UIViewAnimationOptions.BeginFromCurrentState, animations: { () -> Void in
self.setStyleMode()
}) { (finish: Bool) -> Void in
}
}
func setStyleMode() {
if isDarkMode {
view.backgroundColor = UIColor(red:0.1922, green:0.1922, blue:0.1922, alpha:1.0)
self.tableView.backgroundView?.backgroundColor = UIColor(red:0.1922, green:0.1922, blue:0.1922, alpha:1.0)
tableView.separatorColor = UIColor(red:0.3137, green:0.3137, blue:0.3137, alpha:1.0)
self.navigationController?.navigationBar.barTintColor = UIColor(red:0.1451, green:0.1451, blue:0.1451, alpha:1.0)
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor(red:0.6549, green:0.6549, blue:0.6549, alpha:1.0)]
self.navigationController?.navigationBar.tintColor = UIColor(red:0.9412, green:0.3412, blue:0.302, alpha:1.0)
for sectionIndex in 0...tableView.numberOfSections - 1 {
for rowIndex in 0...tableView.numberOfRowsInSection(sectionIndex) - 1 {
let cellPath = NSIndexPath(forRow: rowIndex, inSection: sectionIndex)
let cell = tableView.cellForRowAtIndexPath(cellPath)
cell?.backgroundColor = UIColor(red:0.1451, green:0.1451, blue:0.1451, alpha:1.0)
}
}
for aLabel in labels {
aLabel.textColor = UIColor(red:0.6549, green:0.6549, blue:0.6549, alpha:1.0)
}
} else {
view.backgroundColor = UIColor.whiteColor()
tableView.backgroundColor = UIColor(red:0.9529, green:0.9529, blue:0.9529, alpha:1.0)
tableView.separatorColor = UIColor(red:0.7372, green:0.7371, blue:0.7372, alpha:1.0)
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.blackColor()]
self.navigationController?.navigationBar.tintColor = UIColor(red:0.9412, green:0.3412, blue:0.302, alpha:1.0)
for sectionIndex in 0...tableView.numberOfSections - 1 {
for rowIndex in 0...tableView.numberOfRowsInSection(sectionIndex) - 1 {
let cellPath = NSIndexPath(forRow: rowIndex, inSection: sectionIndex)
let cell = tableView.cellForRowAtIndexPath(cellPath)
cell?.backgroundColor = UIColor.whiteColor()
//do stuff with 'cell'
}
}
for aLabel in labels {
aLabel.textColor = UIColor.blackColor()
}
}
}
(This "settings" tableView is in a "tableviewController " and embed in a ContainerView)
Looks like you have not called reloadData()
Once your style changes are over call call execute the following code
tableView.reloadData()
Another thing is, styling your tableViewCellshould be done inside
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
Not inside setStyleMode() function. You can make the style changes based on some bool value.
Hope this will resolve your issue
You're setting the cell's background color, but not the cell's contentView's background color.
You should do:
let cell = tableView.cellForRowAtIndexPath(cellPath)
cell?.backgroundColor = ....
cell?.contentView.backgroundColor = ....
You might have to dig deeper if your cell has more wrapper views in the hierarchy.
A couple of observations, though:
It would be a better pattern to define a method within the UITableViewCell subclass to define a dark and light mode. In complex cell structures, you might not easily be able to access all the subviews you need. Besides, what about encapsulation?
I would also much prefer the reload way. Calling a UITableViewDatasource method manually seems like an anti-pattern.
There's a lot of duplication in your code. You could significantly reduce the dependency by, for instance, using ternary operators on isDarkMode
Need change background of "headerView" and "footerView" in "setStyleMode()"
let header = tableView.headerViewForSection(sectionIndex)
let footer = tableView.footerViewForSection(sectionIndex)
header?.contentView.backgroundColor = UIColor(red:0.1922, green:0.1922, blue:0.1922, alpha:1.0)
footer?.contentView.backgroundColor = UIColor(red:0.1922, green:0.1922, blue:0.1922, alpha:1.0)
Related
I am trying to show a large Title in a Navigation bar, but with clear background. When scrolled up, it will be the Navigation bar with a blur effect.
This looks correct, however, when scrolling, the animation seems to be broken. Also, transition gets stuck from time to time:
My code as follows:
UINavigationController:
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
self.navigationBar.prefersLargeTitles = true
let style = UINavigationBarAppearance()
style.configureWithDefaultBackground()
style.titleTextAttributes = [.font: UIFont.systemFont(ofSize: 18)]
self.navigationBar.standardAppearance = style
self.navigationBar.compactAppearance = style
//Configure Large Style
let largeStyle = UINavigationBarAppearance()
largeStyle.configureWithTransparentBackground()
largeStyle.largeTitleTextAttributes = [.font: UIFont.systemFont(ofSize: 28)]
self.navigationBar.scrollEdgeAppearance = largeStyle
}
}
The UITableView is inside the UINavigationController. Both are from storyboards via a segue way.
Instead of UITableview, You can try using UITableViewController. I have tried using UITableViewController and its working fine for me. Please check the following design and code.
class ViewController: UITableViewController
{
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
let style = UINavigationBarAppearance()
style.configureWithDefaultBackground()
style.titleTextAttributes = [.font: UIFont.systemFont(ofSize: 18)]
self.navigationController?.navigationBar.standardAppearance = style
self.navigationController?.navigationBar.compactAppearance = style
//Configure Large Style
let largeStyle = UINavigationBarAppearance()
largeStyle.configureWithTransparentBackground()
largeStyle.largeTitleTextAttributes = [.font: UIFont.systemFont(ofSize: 28)]
self.navigationController?.navigationBar.scrollEdgeAppearance = largeStyle
}
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
// Do any additional setup after loading the view.
}
override func numberOfSections(in tableView: UITableView) -> Int {
1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
}
Output:-
In view debugger, check if navigation title goes beyond navigation bar bounds.
If that's the case then :
let titleHeight = UIFont.systemFont(ofSize: 28).lineHeight
if titleHeight > self.view.frame.size.height {
self.navigationController.navigationBar.frame = CGRectMake(0, 0, self.view.frame.size.width, titleHeight + topAndBottomPadding)
}
hey How are you here is your code try to remove this line
largeStyle.configureWithTransparentBackground()
you have to configure with white background
your code:
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
self.navigationBar.prefersLargeTitles = true
let style = UINavigationBarAppearance()
style.configureWithDefaultBackground()
style.titleTextAttributes = [.font: UIFont.systemFont(ofSize: 18)]
self.navigationBar.standardAppearance = style
self.navigationBar.compactAppearance = style
//Configure Large Style
let largeStyle = UINavigationBarAppearance()
largeStyle.configureWithTransparentBackground()
largeStyle.largeTitleTextAttributes = [.font: UIFont.systemFont(ofSize: 28)]
self.navigationBar.scrollEdgeAppearance = largeStyle
}
}
changing properties via storyboard night i’ve some insights. usually when i’m stuck i reflect same
changes that i made programmatically to storyboard and the things left in code are usually the ones causing my bug. try this out if possible
I have a tableView which is a subclass of a Parallax table view I found on Github. Done all table view set up as normal (Deleted some of it since its irrelevant).
class EventDetailTableViewController: ParallaxTableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Set the image:
self.imageView.image = eventImage
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = true
}
// MARK: - UITableViewDelegate
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 4
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// SET UP CELL
}
#IBAction func backButtonPressed(sender: AnyObject) {
print("backButtonPressed")
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)
self.navigationController?.popViewControllerAnimated(true)
}
} // END OF VIEWCONTROLLER CLASS
Important things to note here is I have made the navigationBar transparent. When backButtonPressed is called, I wish to change back the navigationBar.Color to the color of the previous View Controller (Red). So I have coded that in the backButtonPressed()
Here is the Parallax code I have. Please view the last func moveImage(). I have the simple effect of when the tableview scrolls down far enough to the description the navigationBar appears with the title "Event Description"
class ParallaxTableViewController: UITableViewController {
// Create the UIView
//var bottomFloatingView = UIView()
// Create the UIImageView
let imageView = UIImageView()
// Set the factor for the parallaxEffect. This is overwritable.
var parallaxFactor:CGFloat = 2
// Set the default height for the image on the top.
var imageHeight:CGFloat = 320 {
didSet {
moveImage()
}
}
// Initialize the scrollOffset varaible.
var scrollOffset:CGFloat = 0 {
didSet {
moveImage()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Set the contentInset to make room for the image.
self.tableView.contentInset = UIEdgeInsets(top: imageHeight, left: 0, bottom: 0, right: 0)
// Change the contentMode for the ImageView.
imageView.contentMode = UIViewContentMode.ScaleAspectFill
// Add the imageView to the TableView and send it to the back.
view.addSubview(imageView)
view.sendSubviewToBack(imageView)
}
override func viewDidLayoutSubviews() {
// Update the image position after layout changes.
moveImage()
}
// Define method for image location changes.
func moveImage() {
let imageOffset = (scrollOffset >= 0) ? scrollOffset / parallaxFactor : 0
let imageHeight = (scrollOffset >= 0) ? self.imageHeight : self.imageHeight - scrollOffset
imageView.frame = CGRect(x: 0, y: -imageHeight + imageOffset, width: view.bounds.width, height: imageHeight)
if imageOffset > 150 {
print("imageOffSet")
self.navigationItem.title = "Event Description"
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.shadowImage = nil
} else {
print("else")
self.navigationItem.title = ""
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = true
// This is being called after the back button is being pressed. Which means this else function overrides my backButtonPressed() therefore making my navigation bar in the new VC not the correct color.
}
}
}
As you can see in my notes, this else function is being called again after the backButtonPressed() is called. Therefore it does not give me the desired red in the new VC but it leaves it translucent instead. How can I stop this else function being called when the backButtonPressed is being called?
viewDidLayoutSubviews should never be involved in responding to user events. It is an internal lifecycle method that is rarely used unless you're adding or modifying programmatic NSLayoutConstraints to those already added in Storyboard. It is called quite frequently and apparent redundancy.
Use table delegate methods instead. In particular UITableViewDelegate inherits from UIScrollViewDelegate so reference:
UITableView Scroll event
Then query the tableView itself for visibility information e.g. indexPathsForVisibleRows:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instp/UITableView/indexPathsForVisibleRows
You should not use viewDidLayoutSubviews() like this as BaseZen has explained in his answer.
You can use scrollViewDidScroll to achieve what you want.
Replace this
#IBAction func backButtonPressed(sender: AnyObject) {
print("backButtonPressed")
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)
self.navigationController?.popViewControllerAnimated(true)
}
With this
var backButtonWasPressed = false
#IBAction func backPressed(sender: AnyObject) {
print("backButtonPressed")
backButtonWasPressed = true
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)
self.navigationController?.popViewControllerAnimated(true)
}
And replace this
override func viewDidLayoutSubviews() {
// Update the image position after layout changes.
moveImage()
}
With this
override func scrollViewDidScroll(scrollView: UIScrollView) {
if !backButtonWasPressed {
moveImage()
}
}
And put backButtonWasPressed = false in your viewDidLoad()
I have a custom cell in my table view which contain a button and name of audio file. when i am tapping in button the relevant audio is playing and when tapping again it audio stops. My problem is when i am tapping the same button it is ok but when i am tapping in any button different then current cell then my process is not working. Can any one show me the right direction to do this . My code is below . Thanks in advance..
var isAudioPlaying = false
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return designCellAtIndexPath(indexPath)
}
private func designCellAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = NSBundle.mainBundle().loadNibNamed("ExtendedDesign", owner: self, options: nil)[4] as! UITableViewCell
cell.frame = CGRectMake(0.0, 0.0, UIScreen.mainScreen().bounds.size.width, cell.bounds.height)
cell.contentView.frame = cell.bounds
cell.selectionStyle = UITableViewCellSelectionStyle.None
btnPlayPause = cell.viewWithTag(1) as! subclassedUIButton
btnPlayPause.addTarget(self, action: "btnPlayPauseTapped:", forControlEvents: .TouchUpInside)
btnPlayPause.urlString = arrAttractionList[indexPath.row].audio.url
let lblAttractionName = cell.viewWithTag(2) as! UILabel
lblAttractionName.text = arrAttractionList![indexPath.row].name
return cell
}
My Button Methode is:
func btnPlayPauseTapped(sender: subclassedUIButton) {
if !isAudioPlaying {
isAudioPlaying = true
sender.setImage(UIImage(named: "Button_Pause"), forState: .Normal)
AudioHandler.sharedManager().playAudio(sender.urlString)
} else {
isAudioPlaying = false
sender.setImage(UIImage(named: "Button_Play_Menu.png"), forState: .Normal)
AudioHandler.sharedManager().audioPlayer?.pause()
}
}
// Custome class for UIButton
class subclassedUIButton: UIButton {
var indexPath: Int?
var urlString: String?
}
You have to manage other flag for your current cell's audio you have to play. Set current cell index and manage that.
let cell: UITableViewCell = NSBundle.mainBundle().loadNibNamed("ExtendedDesign", owner: self, options: nil)[4] as! UITableViewCell
This is not the correct way to add a cell to a table view. You should call registerNib(_:forCellReuseIdentifier:) (usually in the viewDidLoad() method) and then dequeueReusableCellWithIdentifier(_:forIndexPath:) in your cellForRowAtIndexPath(_:) delegate method.
The registerNib(_:forCellReuseIdentifier:) isn't needed if you design your cell with a template in the storyboard.
But you really need to use table views the way they were designed to be used. What you have now might seem to work, but it's going to have problems and make your life miserable if you don't use table views the way they were intended to be used.
Also, you don't want to be referencing your subviews with viewWithTag(_:). You want to wire up proper IBOutlets in Interface Builder. Or at least creating properties in your UITableView subclass to access the subviews.
Finally I did it here is my code to do this. First Declare Two variables in class:
var currentCellIndex :int = -1
var previousCellIndex : int = -1
func btnPlayPauseTapped(sender: subclassedUIButton) {
currentCellIndex = sender.indexPath!
if currentCellIndex == previousCellIndex {
if !isAudioPlaying {
isAudioPlaying = true
AudioHandler.sharedManager().stopAudioPlayer()
sender.setImage(UIImage(named: "Button_Play_Menu.png"), forState: .Normal)
} else {
isAudioPlaying = false
AudioHandler.sharedManager().playAudio(sender.urlString)
sender.setImage(UIImage(named: "Button_Pause"), forState: .Normal)
}
} else {
let indexPath = NSIndexPath(forRow: previousCellIndex, inSection: 0)
tblAttractinList.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
isAudioPlaying = false
sender.setImage(UIImage(named: "Button_Pause"), forState: .Normal)
AudioHandler.sharedManager().playAudio(sender.urlString)
previousCellIndex = sender.indexPath!
}
}
Thank You all of you for your help! :)
I'd like to change the color of my cell accessoryType from blue to white.
The textColor is already set to white.
Does someone of you guys know how to do this?
My Code:
cell!.accessoryType = UITableViewCellAccessoryType.Checkmark
You can set your UITableViewCell tintColor property to the desired color:
[cell setTintColor:[UIColor whiteColor]];
Doesn't work for .disclosureIndicator ?
If someone is here looking for "How to change color for .disclosureIndicator indicator type".
The answer is you can't. BUT:
There is a way. Apply a custom image:
let chevronImageView = UIImageView(image: "disclosureIndicatorImage"))
accessoryView = chevronImageView
Additional supporting links:
The image can be downloaded from here.
How to change color of the image is here.
Swift:
cell.tintColor = UIColor.whiteColor()
Swift 3.0
cell.tintColor = UIColor.white
"How to change color for .disclosureIndicator indicator type". After much research, I noticed that the image of disclosureIndicator is not an Image but a backgroundImage. I found a solution like this:
import UIKit
class CustomCell: UITableViewCell {
fileprivate func commonInit() {
}
open override func layoutSubviews() {
super.layoutSubviews()
if let indicatorButton = allSubviews.compactMap({ $0 as? UIButton }).last {
let image = indicatorButton.backgroundImage(for: .normal)?.withRenderingMode(.alwaysTemplate)
indicatorButton.setBackgroundImage(image, for: .normal)
indicatorButton.tintColor = .red
}
}
}
extension UIView {
var allSubviews: [UIView] {
return subviews.flatMap { [$0] + $0.allSubviews }
}
}
Swift 3.1:
cell.backgroundColor = UIColor.yellow // the accessoryType background
cell.tintColor = UIColor.black // the accessoryType tint color.
Swift 5 I am Improving Tung Fam Answer
let chevronImageView = UIImageView(image: UIImage(named: "chevron-right"))
cell.accessoryView = chevronImageView
You can also change the cell's tint color from the storyboard (assuming you are using a xib file)
Im my case i need to change contentView color of my CustomCell.
Its can be easy making when u override methods :
override func setHighlighted(highlighted: Bool, animated: Bool) {}
and:
override func setSelected(selected: Bool, animated: Bool) {}
But when i add to my customCell :
cell?.accessoryType = .DisclosureIndicator
i had a problem when view under DisclosureIndicator is not change color. Its looks like:
So i look on subviews of CustomCell and find that DisclosureIndicator is a button. If change background color of this button u have this
So i try to change background color of superview of this button. And its work great.
Full code of myCustomCell setHighlighted func :
override func setHighlighted(highlighted: Bool, animated: Bool) {
if(highlighted){
viewContent.view.backgroundColor = Constants.Colors.selectedBackground
for item in self.subviews {
if ((item as? UIButton) != nil) {
item.superview?.backgroundColor = Constants.Colors.selectedBackground
}
}
} else {
viewContent.view.backgroundColor = Constants.Colors.normalCellBackground
for item in self.subviews {
if ((item as? UIButton) != nil) {
item.superview?.backgroundColor = Constants.Colors.normalCellBackground
}
}
}
}
The best way to do that, I think, is to set accessory to image the following way:
let image = UIImage(named: "some image.png")
cell.accessoryView = image
cell.contentView.backgroundColor = .grey
cell.backgroundColor = .grey
I want to use TTTAttributedLabel to detect the link of the text in the Label of UITableViewCell, but it doesn't work. I'm using swift with iOS8. below is UITableViewCell code:
class StoryTableViewCell: UITableViewCell, TTTAttributedLabelDelegate {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
// Link properties
let textLabel = self.descriptionLabel
let linkColor = UIColor(red: 0.203, green: 0.329, blue: 0.835, alpha: 1)
let linkActiveColor = UIColor.blackColor()
if (textLabel is TTTAttributedLabel) {
var label = textLabel as TTTAttributedLabel
label.linkAttributes = [NSForegroundColorAttributeName : linkColor]
label.activeLinkAttributes = [NSForegroundColorAttributeName : linkActiveColor]
label.enabledTextCheckingTypes = NSTextCheckingType.Link.toRaw()
label.delegate = self
}
}
}
I think you have not configured your custom cell correctly.
First at your customCell declare and connect your IBOutlet-s. Select your textLabel and add its class to TTTAttributedLabel. Your custom cell should look like this:
class StoryTableViewCell: UITableViewCell {
#IBOutlet weak var textLabel: TTTAttributedLabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Second you need to add the TTTAttributedLabelDelegate at the class where you are using the tableView datasource and delegate.
Then under cellForRowAtIndexPath
var cell: StoryTableViewCell = tableView.dequeueReusableCellWithIdentifier("yourCellIdentifier") as StoryTableViewCell
let linkColor = UIColor(red: 0.203, green: 0.329, blue: 0.835, alpha: 1)
let linkActiveColor = UIColor.blackColor()
cell.textLabel.delegate = self
cell.textLabel.linkAttributes = [kCTForegroundColorAttributeName : linkColor]
cell.textLabel.activeLinkAttributes = [kCTForegroundColorAttributeName : linkActiveColor]
cell.textLabel.enabledTextCheckingTypes = NSTextCheckingType.Link.rawValue
Then if you have methods that need to be executed from TTTAttributedLabelDelegate add them and do your calculations.
Hope it helps
If you've set TTTAttributedLabel as the class of your UILabel, within a nib or the storyboard, make sure User Interaction Enabled is set to true, as be default a UILabel will have user interaction disabled.
let linkColor = UIColor.blueColor()
let linkActiveColor = UIColor.greenColor()
textLabel.delegate = self
textLabel.linkAttributes = [kCTForegroundColorAttributeName : linkColor.CGColor,kCTUnderlineStyleAttributeName : NSNumber(bool: true)]
textLabel.activeLinkAttributes = [NSForegroundColorAttributeName : linkActiveColor]
textLabel.enabledTextCheckingTypes = NSTextCheckingType.Link.rawValue
swift 4.2
label.enabledTextCheckingTypes = NSTextCheckingResult.CheckingType.link.rawValue | NSTextCheckingResult.CheckingType.phoneNumber.rawValue
Nothing works for me finally i put below code in TTTAttributedLabel.m in commonInit() method
self.enabledTextCheckingTypes = NSTextCheckingTypeLink;