Apply vertical alpha gradient to UITableView
You should mask the superview
, not the view itself.
Here's an example:
let gradient = CAGradientLayer()
gradient.frame = tableView.superview?.bounds ?? .null
gradient.colors = [UIColor.clear.cgColor, UIColor.clear.cgColor, UIColor.black.cgColor, UIColor.black.cgColor, UIColor.clear.cgColor, UIColor.clear.cgColor]
gradient.locations = [0.0, 0.15, 0.25, 0.75, 0.85, 1.0]
tableView.superview?.layer.mask = gradient
tableView.backgroundColor = .clear
Result:
You can change the orientation by changing the startPoint
and endpoint
properties. The default values (vertically) are (0.5, 0.0) and (0.5, 1) respectively. Point (0,0) is the bottom-left corner of the layer and (1,1) is the top-right corner. For example, if you want to apply that mask horizontally instead of vertically, just do:
gradient.startPoint = .init(x: 0.0, y: 0.5)
gradient.endPoint = .init(x: 1.0, y: 0.5)
One more thing: if you're using AutoLayout, then you need to update the layer with the correct CGRect
value. I usually override layoutSubviews()
method to update it like gradient.frame = tableView.superview?.bounds ?? .null
.
Vertical Alpha Gradient without the use of color in iOS
Answered previously here:
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.tableView.superview.bounds;
gradient.colors = @[(id)[UIColor clearColor].CGColor, (id)[UIColor blackColor].CGColor, (id)[UIColor blackColor].CGColor, (id)[UIColor clearColor].CGColor];
gradient.locations = @[@0.0, @0.03, @0.97, @1.0];
self.tableView.superview.layer.mask = gradient;
For more information, check out the original link.
How can I set UITableView's section's header gradient (and transparent) background in Xcode?
1. Use ViewForHeaderInSection as below:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = self.getGradientBackgroundView()
// Add any title to the Header if needed
let label = UILabel()
label.frame = CGRect.init(x: 5, y: 5, width: headerView.frame.width-10, height: headerView.frame.height-10)
label.text = "My header"
headerView.addSubview(label)
return headerView
}
2. Set Height of the header using heightForHeaderInSection:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50 //whatever height you needed.
}
3. To get the gradient BG Header View
private func getGradientBackgroundView() -> UIView {
let gradientBackgroundView = UIView()
// Prepare Gradient Layer
let gradientLayer = CAGradientLayer()
gradientLayer.frame.size = CGSize(width: self.myTableView.frame.size.width, height: 50) // height same as in heightForHeaderInSection
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.colors = [UIColor.blue.cgColor, UIColor.green.cgColor]
// Add layer to view
gradientBackgroundView.layer.addSublayer(gradientLayer)
return gradientBackgroundView
}
Hope this helps!!
UITableViewCell background gradient not working at first render
The problem is this line:
gradient.frame = gradientLayerView.bounds
At the time this code runs in cellForRowAt
, your gradientLayerView
has not yet been fully laid out, so its bounds
are not yet known. Thus, you are saddling your gradient
with a frame
which will not fit its view after layout does take place.
I think you can solve the problem by moving the call to cell.setData
to tableView(_:willDisplay:forRowAt:)
, at which point the cell size should be known.
And also how can I remove gradient from layer for next usage of cells?
Well, the problem here is that your condition has no alternative:
if data.userUniqueId != nil && userUIID != nil && data.userUniqueId! == userUIID!
The question is: what if not? In that case, if the gradient layer has been added, it needs to be removed. You have provided no logic for that situation. — Also you need to be careful because what if the gradient layer has been added and your logic now causes you to add another gradient layer? Basically your whole approach fails to take account of the most fundamental fact about table view cells, namely that they are reused.
How to add a gradient shadow to tableView cell similar to Apple Health app?
I believe instead of casting a "gradient shadow" across the bottom of the cell, you just want the cell to have a background gradient from a lighter color on the top to a darker color in the bottom.
I usually use en extension of UIView
for adding gradients to views:
extension UIView {
func setGradient(colors: [CGColor]) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = colors
self.layer.insertSublayer(gradient, at: 0)
}
}
Then, try using something like this in your code:
myCell.setGradient([cgColorLight, cgColorDark])
This sometimes doesn't work if you do some custom drawing in your view's layers, but I believe it should be okay for your needs.
UITableViewCell with gradient not working until first reuse of cell
Option 1: Call your addGradient()
from tableview's willDisplayCell
delegate method.
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell is YourCustomTableViewCell {
(cell as! YourCustomTableViewCell).addGradient()
}
}
Make sure you add the gradient once. Because of the cell reuse addGradient()
may get called several times on the same cell. So better rename your function to addGradientfNeeded()
and adjust its logic accordingly.
Option 2:
Instead of adding your gradient in willDisplay
method, add the gradient view and the layer in the cell (once) and only update the frame of the gradient layer.
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell is YourCustomTableViewCell {
(cell as! YourCustomTableViewCell).updateGradientLayerFrame()
}
}
Option 3:
Create a GradientView
class and add it either in the interface builder or programatically to your cell, the gradient will resize as the view's frame changes:
public class GradientView: UIView {
private var gradientLayer: CAGradientLayer?
override public func layoutSubviews() {
super.layoutSubviews()
guard gradientLayer == nil else {
gradientLayer?.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
return
}
gradientLayer = CAGradientLayer()
gradientLayer!.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
gradientLayer!.colors = [
UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
]
gradientLayer!.locations = [0, 1]
gradientLayer!.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer!.endPoint = CGPoint(x: 0.5, y: 1)
self.layer.addSublayer(gradientLayer!)
}
}
set horizontal gradient in UITableviewcell swift
Instead of using frame
, use bounds
of the cell, Also insertSublayer
at index 0, so it will come behind all other layers including your label
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
cell.layer.insertSublayer(gradient(cell.bounds), atIndex:0)
cell.backgroundColor = UIColor.clearColor()
cell.textLabel?.textColor = UIColor(red:0, green:0.102, blue: 0.2, alpha: 1)
}
How to change the background color of UITableViewController to gradient color on swift 3
I created a new project with a table view controller that contains exactly your code. All I had to do was make the cells transparent, too, just like the post you linked to said. It worked, so this made me curious. You did not show what primaryColor
and secondaryColor
are.
Note that you need to use CGColor
s in gradient.colors
. I just tried using UIColor
s and the screen was just as black. Try using
gradient.colors = [UIColor.red.cgColor, UIColor.blue.cgColor]
or rather (if they are indeed of type UIColor
)
gradient.colors = [primaryColor.cgColor, secondaryColor.cgColor]
Related Topics
Arkit - Viewport Size VS Real Screen Resolution
Swift Error Handling for Methods That Do Not Throw
Mutable Binding in Swiftui Live Preview
Error: Use of Unresolved Identifier 'Process'
Can the Conversion of a String to Data with Utf-8 Encoding Ever Fail
Implementing a Function with a Default Parameter Defined in a Protocol
Sprite Kit Physicsbody.Resting Behavior
How to Detect Absent Network Connection When Setting Firestore Document
Higher Order Function: "Cannot Invoke 'Map' with an Argument List of Type '((_) -> _)'"
Creating a Countableclosedrange<Character>
Non-Strong References Not Working in Playground
Why Should Not Directly Extend Uiview or Uiviewcontroller
Swift - Avaudioplayer, Sound Doesn't Play Correctly
Nsapplicationdelegate Not Working Without Storyboard
Implementing Nscopying in Swift with Subclasses
How to Limit the Movement of Two Anchored Lines So They Swing Continually Like a Pendulum