Blur and vibrancy effects on UITableView - ios

I just don't know how to do that. I've tried everything from Stackoverflow and nothing worked. I have a view, image and below all of that tableView in my hierarchy. But table view is still white. Is there somebody who knows how to do this? As I wrote, nothing from here worked.
I want to have this kind of UITableView:
Navigation bar is part of my question too (his blur and vibrancy).
After use of this code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
let backgroundImageView = UIImageView(image: UIImage(named: "background3.png"))
cell.backgroundView = backgroundImageView
var visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light)) as UIVisualEffectView
visualEffectView.frame = CGRectMake(0, 0, cell.bounds.width, cell.bounds.height)
backgroundImageView.addSubview(visualEffectView)
cell.textLabel?.text = self.field[indexPath.row]
cell.textLabel?.textColor = UIColor.whiteColor()
cell.textLabel?.backgroundColor = UIColor.clearColor()
return cell
}
My tableView now look like this:
And that is logical, because it is the look of the background3.png image.

Subclass UITableViewController.
let effect = UIBlurEffect(style: .Dark)
let resizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
Build a background view like this and stick it into your table view. Notice separator effect, which is new api.
override func viewDidLoad() {
super.viewDidLoad()
let backgroundView = UIView(frame: view.bounds)
backgroundView.autoresizingMask = resizingMask
backgroundView.addSubview(self.buildImageView())
backgroundView.addSubview(self.buildBlurView())
tableView.backgroundView = backgroundView
tableView.separatorEffect = UIVibrancyEffect(forBlurEffect: effect)
}
func buildImageView() -> UIImageView {
let imageView = UIImageView(image: UIImage(named: "coolimage"))
imageView.frame = view.bounds
imageView.autoresizingMask = resizingMask
return imageView
}
func buildBlurView() -> UIVisualEffectView {
let blurView = UIVisualEffectView(effect: effect)
blurView.frame = view.bounds
blurView.autoresizingMask = resizingMask
return blurView
}
Change background colour of cell to clear, so background is visible when you have cells.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)as! UITableViewCell
cell.backgroundColor = UIColor.clearColor()
return cell
}

So the solution is really simple. I've find a great tutorial on Youtube:
Swift iOS tutorial - Custom tableview appearance in Xcode 6
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
var openSansSemibold = UIFont(name: "OpenSans-Semibold", size: 12)?.fontDescriptor().fontDescriptorWithSymbolicTraits(UIFontDescriptorSymbolicTraits.TraitBold)
cell.textLabel?.font = UIFont(descriptor: openSansSemibold!, size: 12)
if(indexPath.row % 2 == 1){
cell.backgroundColor = UIColor.clearColor()
}else{
cell.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
cell.textLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
cell.detailTextLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
}
cell.textLabel?.textColor = UIColor.whiteColor()
return cell
}
In viewDidLoad() method:
self.tableView.rowHeight = 70
self.tableView.backgroundView = UIImageView(image: UIImage(named: "background"))
And that is it. Every odd cell has clear color, every even has blurred background. It looks really great!

Related

Elements of the FirstViewController still visible in DetailViewController after using pushViewController method

I first programmatically created a tableview :
private func setupTableView() {
tableView = UITableView(frame: CGRect(x: 0, y: 180, width: view.frame.width, height: view.frame.height), style: UITableView.Style.plain)
tableView.dataSource = self
tableView.delegate = self
tableView.register(ItemTableViewCell.self, forCellReuseIdentifier: "Cell")
view.addSubview(tableView)
}
and set the cellForRow method as below :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ItemTableViewCell
guard let finalItems = presenter.finalItems?[indexPath.row] else { return cell }
presenter.configure(cell: cell, FinalItem: finalItems)
return cell
}
Then I configure the ItemTableViewCell as below :
class ItemTableViewCell: UITableViewCell {
private var iconImageView : UIImageView = {
let imgView = UIImageView(image: #imageLiteral(resourceName: "Image"))
imgView.contentMode = .scaleAspectFit
imgView.clipsToBounds = true
return imgView
}()
private var titleLabel : UILabel = {
let lbl = UILabel()
lbl.textColor = .black
lbl.font = UIFont.boldSystemFont(ofSize: 12)
lbl.textAlignment = .left
return lbl
}()
func configure(finalItem: FinalItem) {
titleLabel.text = finalItem.title
iconImageView.downloaded(from: finalItem.images_url.small)
}
}
When I push to the DetailViewController with the uinavigationbar, the elements contained in the rows (titles, labels...) are still visible a few milli seconds:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let finalItem = finalItems[indexPath.row]
let detailViewController = ModuleBuilder.createDetailModuleWith(finalItem)
detailViewController.finalItem = finalItem
navigationController?.pushViewController(detailViewController, animated: true)
}
This is not what I am expecting. I never figure this problem out before.

Swift - How to change the color of an accessoryType (disclosureIndicator)?

I have question about the accessoryType of cells. I am using a cell with an disclosureIndicator as accessoryType and I want to change it's color but I can't.
Does anyone know if this is a bug or if Apple forces me to use the grey color?
Actually I can change the colors of other accessoryType.
My code looks like this:
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath) as! customCell
cell.tintColor = UIColor.red
cell.accessoryType = .disclosureIndicator
And my arrow is still grey. But if I use a checkmark accessoryType it becomes red.
Is there any way to fix this or do I have to use a colored image?
You can do something like this
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.tintColor = UIColor.white
let image = UIImage(named: "Arrow.png")
let checkmark = UIImageView(frame:CGRect(x:0, y:0, width:(image?.size.width)!, height:(image?.size.height)!));
checkmark.image = image
cell.accessoryView = checkmark
let object = objects[indexPath.row] as! NSDate
cell.textLabel!.text = object.description
return cell
}
Sample Arrow Images
Output
Use SF Symbol
let image = UIImage(systemName: "chevron.right")
let accessory = UIImageView(frame:CGRect(x:0, y:0, width:(image?.size.width)!, height:(image?.size.height)!))
accessory.image = image
// set the color here
accessory.tintColor = UIColor.white
cell.accessoryView = accessory
Updated for Swift 4.2 with images attached:
cell.accessoryType = .disclosureIndicator
cell.tintColor = .black
let image = UIImage(named:"disclosureArrow")?.withRenderingMode(.alwaysTemplate)
if let width = image?.size.width, let height = image?.size.height {
let disclosureImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
disclosureImageView.image = image
cell.accessoryView = disclosureImageView
}
Images you can use:
What it could look like:
Bellow Code is Swift 3.0 code, and will change the accessoryType color as per tintColor.
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "SOME TITLE GOES HERE"
cell.accessoryType = .disclosureIndicator
cell.tintColor = UIColor.blue
let image = UIImage(named:"arrow1")?.withRenderingMode(.alwaysTemplate)
let checkmark = UIImageView(frame:CGRect(x:0, y:0, width:(image?.size.width)!, height:(image?.size.height)!));
checkmark.image = image
cell.accessoryView = checkmark
return cell
}
Swift 5. Extension style ;)
extension UITableViewCell {
func setupDisclosureIndicator() {
accessoryType = .disclosureIndicator
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: 7, height: 12))
imgView.contentMode = .scaleAspectFit
imgView.image = UIImage(named: "your_icon_name")
accessoryView = imgView
}
}
Swift 5 & iOS 15 & Xcode 13
Here is an extension which uses SF Symbols, so you have a chevron like the default disclosure indicator one:
extension UITableViewCell {
func addCustomDisclosureIndicator(with color: UIColor) {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 10, height: 15))
let symbolConfig = UIImage.SymbolConfiguration(pointSize: 15, weight: .regular, scale: .large)
let symbolImage = UIImage(systemName: "chevron.right",
withConfiguration: symbolConfig)
button.setImage(symbolImage?.withTintColor(color, renderingMode: .alwaysOriginal), for: .normal)
button.tintColor = color
self.accessoryView = button
}
}
You can use it like this:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.addCustomDisclosureIndicator(with: .white) // Here your own color
return cell
}
Swift 5 & iOS 11-15
A combination of some answers
extension UITableViewCell {
func addCustomDisclosureIndicator(with color: UIColor) {
accessoryType = .disclosureIndicator
let disclosureImage = UIImage(named: "arrow_right")?.withRenderingMode(.alwaysTemplate)
let imageWidth = (disclosureImage?.size.width) ?? 7
let imageHeight = (disclosureImage?.size.height) ?? 12
let accessoryImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight))
accessoryImageView.contentMode = .scaleAspectFit
accessoryImageView.image = disclosureImage
accessoryImageView.tintColor = color
accessoryView = accessoryImageView
}
}

Blur effect on Image View is not working in iOS swift?

Here is my code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell:TableViewCell = tableView.dequeueReusableCellWithIdentifier("TracksCellTracksView") as! TableViewCell
self.addBlurEffect()
return cell
}
func addBlur effect() {
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.ExtraLight)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = albumArt!.bounds
blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
albumArt!.addSubview(blurEffectView)
}
This code is not working; Please tell me some alternative way to do it.
For info, I'm using constraints for ImageView.
If you are trying to apply the blur effect to the imageview on your table cell, then you need to do this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell:TableViewCell = tableView.dequeueReusableCellWithIdentifier("TracksCellTracksView") as! TableViewCell
addBlurView(cell.imageView)
return cell
}
func addBlurView(imgView: UIImageView) {
var blurEffect: UIBlurEffect = UIBlurEffect.effectWithStyle(UIBlurEffectStyleLight)
self.blurEffectView = UIVisualEffectView(effect: blurEffect)
self.blurEffectView.frame = imgView.bounds
self.blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
imgView.addSubview(blurEffectView)
}
You need to pass the reference of the imageview to your blur add method, so that blur gets added to that image view.

Any way to fix the overlapping of the button and the text?

I have a button on the right in a cell and text as well. The text overlaps the button. I want the text to go to the next line before it touches the button. How would I do that?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ProfileMusicCell
cell.customtitle.text = ret[indexPath.row]
cell.customartist.text = ter[indexPath.row]
cell.customtitle.font = UIFont(name: "Lombok", size: 22)
cell.customtitle.textColor = UIColorFromRGB("4A90E2")
cell.customartist.font = UIFont(name: "Lombok", size: 16)
cell.customartist.textColor = UIColor.blackColor()
cell.playbutton.tag = indexPath.row
cell.playbutton.addTarget(self, action: "playmusic:", forControlEvents: .TouchUpInside)
cell.contentView.addSubview(playButton)
cell.textLabel?.numberOfLines = 0;
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.backgroundColor = UIColor.clearColor()
return cell
}
func playmymusic(sender: UIButton!) {
let playButtonrow = sender.tag
print(ret[playButtonrow])
print(ter[playButtonrow])
}
You can set frame for your uilabel and uibutton, like :
cell.detailTextLabel.frame = CGRectMake(cell.detailTextLabel.frame.origin.x, cell.detailTextLabel.frame.origin.y, self.frame.size.width - playButton.frame.size.with - cell.detailTextLabel.frame.origin.y, cell.detailTextLabel.frame.height)
But, i think you should create a custom uitableviewcell for yourself, in there you can use autolayout, it better

Unexpected behavior when adding sublayer to UICollectionViewCell

In the following minimal example, I create a UICollectionView with five UICollectionViewCells. For each, I create a CALayer with the same frame and set its backgroundColor property and add it as a sublayer to the UICollectionViewCell's layer property. The cells initially on screen are set as expected, but the remaining cells may be the wrong color, and may disappear before entirely off screen when scrolling. This question [1] suggests that this is happening because the cells are not initially on screen (?), but I don't see from the answers how to fix the problem.
Below is a minimal working example. A few things I've tried are commented out:
Set the cell's background color directly, to make sure this isn't a problem with the way I set up the collection view (it isn't).
Calling setNeedsDisplay() (has no effect).
Removing the cell's layer's sublayers (crashes when scrolling).
import Foundation
import UIKit
enum Colors: Int {
case Red
case Orange
case Yellow
case Green
case Blue
}
class TestViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var collectionView = UICollectionView(frame: CGRect(x: 100, y: 100, width: 100, height: 100), collectionViewLayout: UICollectionViewFlowLayout())
let reuseIdentifier = "ColorCell"
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.dataSource = self
self.collectionView.delegate = self
self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "ColorCell")
self.view.addSubview(self.collectionView)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: UICollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(self.reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
var l = CALayer()
l.frame = cell.frame
l.delegate = self
if let color = Colors(rawValue: indexPath.item) {
switch color {
case .Red:
l.backgroundColor = UIColor.redColor().CGColor
// cell.backgroundColor = UIColor.redColor()
case .Orange:
l.backgroundColor = UIColor.orangeColor().CGColor
// cell.backgroundColor = UIColor.orangeColor()
case .Yellow:
l.backgroundColor = UIColor.yellowColor().CGColor
// cell.backgroundColor = UIColor.yellowColor()
case .Green:
l.backgroundColor = UIColor.greenColor().CGColor
// cell.backgroundColor = UIColor.greenColor()
case .Blue:
l.backgroundColor = UIColor.blueColor().CGColor
// cell.backgroundColor = UIColor.blueColor()
}
} else {
l.backgroundColor = UIColor.blackColor().CGColor
// cell.backgroundColor = UIColor.redColor()
}
// for sub in cell.layer.sublayers {
// sub.removeFromSuperlayer()
// }
cell.layer.addSublayer(l)
// cell.setNeedsDisplay()
return cell
}
}
[1] CALayer delegate method drawLayer not getting called
The main problem is that you should set the layer's frame to the cell's bounds, not its frame. Another problem, though, is that you will be adding additional layers when you scroll and cells are reused, since you add a sublayer every time cellForItemAtIndexPath is called. To fix those problems, I would create a subclass of UICollectionViewCell, and add and size the layer there,
class CustomCollectionViewCell: UICollectionViewCell {
var l = CALayer()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
l.frame = self.bounds
layer.addSublayer(l)
}
}
Then, cellForItemAtIndexPath becomes,
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(self.reuseIdentifier, forIndexPath: indexPath) as CustomCollectionViewCell
cell.l.delegate = self
if let color = Colors(rawValue: indexPath.item) {
switch color {
case .Red:
cell.l.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 0.5).CGColor
case .Orange:
cell.l.backgroundColor = UIColor.orangeColor().CGColor
case .Yellow:
cell.l.backgroundColor = UIColor.yellowColor().CGColor
case .Green:
cell.l.backgroundColor = UIColor.greenColor().CGColor
case .Blue:
cell.l.backgroundColor = UIColor.blueColor().CGColor
}
} else {
cell.l.backgroundColor = UIColor.blackColor().CGColor
}
return cell
}
If you do this, be sure to register your custom class instead of UICollectionViewCell in viewDidLoad.

Resources