Adding gradient to scrolling UITableView - ios

I was able to add a gradient my UITableView, but I have the issue of when I have to scroll through my cells, the gradient background scrolls along also. I want the background to stay consistent as I scroll up or down. How can I achieve this? Do I have to create a custom UITableView in order to do this?
The pictures below show what it currently looks like.
Here is my code for adding the gradient to the UITableView:
func addGradientToBackground(){
var gradient : CAGradientLayer = CAGradientLayer()
gradient.frame = self.tableView.bounds
gradient.colors = [UIColor.blueColor().CGColor, UIColor.redColor().CGColor]
self.tableView.layer.insertSublayer(gradient, atIndex: 0)
}
Messing around will setting the gradient doesn't work either, like setting:
self.view.layer.insertSublayer(gradient, atIndex: 0)
or changing the bounds:
gradient.frame = self.tableView.frame
Also, in cellForRowAtIndexPath I set the UITableViewCells background color to clear:
cell.backgroundColor = UIColor.clearColor()
I can't add images, but here is the link if you wish to see them: http://imgur.com/Vtka1tO,6faLMkr#0

The gradient needs to be behind the table view if you don't want it to scroll. If you're using a UITableViewController, the only thing behind is the window, so you could give it the gradient, and make the cells and the table view have a clear background color. If you're using a UIViewController with a table view as a subview, then you could give the controller's main view a gradient background color.

Have you thought to add a background image as follows?
var imageView = UIImageView(frame: CGRectMake(10, 10, cell.frame.width - 10, cell.frame.height - 10))
let image = UIImage(named: ImageNames[indexPath.row])
imageView.image = image
cell.backgroundView = UIView()
cell.backgroundView.addSubview(imageView)

Related

Adding an overlay view to UICollectionViewCell - keeps overlaying

I'm trying to add a 50% black alpha view on every collection view cell. The collection view cells have a background photograph and text on top. Would like the overlay view to be in between the two.
In my cellForItemAt method, I use the following:
let overlayView = UIView()
overlayView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
overlayView.frame = cell.bounds
cell.addSubview(overlayView)
The problem is as i scroll down, then up, the overlay keeps adding, making the alpha much darker than 50%. Additionally, the overlayView is being added on top of my text (I need it below the text.)
How can I prevent the overlay from adding multiple times, and adding it in between the correct layers of the cell?
UITableView has a method of reusing cells to make it more efficient (keeping only the required cells in memory). Because of this the reused cell may already have this subview, so calling addSubview again causes another view to be added on top of it.
Here is how to solve this:
Move addSubview(overlayView) to the layoutSubviews() method inside your cell subclass.
override func layoutSubviews() {
super.layoutSubviews()
addSubview(overlayView)
}
Remove the overlay view in the prepareForReuse() method inside your cell subclass.
override func prepareForReuse() {
super.prepareForReuse()
overlayView.removeFromSuperview()
}
Note that this requires you to define the overlay view in the cell's subclass (which you should probably do since the cell itself should be responsible for its own subviews).
This happens because your cells are dequeued and reused multiple times, therefore, you are adding multiple layers.
Put this code inside your cell's class
override func awakeFromNib() {
super.awakeFromNib()
let overlayView = UIView()
overlayView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
overlayView.frame = self.bounds
self.addSubview(overlayView)
}
Or if you want to achieve the same result you can set black backgroundColor and set imageView's alpha to 50%
cell.backgroundColor = .black
cell.imageView.alpha = 0.5
Avoid adding this in cellForItem. The cells are reused, hence if you keep adding the view it would add one top of another. On reusing the cell the previously added view is not removed. Instead you can add the view in Prototype cell or XIB and set its alpha to whatever you want. Or if you are creating the cell programatically you can it in awakeFromNib()

Text disappearing when I add gradient background to UIPicker in Swift 3

I am trying to add a gradient background to my picker in the same way that I have added a gradient background to my VC.
When I do this via the code below, the gradient is added but the text disappears from view. Although the picker still behaves as if the text is there.
My guess is it's something to do with the .insertSublayer placing the gradient background over the top off the text.
override func viewDidLoad() {
let background = CAGradientLayer().bespokeColor()
background.frame = self.view.bounds
self.view.layer.insertSublayer(background, at: 0)
let pickerBackground = CAGradientLayer().bespokeColor()
pickerBackground.frame = self.Picker.bounds
self.Picker.layer.insertSublayer(pickerBackground, at: 0)
}
How do I get around this?

Gradient at Top/Bot of Scrollview When There's Additional Content

I have a scrollview>ContentView>TextLabel setup where the gradient is showing up but not working how I want it to. It's a clear background scrollView, so all I'm looking for is a clear gradient mask over the text. I found something similar to I'm looking for in Objective-C but that thread doesn't have a Swift solution.
My end goal seems like something most people might use, so I'm surprised there's not a Swift version yet. The functionality I'm trying to code is:
Sometimes the text will fit perfectly in the scrollView's fixed size so there should be no gradient.
When the text is longer than can fit and so some of it is below the scrollView's bottom cutoff, the bottom of the view should fade to clear.
Once the user scrolls down and the top should fade, indicating that there's more above.
I tried this code to handle bullet #2:
let gradient = CAGradientLayer()
gradient.frame = self.bio_ScrollView.superview!.bounds ?? CGRectNull
gradient.colors = [UIColor.whiteColor().CGColor, UIColor.clearColor().CGColor]
//gradient.locations = [0, 0.15, 0.25, 0.75, 0.85, 1.0]
gradient.locations = [0.6, 1.0]
self.bio_ScrollView.superview!.layer.mask = gradient
But it fades everything, including the button below it, which is clearly not in the scrollview:
If I remove the .superview and apply it directly to the scrollView, it just fades all the text below the initial part that was visible:
Does anyone know anything about how to implement this correctly?
Figured it out. First, make sure you've added the right view hierarchy. The scroll view needs to be embedded in a container view (which is what the gradient will be applied to):
Top/container view: Set this up however you want
Scrollview: Pin all edges to container (4 total constraints)
Scrollview content view: Pin edges + Center X (5 total constraints)
Label: Pin edges (4 total constraints)
Add "scrollViewDelegate" to the ViewController class:
class ViewController_WithScrollView: UIViewController, UIScrollViewDelegate {
....
Connect the four views listed above with IBOutlets. Then, set your scrollView delegate within the viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
yourScrollView.delegate = self
//+All your other viewDidLoad stuff
}
Then implement the scrollViewDidScroll func, which will run automatically thanks to the work you did above.
func scrollViewDidScroll (scrollView: UIScrollView) {
if scrollView.isAtTop {
self.applyGradient_To("Bot")
} else if scrollView.isAtBottom {
self.applyGradient_To("Top")
} else {
self.applyGradient_To("Both")
}
}
Then add this magical gradient code:
func applyGradient_To (state: String) {
let gradient = CAGradientLayer()
gradient.frame = self.yourScrollView.superview!.bounds ?? CGRectNull
switch state {
case "Top":
gradient.colors = [UIColor.clearColor().CGColor,UIColor.whiteColor().CGColor]
gradient.locations = [0.0,0.2]
case "Bot":
gradient.colors = [UIColor.whiteColor().CGColor, UIColor.clearColor().CGColor]
gradient.locations = [0.8,1.0]
default:
gradient.colors = [UIColor.clearColor().CGColor,UIColor.whiteColor().CGColor,UIColor.whiteColor().CGColor, UIColor.clearColor().CGColor]
gradient.locations = [0.0,0.2,0.8,1.0]
}
self.yourScrollView.superview!.layer.mask = nil
self.yourScrollView.superview!.layer.mask = gradient
}
That should do it!

UITableViewController Blur Background Not Showing With Scroll

I have set a background image for my UITableViewController and then added a blur effect with the following code:
var blur = UIBlurEffect(style: UIBlurEffectStyle.Dark)
var blurView = UIVisualEffectView(effect: blur)
blurView.frame = self.view.bounds
self.view.insertSubview(blurView, atIndex: 0)
When I scroll down, the background image is still there but the blur effect is only there for the first few cells that fit into the view at a time. How can I make it so the blur effect is there as I scroll?
I tried adding the blur effect to each cell, but that makes it look really weird.
For UITableViewControllers self.view is the UITableView it self. That means any subview you add to self.view will scroll along with the content of the table view.
You could either make an own UIViewController, set up UITableView manually and place it in front of the blur view (instead of placing the blur view inside the table view) or you could move the blur view's location when the table view is scrolled.
To move the blur view to compensate for the table view's offset you can do something like this:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var blurViewFrame = CGRect()
blurViewFrame.size = view.bounds.size
blurViewFrame.y = tableView.contentOffset.y
blurView.frame = blurViewFrame
}

Removing shadow from single subview in UIView with shadow

Context:
In order to get a shadow on all my tableview cells I have added a shadow to my transparent table view. This to avoid shadows from separate cells falling onto other cells. However, this also means everything in the table view gets a shadow. As I want to have a shadowless remove button appear without shadow when the cell is swiped to the right, I was wondering:
Question:
Can I eliminate the shadow from one specific subview in a UIView with a shadow?
Specifically without having to take it out of the table view in this case. I like to keep it in the tableview so that it scrolls with the table view.
Adding shadow to tableView
self.tableView.clipsToBounds = false
self.tableView.layer.shadowOffset = CGSizeMake(5,5)
self.tableView.layer.shadowColor = UIColor.blackColor().CGColor
self.tableView.layer.shadowRadius = 5
self.tableView.layer.shadowOpacity = 1
and then when the cell is swiped away I simply add the button
let cellFrame = tableView.rectForRowAtIndexPath(indexPath)
var buttonFrame = CGRectInset(cellFrame,10,8)
buttonFrame.size.width = 150
let buttonView = UIButton(frame: buttonFrame)
buttonView.setTitle("Remove", forState: UIControlState.Normal)
buttonView.backgroundColor = UIColor.redColor()
tableView.insertSubview(buttonView, atIndex: 0)
//some animation to move the cell out of the way

Resources