I have four buttons in a stackView in a collectionViewCell
I am performing segue to a newVC if the button is tapped, the content i am displaying in the newVC is coming via JSON. If the url is empty or url.characters.count == 0 for the respective button, i want to remove it from the cell and resize the rest of the buttons equally in the cell. How can i achieve that.
With UIStackView it is very simple. Just mark the button as hidden and the UIStackView will resize itself.
func buttonTapped(_ button: UIButton) {
button.isHidden = shouldHideButton()
performSegue(withIdentifier: "YourSegueIdentifier", sender: self)
}
func shouldHideButton() {
...
}
Also as venkat mentioned you can use removeArrangedSubview(_:) instead of just hiding, which will remove the button permanently.
I recommand you to read UIStackView documentation.
Since you're working in a StackView, the other items inside it will automatically adjust when we hide your UIButton.
In order to hide you UIButton based on your URL's character count, we can do the following:
button.isHidden = url.characters.count == 0
To simplify even further, we can just check for .isEmpty like so:
button.isHidden = url.isEmpty
Related
Requirement:
I should be able to scroll entire view if left view is visible or not (all components should scroll at a time if i scroll anywhere with in the view).
By clicking on show/hide left view button button it should be able to hide or show left view.
In cell (only cell not left view) there is a expand/collapse functionality (i can increase/decrease cell height)
And If i change font size in device settings app, it should be effect here also(So supporting dynamic font size)
What i have tried:
I have tried with tableview, scroll view but no luck. Finally want to try with collection view, can any one please help me out how to proceed with collection view. And in future do we get any complications if we use collection view.
Best Approach.
Your UI hierarchy should be like this.
StackView
CollectionView
TableView
Note: You can take both CollectionView or TableView but I prefer both different so that I don't need to put condition in delegates & datasource and I can manage easily. Choice is your's what you like to prefer.
Now your UI design looks like this
Green color button is used to show hide your left collectionview (you mentioned in your post).
Set your datas in CollectionView and TableView as per your requirement.
To toggle left menu, just use below one line code on greenButton action.
#IBAction func btnToggle(_ sender: Any) {
colView.isHidden = !colView.isHidden
}
For simple animation
#IBAction func btnToggle(_ sender: Any) {
UIView.animate(withDuration: 0.3) {
self.colView.isHidden = !self.colView.isHidden
}
}
Output:
Edit
You can take stackView in scrollview and turn off colview, tblView scrolling. Check below :
UI heirarchy
Additional code work
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
colView.isScrollEnabled = false
tblView.isScrollEnabled = false
colView.reloadData()
tblView.reloadData()
scrollView.contentSize = CGSize(width: self.view.frame.width,
height: max(colView.contentSize.height, tblView.contentSize.height))
stackHeight.constant = scrollView.contentSize.height
}
Note : It may cause some unexpected output (can be / can not be), so you need to take care of it.
Output:
What you need is UICollectionView with custom layout. You can achieve the effect you need using this approach.
There is tone of tutorials how to implement own custom layout.
Here is one of them
I have a UITableView with dynamically populated rows, but also there's a section at the top that contains one special cell (with a different identifier) which is always the same.
I've added two buttons to this cell and they do work, however they react poorly. That is, the highlighting occurs only after about 0.25s.
I'm using the following slightly customized button:
import UIKit
class HighlightingButton: UIButton {
override var isHighlighted: Bool {
didSet {
if isHighlighted {
backgroundColor = UIColor.lightGray
} else {
backgroundColor = UIColor.white
}
}
}
}
It's important that the user gets a clear feedback that they tapped the button. However with the slow highlighting this isn't satisfying, although the events seem to be triggered quickly (juding by printing some output).
In a normal view this HighlightingButton works as expected and the highlighting flashes as quickly as I can tap.
Is there something in the event handling of the UITableViewCell that leads to this slowness?
Update
I created a minimalistic example project that demonstrates the problem.
There aren't any GestureRecognizers and still there's this very noticable delay.
Take a look at delaysContentTouches property of UIScrollView.
I fixed your problem by setting it to false on tableView and all of it's scrollview subviews.
So you should just add a tableView IBOutlet and override viewDidLoad method like this:
override func viewDidLoad() {
super.viewDidLoad()
tableView.delaysContentTouches = false
for case let subview as UIScrollView in tableView.subviews {
subview.delaysContentTouches = false
}
}
I have a UIButton at the bottom layer of the UIViewController.
And I have a UITableView (full screen size) on top of the UIButton, the UITableView has a header (UIView) which has a transparent background which could be able to see through and show the UIButton.
The UIButton is not clickable even when the button appear behind the tableview header.
My tableView's cell and the header of the tableView has buttons on it, so I could not set headerView.userInteraction = true or tableView.userInteraction = true
I have tried to use pointInside:withEvent: and hitTest:withEvent:, UIButton is still not clickable in both cases.
Any suggestions? Thanks
You could use UITapGestureRecognizer for example like this:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
...
let headerViewGesture = UITapGestureRecognizer(target:self, action:#selector(MyClass.headerViewTap(_:)))
headerView.addGestureRecognizer(mainViewGesture)
...
}
func headerViewTap(recognizer: UITapGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.Recognized
{
let touchLocation = recognizer.locationInView(recognizer.view)
print(touchLocation)
if CGRectContainsPoint(myButton.frame, touchLocation) {
print("button was touched")
}
}
}
Please try bringSubviewToFront to get the button clickable.
self.view.bringSubviewToFront(yourButtton)
Or you can check it in storyboard whether the button is inside some view, And add make sure the button is placed properly in storyboard. The button should be below the table view like in the sample picture.
You can try both the ways and let me know if you have any doubt.
I have a UIButton that is within a nested scrollview (a vertically paged scrollview inside a horizontally paged scrollview). My problem is when I tap the button it highlights but it does not trigger a segue that I have it linked to. I then tried to link it to an IBAction function where I placed a breakpoint and when I tapped the button I did not hit that breakpoint, so my button is also not triggering IBActions either.
I've tried turning off delays content touches for both scrollviews and that didn't work. All that did was make the button highlight as soon as I tapped it rather than weighting a little bit before highlighting. Either way, my button highlights when I tap it but none of my outlets (segues or IBActions) are triggering which I thought was very strange. I've found other people online with similar issues but their buttons didn't even highlight. Mine highlights so I know its getting input from the user.
Here is how I am instantiating the nested scrollview. The main horizontal scrollview is created in my storyboard then in its ViewController viewDidLoad method I do this to nest the vertical scrollview. The vertical scrollview is what contains my button.
let readingVC = storyboard!.instantiateViewControllerWithIdentifier("ReadingViewController") as! ReadingRingViewController
readingVC.read = reading.minutesRead
readingVC.goal = reading.minutesGoal
readingVC.selectedDate = selectedDate
readingVC.today = today
let readingView = readingVC.view
let scrollPage2 = UIScrollView(frame: CGRectMake(readingView.bounds.size.width,0,readingView.bounds.size.width, readingView.bounds.size.height))
scrollPage2.addSubview(readingView)
scrollPage2.contentSize = CGSize(width: readingView.bounds.size.width, height: readingView.bounds.size.height*2)
scrollPage2.pagingEnabled = true;
scrollPage2.alwaysBounceVertical = true
scrollPage2.userInteractionEnabled = true
let readingBottomView = storyboard!.instantiateViewControllerWithIdentifier("ReadingBottomViewController").view
let scrollPage2Bottom = UIScrollView(frame: CGRectMake(0,readingView.bounds.size.height,readingBottomView.bounds.size.width, readingBottomView.bounds.size.height*2))
scrollPage2Bottom.addSubview(readingBottomView)
scrollPage2Bottom.contentSize = CGSize(width: readingBottomView.bounds.size.width, height: readingBottomView.bounds.size.height)
scrollPage2.addSubview(scrollPage2Bottom)
scrollPage2.sendSubviewToBack(scrollPage2Bottom)
Here is the code for the viewController that my button is in. I've linked it to the IBAction and also linked it to another viewController as a push segue
#IBAction func start(sender: AnyObject) {
var x = 0
var y = 0
x = y + x
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "StartReading" {
let destVC = segue.destinationViewController
}
}
I solved my own question. The reason the button's actions were not working was because I was adding the view the button was in as a subview but forgetting to also add the view controller for the button's view as a subviewcontroller. So I inserted the lines following lines of code after I instantiated readingVC and set its member variables:
self.addChildViewController(readingVC)
readingVC.didMoveToParentViewController(self)
Now the button works exactly as expected
Hello I am developing app which has UI like below images..
I am not able to understand how to create bottom swipe up view.
I have tried swipe up gesture on bottom view to open it.
But I want to open bottom view with finger (means slow upward drag of view should reveal bottom view slowly)
I am using auto layout and storyboard. How do I achieve this ?
I have searched a lot and I got this https://github.com/crocodella/PullableView but I am not able to add this view with storyboard and auto layout.
I Just want say before solution is that this is not gonna be drag like effect for that you need to use gesture...but It gives you similar effect if you strongly need it with button click.. I think its not what you want but this give you an option if you want
For drag bottom view to top,you shold use gesture and this may help you
Drag Down UIView in iOS 5
or this
http://www.jondev.net/articles/Dragging_View_with_Finger_(iPhone)
You got the similar effect using constant property of constraints..like Give the height constraint to bottom view and use constant property on click event to swipe up and down.
Still confused!!! Here is the solution
UI setup
Constraints Setup
After that You just need to make some outlets and click event of button...
make an outlet of height constraint of bottom view
make an outlet of button to change its title to up/down
make and click event of button
After this procedure you need to code on button action, So here is that code
class ViewController: UIViewController {
// Button outlet
#IBOutlet weak var btnUp: UIButton!
// Height Constraint outlet
#IBOutlet weak var constHeightBottomView: NSLayoutConstraint!
// Boolean property to handle click
var clicked = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnUpClicked(sender: UIButton) {
if clicked{
self.clicked = !clicked
UIView.animateWithDuration(0.2, animations: {
self.btnUp.setTitle("Down", forState: .Normal)
self.constHeightBottomView.constant = 200
self.view.layoutIfNeeded()
})
}
else{
self.clicked = true
UIView.animateWithDuration(0.2, animations: {
self.btnUp.setTitle("Up", forState: .Normal)
self.constHeightBottomView.constant = 0
self.view.layoutIfNeeded()
})
}
}
}
and the output of this work would be