My question is :
Why when I build and run the Table View created with different rows don't bounce, although I selected the checkbox Bounces and Bounce Vertically in Xcode 6 ?
By default UIScrollView, which is a superclass of UITableView won't bounce if the content fits within its bounds i.e. if the rows fit within table's bounds.
To alter this behaviour you can set alwaysBounceVertical property to true.
var alwaysBounceVertical: Bool { get set }
If this property is set to true and bounces is true, vertical dragging
is allowed even if the content is smaller than the bounds of the
scroll view. The default value is false.
Try this code:
[eventTable setBounces:NO];
(OR)In Storyboard untick the Bounces.
Related
In my code I have a stack view that initially has 1 element PhoneNumberField. Another PhoneNumberFieldscan be added dynamically in the runtime:
#IBAction func addAlternatePhoneNumberAction(_ sender: UIButton) {
let alternateNumberView = PhoneNumberField()
...
phoneNumberStackView.addArrangedSubview(alternateNumberView)
}
This is what xib for PhoneNumberFieldlooks like:
The problem is that I would like to be able to dynamically hide the 'Name for other phone' field based on the content of 'Mobile combobox'. When I set the 'isHidden' parameter everything works as expected, the only problem is that the PhoneNumberField height stays the same. I would like it to shrink when the 'Name for other phone' field is hidden.
I tried doing it using the outlet for height constant for otherNumberNameField in the PhoneNumberField.swift file but the problem is that in that case all of the PhoneNumberFields in the stack view have the size of the first field.
What would be the correct solution for this?
edit: In addition to the answer below: I had to set the distribution for the phoneNumberStackView to equal spacing. Worked like a charm.
First, create StackView.
Don't set its height constraint, just set top, leading, trailing and bottom constraints.
Bottom constraint set equal to Error label top constraint.
Then set its distribution to Fill Equally.
Now put first two Views into one view and put this view together with OtherNumberField view to this StackView.
So now your hierarchy should look like this:
Now when you hide one view from StackView, StackView will be smaller because you didn't set its height.
I tried to set a margin for a certain cell in my TableView by using code as below:
cell.layoutMargin.left = 20
However, when I launched the application, it changes nothing on the appearance. Is there any way I could achieve this?
For margins to take effect in any UIView, any constraints must have the "Constrain to margins" checked. Otherwise, the margins will not change any subview's constraints on the superview.
If you are adding constraints with Swift, here is an example of adding constraints relative to margins from Apple. The key part is:
// Get the superview's layout
let margins = view.layoutMarginsGuide
// Pin the leading edge of myView to the margin's leading edge
myView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
Ensure that your view is being updated and that any changes you are making to UIView is from the main thread.
To give a more thorough answer, more data is needed on your current auto layout setup.
I found a solution or alternative for this problem after getting help from my colleague, what we did was creating an IBOutlet for the constraint (which I just discover). So in UITableviewCell class, i add this line of code :
#IBOutlet var boxLeadingContraint: NSLayoutConstraint!
And in UITableView I set the margin for the specified cell like this:
cell.boxLeadingContraint.constant = 10
Note: I did this on a UIImageView inside the cell not on the cell itself. Any feedback or advice will be appreciated.
I have a strange problem: in my table view I want to update a single cell when its UISlider gets modified (value changed control event). At the moment the value of the slider changes, I want to animate a button into the cell (sliding in from the right). I set the constant of the button's constraint to -50 to make sure it's not visible by default, and when the slider's value gets changed, a method gets called which updates the table view, so cellForRowAtIndexPath gets called again for all cells in my table. Simplified it looks something like this:
func valueChanged(sender:UISlider) {
// Reload table view
self.myTableView.reloadData()
// Let table view know the value of the slider got modified
self.didChangeValueOfSlider = true
}
And in cellForRowAtIndexPath I'm keeping track of which cell's slider got changed by using a custom selectedCellIndexPath variable. When the table view gets to the cell that got modified: it runs the following code:
// Check if cell is selected
if indexPath == self.selectedCellIndexPath {
// Check if value of slider was changed
if self.didChangeValueOfSlider == true {
// Value was changed: set constraint back to default
saveButtonTrailingConstraint.constant = CGFloat(15)
self.view.setNeedsUpdateConstraints()
self.view.updateConstraintsIfNeeded()
// Reset slider update status
self.didChangeValueOfSlider = false
}
}
Calling those setNeedsUpdateConstraints() and updateConstraintsIfNeeded() might be overkill or unnecessary, but please note this is my 15th attempt or so to actually get the view to display the updated layout. I used breakpoints to confirm the constant actually changes, after the code above is finished running and everything works perfectly fine. The only thing I can't get working is the updating part. I've tried UIView.animateWithDuration to animate the change, and I've tried methods like layoutIfNeeded() and beginUpdates() and endUpdates of the table view: nothing works. What could be the reason the layout doesn't get updated? And what am I supposed to be calling the layout and update methods on? I've been calling them on self.view but I'm not even sure if you're supposed to be calling it on the view if you're trying to update the layout of a table view cell. Any help would be appreciated.
I figured it out. The problem turned out to be the constraint itself. as I was accessing the wrong one. I defined it as saveButtonTrailingConstraint but I was actually modifying was the saveButton's width constraint (which apparently can't be animated). Instead of accessing saveButton.constraints[indexOfTrailingConstraint] I should have defined saveButton.superview!.constraints[indexOfTrailingConstraint] as the constraint belongs to the superview and not to the button itself. I guess the best thing to take away from this clumsy mistake is to always double-check if you're modifying the correct constraint if you're doing it programmatically, because it doesn't always show on the first eye.
I'd like to perform an interactive gesture-based animation with my views that requires moving a view which is centered in the screen to the top-left corner of the screen. I can't seem to interpolate between the position of two different x/y constraints (only changing the constant), so as an alternative, I thought perhaps I could lay out the views in my storyboard, then animate them by changing the frame directly. Is there a good way to do this, or is it a bad idea?
You don't need to remove them! Just deactivate them is enough.
If you have seen the docs, you should know that the constraints property of a UIView returns the constraints that it has as a [NSLayoutConstraint]. You just need to loop through this array and deactivate all the constraints!
for constraint in someView.constraints {
constraint.active = false
}
Or using forEach:
someView.constraints.forEach { $0.active = false }
The advantage of deactivating constraints instead of removing them is that you can activate them again easily when you need it.
If I were you I would choose to animate constraint instead. Even if you cannot change the constraint constant for some reason, you can still remove the previous contraint and add a new one.
To do so you'll need to :
Keep a reference to the constraint you want to change
remove it from the view
set the new constraint and add it to the view
keep the reference of that new constraint
Animate with :
UIView.animateWithDuration(0.5) {
self.view.layoutIfNeeded()
}
I need to set custom section height for my table view, and I'm trying to do it in pretty straightforward way by calling some delegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 39.0;
}
I do get desired result - a taller section but I'v noticed one problem. When I tap the table (start dragging), move my finger up to top, and release the table, then the table bounces back but does not return to the correct initial place. If What I mean is the section header overlaps the first row. Here is the screen:
Any ideas why this happens or what workarounds exist?
UPDATE: I also tried increasing section height property of the tableView in IB. This increases the height but the same problem exist.
It sounds like you're dragging the table up so that the last row of the table, plus empty space below it, is showing, like this:
When you let go, it slides the table back down so that bottom edge of the last table row is flush against the bottom edge of the view.
This is the expected behavior for a table view. You're seeing the top row slip partly underneath your section header because the view height, minus the section header height, isn't an integer multiple of the row height. If you don't like this, you need to make sure the view height minus the section header height is an integer multiple of the row height.
There is another way to set the section height without using the delegate:
self.tableView.sectionHeaderHeight = 39.0;
If this does not help, you will have to fiddle with the UIScrollView Delegate.
Also, from your screen shot I see that you might be interested in the property tableHeaderView, which is a header above the table that will scroll off-screen when the table view is scrolled.