I'm trying to create a tableview from which i will use the selected cells. The tableview only contains 3 cells in view. If i tap the first/last cell, it will get selected, but if i'm trying to select the cell in the middle it will not select unless pressed in a certain area which is about half a cm of the whole cell in the bottom or top, depending on how scrolled the content is.
Note that allowsMultipleSelection is true and i have overridden the setSelected method in the cell with this one:
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if self.isSelected {
checkImage.isHidden = true
subContentView.backgroundColor = #colorLiteral(red: 0.8979414105, green: 0.8980956078, blue: 0.8979316354, alpha: 1)
} else {
checkImage.isHidden = false
subContentView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}
}
Does anyone have any idea why this might happen?
Nevermind, i solved it. There was a separate view that was covering the tableview exactly in the middle, having the height almost as the height of a cell.
Related
I'm trying to recreate the App Store navigation bar animation. What I'm currently doing is adjusting the alpha of the navigation bar based on the scroll position.
The issue is that when you slide back the navigation bar does not appear in the previous view so I set the alpha back to one in viewWillDissapear (which doesn't work the best as seen in the gif).
With regards to the back button, if you change the alpha of the navigation bar the back button is also affected. Apple has a different back button (the circle with the arrow) when the navigation bar is not visible and this button disappears with an animation as the navigation bar appears and the default back button appears. I'm not sure if they're just overlaying a new one.
This question has been asked before but the accepted answer was to make the navigation bar transparent then change it's opacity as you scroll. This doesn't create the same effect as the default navigation bar isn't white but translucent and you also lose the border line at the bottom.
Swift 5
override func viewWillDisappear(_ animated: Bool) {
navigationController?.navigationBar.alpha = 1
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let currentVerticalOffset = scrollView.contentOffset.y
var percentageVerticalOffset = CGFloat() //currentVerticalOffset / maximumVerticalOffset
if currentVerticalOffset > collectionView.frame.size.height {
percentageVerticalOffset = currentVerticalOffset / currentVerticalOffset
self.title = "The Barn Owl"
//self.navigationItem.setHidesBackButton(false, animated: true)
} else {
percentageVerticalOffset = currentVerticalOffset / collectionView.frame.size.height
//self.navigationItem.setHidesBackButton(true, animated: true)
self.title = ""
}
// let color = UIColor.init(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: percentageVerticalOffset)
// navigationController?.navigationBar.backgroundColor = color
navigationController?.navigationBar.alpha = percentageVerticalOffset
}
I have a horizontal CollectionView on top and TableView under it
I want as I scroll TableView my CollectionView should scroll and animate along with to some level I have achieved with scrollItemTo but CollectionView scrolling to slow but I want it working as it is working in uberEats iOS app in restaurant items list details and same is working in urbanClap app
It's like moving a view cell by cell as table view section header reach top
The uber eats app functionality that you're referring works like: whenever a particular section of tableView reaches the top, that particular collectionViewCell is selected.
As evident from the above statement,
number of items in collectionView = number of sections in tableView
You can achieve the solution to this particular problem by tracking the top visible section index of tableView and then selecting the collectionViewCell at that particular index, i.e.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView === self.tableView {
if
let topSectionIndex = self.tableView.indexPathsForVisibleRows?.map({ $0.section }).sorted().first,
let selectedCollectionIndex = self.collectionView.indexPathsForSelectedItems?.first?.row,
selectedCollectionIndex != topSectionIndex {
let indexPath = IndexPath(item: topSectionIndex, section: 0)
self.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
}
}
}
Changing collectionViewCell color on selection:
Create a custom UICollectionViewCell and override **isSelected** property to handle selected and un-selected state, i.e.
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var titleLabel: UILabel!
override var isSelected: Bool {
didSet {
if self.isSelected {
self.contentView.backgroundColor = #colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 1)
} else {
self.contentView.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
}
}
}
}
You won't need to manually update the backgroundColor of cell elsewhere after this.
You can implemement scrollViewDidScroll of UIScrollViewDelegate for your tableView then manually scroll your UICollectionView from there
class XYZ: UIViewController, UIScrollViewDelegate{
func viewDidLoad(){
super.viewDidLoad()
tableView.delegate = self
}
func scrollViewDidScroll(_ scrollView: UIScrollView){
let tableView = scrollView //assuming the only scrollView.delegate you conform to is the tableVeiw
collectionView.contentOffset = someMappingFrom(tableView.contentOffset) //or some other scrolling mechanism (scrollToItem)
}
}
You need to change selection on scrollViewDidScroll.
I've attached the link to repo for the same code
Github Repo for solution
I have a tableview with multiple cells. Each one contains an image and a label in the center. When a user presses on a cell, I want it to become slightly darker so the user knows that they are pressing on the cell.
Please take button in above of imageview with same size as cell. Just drag outlet and action of it. Use this code on button to manage selection and unselection.
Selection:
sender.backgroundColor = UIColor.black.withAlphaComponent(0.35)
Unselection:
sender.backgroundColor = UIColor.black.withAlphaComponent(0.0)
Happy Coding
If you want to slightly darken the cell and highlight it check the property in UITaleView that's called, isUserInteractionEnabled.
This behavior is already implemented by default in the UITableViewCell, however if that's not what you're looking for you can implement didSelectRowAt delegate function and do whatever you want on that cell, or you can use didHighlightRowAt.
You can read a lot about those functions online here is an example about implementing the didSelectRowAt.
UPDATE: some work around to manually shows the user what he clicked, inside the didSelectRowAt method add implement this.
let cell = (tableView.cellForItem(at: indexPath) as! MyCustomCell)
UIView.animate(withDuration: 0.4) {
cell.imageView.highlightedImage = cell.imageView.image?.withRenderingMode(.alwaysTemplate)
cell.imageView.tintColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 0.3)
UIView.animate(withDuration: 0.4, animations: {
talbeView.deselectItem(at: indexPath, animated: true)
})
}
This will manually cover the image inside the image view with the tint color you set in this case is black with opacity of 0.3.
And then deselect the cell, all of this wrapped in a 0.4 animation time.
I'm experiencing a weird issue with my Swift app. I'm trying to create a UITableViewCell using a custom cell that I have created.
I have an empty label and a text label in the cell. The empty label is simply colored by setting the backgroundColor against some R, G, B colors.
However, when I select and deselect rows in my table, the background color of the label disappears. This happens until I scroll the cell out of view and back into view again, at which it shows me the color again.
Here's a few screenshot to illustrate what's happening:
This is what it looks like before selecting a color
This is what it looks like when I have a color selected - it seems to change the label background color to transparent. It shouldn't do this
This is what it looks like when I have selected a different color - the color remains transparent/white
Of course, I don't want this to happen. The intention was for the label color to remain the same.
Here's my code for cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! ScenesTableCell
cell.sceneNameLabel.text = scenesArr[indexPath.row].sceneName
let red = scenesArr[indexPath.row].sceneCol[0]
let green = scenesArr[indexPath.row].sceneCol[1]
let blue = scenesArr[indexPath.row].sceneCol[2]
let brightness = scenesArr[indexPath.row].sceneBrightnessMultiplier
cell.colourIndicatorLabel.layer.backgroundColor = UIColor(red: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue), alpha: CGFloat(brightness)).CGColor
cell.colourIndicatorLabel.layer.cornerRadius = 5
cell.colourIndicatorLabel.layer.borderWidth = 1
cell.colourIndicatorLabel.layer.borderColor = UIColor(red: 77.0/255.0, green: 146.0/255.0, blue: 203.0/255.0, alpha: 1.0).CGColor
}
Please note that I have tried the following line of code to change the backgroundColor too, however the same thing happens, but it fills outside of the rounded borders:
cell.colourIndicatorLabel.backgroundColor = UIColor(red: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue), alpha: CGFloat(brightness))
I really appreciate some help here! I know I'm not very good at asking questions on SO, so if you have any questions, please ask! ;)
iOS clears the background colour of all cell subviews when a cell is selected. You can avoid this by overriding the setSelected method on your UITableViewCell subclass:
extension ScenesTableCell {
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.colourIndicatorLabel.backgroundColor = .blue // Set with the color you need
}
}
In order to use rounded corners and UIView.backgroundColor without overflow, you can set cell.colourIndicatorLabel.clipsToBounds = true when you dequeue the cell or in the cell subclass.
I am trying to implement UINavigationBar that changes its transparency when scrolling UITableView. At the beginning, the navigation bar should have transparent background, so the content below it should be visible (there will be an image displayed, for the example I am using solid color):
When user scrolls table view, transparency should be replaced with solid color:
Table view will contain section headers, that should act like when using non-translucent navigation bar. The header views should "stick" to navigation bar once they "touch" it from the bottom:
I have no luck with trying to implement this flow in iOS app.
For the initial state, I am setting UINavigationBar translucent property to YES, and both backgroundColor and barTintColor to clear color, which gives me what I want.
Then, when user scrolls table view, I am updating the backgroundColor and barTintColor to a color with given alpha component, computed basing on current scroll offset. I am using scrollViewDidScroll: from UIScrollViewDelegate protocol to do so. However, it changes only the background of navigation bar, leaving status bar background transparent, which is not what I want.
I can't find another way of making UINavigationBar transparent without setting translucent property to YES. Unfortunately, this changes how the section headers acts when scrolling. As navigation bar is translucent, section header views hides below it when they should "stick" to the bar like on third screenshot above.
I would appreciate any help and hints how to achieve navigation bar that acts like described or similar in Objective-C or Swift.
Assuming that you have a reference to the view above the tableView and that you don't want to interact anything in it:
var overlayView:UIView!
var offsetDenominator:CGFloat!
let TARGER_COLOR = UIColor.blackColor()
override func viewDidLoad() {
super.viewDidLoad()
if let navCtrl = self.navigationController {
self.offsetDenominator = headerView.frame.size.height - navCtrl.navigationBar.frame.height
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: 0.0)
self.overlayView = UIView(frame: self.headerView.frame)
self.overlayView.backgroundColor = overlayColor
self.view.addSubview(self.overlayView)
}
...
override func scrollViewDidScroll(scrollView: UIScrollView) {
if let navCtrl = self.navigationController, let breakpoint = offsetDenominator {
let alpha = scrollView.contentOffset.y / breakpoint
if alpha >= 1.0 {
navCtrl.navigationBar.backgroundColor = self.TARGER_COLOR
} else {
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: alpha)
self.overlayView.backgroundColor = overlayColor
navCtrl.navigationBar.backgroundColor = UIColor.clearColor()
}
}
}
My approach is:
override func viewDidLoad() {
super.viewDidLoad()
...
self.setNavbarTransculent()
}
private func setNavbarTransculent() {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let denominator: CGFloat = 50 //your offset treshold
let alpha = min(1, scrollView.contentOffset.y / denominator)
self.setNavbar(backgroundColorAlpha: alpha)
}
private func setNavbar(backgroundColorAlpha alpha: CGFloat) {
let newColor = UIColor(red: 1, green: 1, blue: 1, alpha: alpha) //your color
self.navigationController?.navigationBar.backgroundColor = newColor
UIApplication.shared.statusView?.backgroundColor = newColor
}
extension UIApplication {
var statusView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
Swift3
var navAlpha = // Your appropriate calculation
self.navigationController!.navigationBar.backgroundColor = UIColor.red.withAlphaComponent(navAlpha)