How to add padding to searchbar swift ios - ios

I'm trying to shift down my searchbar to align with the bottom of its parent cell in a collection view.
if(searchBarCellId == widgets[indexPath.item]){
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: searchBarCellId, for: indexPath) as! SearchBarCell
cell.backgroundColor = UIColor.white
cell.searchBar.backgroundImage = UIColor.white.image()
cell.searchBar.tintColor = UIColor.gray
let textFieldInsideSearchBar = cell.searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.backgroundColor = UIColor.lightGray
return cell
}
Is there a way to align the searchbar with the bottom cell of the cell programatically?
The custom xib editor does not allow me add constraints.
Updated with the full solution
Added constraint using editor
Edited codes:
if(searchBarCellId == widgets[indexPath.item]){
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: searchBarCellId, for: indexPath) as! SearchBarCell
cell.backgroundColor = UIColor.white
let frameWidth = UIScreen.main.bounds.width
let frameHeight = UIScreen.main.bounds.width*0.2
cell.searchBar.frame=CGRect(x: 0, y: frameHeight*0.47, width: frameWidth*0.7, height: frameHeight*0.5)
cell.searchBar.backgroundImage = UIColor.white.image()
cell.searchBar.tintColor = UIColor.gray
let textFieldInsideSearchBar = cell.searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.backgroundColor = UIColor.lightGray
return cell
}

InterfaceBuilder's .xib editor does indeed let you specify constraints. You need to turn on "Use Auto Layout" in the File Inspector (first tab in the right side pane).
Alternatively, you may set up constraints programmatically.
Edited for more info
How to add a bottom constraint to the search bar:
Select just the search bar. Then tap on the Add New Constraints button at bottom right of the .xib window (it looks like a tie fighter icon). Tap on the thin red line below the center box in the graphic, set the value to something appropriate (probably close to 0) and verify the view you're binding it to by pulling down the popup next to that value. Then tap the Add 1 Constraint button. That should bind the bottom of the search bar to the bottom of its parent view.
So the point is you just want to set up constraints for the search box relative to its immediate parent, which will be the view of the cell in your case, regardless that the xib doesn't know it's going to be for a cell.

Related

How to prevent UITableViewCell from being visually deselected right at tap?

I use the following to set the selected backgroud color of my UITableViewCells:
let backgroundColorView = UIView()
backgroundColorView.backgroundColor = .red
UITableViewCell.appearance().selectedBackgroundView = backgroundColorView
When I tap to select them, the cell briefly flashes red and then return to the backgroundColor I've set.
When I add:
if cell.isSelected
{
cell.backgroundColor = .red
}
to cellForRowAt indexPath, the cell becomes red when I scroll it out of sight and back again.
How can I make sure that the cell remains red immediately after I tap it?
EDIT:
If I add the following code to cellForRowAt, things work as expected:
let backgroundColorView = UIView()
backgroundColorView.backgroundColor = .red
cell.selectedBackgroundView = backgroundColorView
Could be an iOS bug?

How to change iOS button size based on titleLabel length

My buttons don't resize based on the text in their titleLabel. All of the titleLabel text is displayed, but it goes outside the bounds of the button
My buttons are in a stackview in a xib cell. The xib cell also has a label above the stackview.
I have two classes: ViewController (tableview and datasource), ViewCell (button outlets and actions)
ViewController code:
In my cellForRowAt method:
cell.choice1Button.titleLabel?.lineBreakMode = .byWordWrapping
cell.choice2Button.titleLabel?.lineBreakMode = .byWordWrapping
cell.choice3Button.titleLabel?.lineBreakMode = .byWordWrapping
cell.choice1Button.titleLabel?.numberOfLines = 0
cell.choice2Button.titleLabel?.numberOfLines = 0
cell.choice3Button.titleLabel?.numberOfLines = 0
cell.conceptLabel.text = question["concept"]!
cell.choice1Button.setTitle(question["choice1"]!, for: .normal)
cell.choice2Button.setTitle(question["choice2"]!, for: .normal)
cell.choice3Button.setTitle(question["choice3"]!, for: .normal)
cell.mcTableCellDelegate = self
I want the buttons to resize in height and for the text to wrap based on how long the titleLabel text is. Is this a constraints issue?

UITableView called many times when the cell is out of the screen

I have a problem when i use the function tableView. I show you my code :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cardCell", for: indexPath) as! OpsCardCell
cell.workTest(drawCard: .selectOpponent)
return cell
}
In the exemple I have 4 cell and when I scroll in the simulator the cell who are out of the screen and come back, the cell is again called. And since I draw the card dynamically, the card was drawn several times and the shadow I adds too many times. I show you the screen before and after:
after few scroll down and scroll up:
this is because the function tableView called many times the cell [0] and [3]
This is my code to draw the card:
func drawBasiqCard(){
let cardView = UIView()
self.addSubview(cardView)
cardView.frame = CGRect(marginCardWidth,
marginCardHeight,
self.bounds.size.width - (marginCardWidth*2),
self.bounds.size.height - (marginCardHeight*2))
cardView.layer.cornerRadius = 10
let rounding = CGFloat.init(10)
let shadowLayer = CAShapeLayer.init()
shadowLayer.path = UIBezierPath.init(roundedRect: cardView.bounds, cornerRadius: rounding).cgPath
shadowLayer.fillColor = UIColor(rgb: 0xaaccbb).cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowRadius = 5
shadowLayer.shadowOpacity = 0.2
shadowLayer.shadowOffset = CGSize.init(width: 0, height: 0)
cardView.layer.insertSublayer(shadowLayer, at: 0)
}
So my question is, what is wrong with my code? And there is another way to solve my problem ?
thanks to your reply !
You should try to add sublayer at once in your awakefromnib method. Tableviewcell reuse the same cell using cell identifier that why multiple shadows added to your cell.
Your problem is cell recycling. When you scroll, the same cell gets re-used to display data at a different indexPath.
You should create a custom subclass of UITableViewCell. Give it an optional property shadowLayer. In your cellForRow(at:) method, dequeue a cell and cast it to the correct custom class. Then check to see if its shadowLayer property is nil. If it is nil, add a shadow layer. If it's not nil, create a shadow layer and install it in the cell (cell.shadowLayer = shadowLayer).
In you code you have taken new card each time that card drawing method called, so this will work fine for the first time, but after that this will create problem because you haven't removed that view or you have not checked is that card is already added in cell or not.
So you can either remove below line from you code and take one parent view to design your card inside your storyboard or xib, if you are going to design your cell using xib or storyboard.
let cardView = UIView()
Or if you are going to design your cell programatically then first check if that cardview is added in cell or not, and then cardview is not added then add new one else skip that code.
So I add to the top of my class :
private var ShadowLayerCard: CAShapeLayer?
and I compare if the ShadowLayerCard is not nil :
if(self.ShadowLayerCard == nil){
let shadowLayer = CAShapeLayer.init()
self.ShadowLayerCard = shadowLayer
// here I have my code to add the shadowLayer and other parameters of the shadow...
}
this solve my problem, thanks to duncan-c

How do I add an ImageView into a table cell on button click?

I am trying to do something like this:
When the user clicks "Add Page," a new grouping shows up below it. Now, I decided to use Table View cells in order to achieve this. After following various tutorials and looking up similar Q&As, I am able to add cells on button click with UILabel and have the cell height be dynamic depending on the content but now I am trying to figure out how to add ImageViews and place buttons within a cell.
I've created a custom cell class:
class PageCell : UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = UITableViewCellSelectionStyle.none
setupViews()
}
...
... // other random code here
let imgView : UIImageView = {
let imgview = UIImageView()
imgview.frame = CGRect(x: 100, y: 150, width: 150, height: 140)
imgview.tintColor = UIColor(red: 0.73, green: 0.2, blue: 0.3, alpha: 1.0)
imgview.translatesAutoresizingMaskIntoConstraints = false
return imgview
}()
func setupViews() {
addSubview(pageLabel) // the label that I got working
addSubview(imgView) // can't get this working
...
// constraint info here
}
}
And back in my TableViewController:
class TakePhotosVC: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(PageCell.self, forCellReuseIdentifier: "cellID")
}
// return the actual view for the cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let pagecell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! PageCell
// set more stuff here
}
... // more code
}
My issue is that I am trying to get a box showing where the ImageView is that the user can click on to load in a picture. I am unsure how to do that and place all the relevant buttons as well (Trash, X, etc.)
Any help would be greatly appreciated.
EDIT
Okay, I was trying to follow this tutorial and I can't quite get it to work. In my prototype cell, I see this:
But the result is this:
I made the UIImageView have a background so I can see it. I have two constraints for the UIImageView which are: width = 240, height = 128 and two constraints for the Page Label which are: width = 240, height = 21. Two questions: why are my elements not placed correctly even though I have it correctly placed in the Storyboard? And why is the cell height not dynamically resizing to accommodate the elements?
I have these two lines in my viewDidLoad method of the TakePhotosVC but it doesn't seem to do anything.
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 200
If it's relevant, I get this warning when I run the Simulator.
Warning once only: Detected a case where constraints ambiguously
suggest a height of zero for a tableview cell's content view. We're
considering the collapse unintentional and using standard height
instead.
EDIT 2
I got it to work. For any poor souls reading this after me, you have to click on those dotted pink lines in the Constraints window editor and then click "Add X Constraints" in order to get the ImageView to center and stuff.
My issue is that I am trying to get a box showing where the ImageView
is that the user can click on to load in a picture. I am unsure how to
do that and place all the relevant buttons as well (Trash, X, etc.)
I am not sure if I understand you correctly. You have a cell with an UIImageView. But you want to show a box to visually indicate where the user should touch to add an UIImage (?)
Why not simply add a UIButton on top of the UIImageView with the exact same frame size, and on touch, you fire your action to add the image, and once the image is successfully added, you can set the UIButton to hidden.
If the user deletes the image with the trash button, you simply show the UIButton again by hidden = NO.
Other solution:
Add a border to the UIImageView with custom colors and add a UITapGestureRecognizer to fire an action. (Make sure you set the UIImageView to userInteractionEnabled = YES;
You can allso add a Placeholder image to the UIImageView when there is no image set, with your custom design.
The easiest approach would be to use a xib instead of placing the buttons programmatically. To do this, add a new file and select xib. In a xib, you can pre-make a tableviewcell with the image view, and you buttons placed for you already with constraints. Then, you can subclass this table view cell and connect the image view and buttons with ib outlets and ib actions to access the buttons and image view. Then, in your cellForRow function, load the xib like this:
Bundle.main.loadNibNamed("NameOfNib", owner: self, options: nil).first as! NameOfSubclass
I would advise to read more on xibs and nibs.

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