I have a tableView, from storyboard i have dragged a UIView just above cell within tableView.So i want to Hide/Show that view on button Action which is outside tableView. Another thing is when i hide that view on button Action tableView will scroll Up and when i show that view on button Action tableView will scroll down,Anyhelp will be appreciated, thanks in advance
That can be done via two ways.
i) Either you can create a protocol in uitableviewCell class and implement in MasterClas which is having your tableview.
ii) Or you can directly call a function which will hide/show your view in MasterClass(Which is having your tableview) in cell for row at index. Like below
cell.button.addTarget(self, : "MasterClassFunction:", forControlEvents: .touchUpInside)
Both function will work. And for top and down animation. Just calculate your view's height and change Y axis as per your requirement On function call with a animation block.
Hope this will help.
Okay here i am editing my answer for some code reference.
`protocol tableViewCellDelegate {
func buttonAction()
}
#IBOutlet weak var cellButton: UIButton!
in awakefrom nib :
`cell.button.addTarget(self, : "buttonActionCell:", forControlEvents: .touchUpInside)
func buttonActionCell(){
delegate.buttonAction()
}
And in your masterClass assign delegate to controller's reference and call the protocol function in your main class
func buttonAction(){
print("Func called in class file")
}
`
First you need to create an outlet for the height of the UIView that you want to hide. give the vertical spacing of the tableview to zero with that UIView.
Then on the Button action you need to give the code for the height constraint of the UIView to be set to zero.
Related
I have a table view that has a UIImage and some UIButton objects in each TableView cell. When I scroll the table view, it works quite well overall. However, if I touch one of the UIButton items to scroll the table view, the UIButton seems to steal the touches and the table view does not scroll. Instead the UIButton items appears to be selected instead. I would like to be able to scroll the table view even when the user touches buttons when starting to scroll. So, I searched for solutions here, tried the following.
extension UITableView {
override public func touchesShouldCancel(in view: UIView) -> Bool {
print("the touchesShouldCancel function is called.")
if view is UIButton {
return true
}
return super.touchesShouldCancel(in: view)
}
}
However, it doesn't work. The function does not even get called whenever I scroll the table view. What am I missing here? I would greatly appreciate your input. Thanks all.
Subclass UITableView Set tableView canCancelContentTouches to true as per Apple docs
The scroll view does not call this method if the value of the
canCancelContentTouches property is false
class YourTableView:UITableView {
override func awakeFromNib() {
canCancelContentTouches = true
delaysContentTouches = false
}
override func touchesShouldCancel(in view: UIView) -> Bool {
}
}
You need to make a UITableView subclass
class SubTbl:UITableView {
// add your method
}
Then assign it to that table in IB or use it in code
My scenario, I am trying to implement keyboard with toolbar view using Swift. Here, I need to do whenever I click the button need to show keyboard with toolbar view view without using textview or textfield.
Below My code I am using
Simply I drag UIView to the top of the bar of current ViewController
I declared below code for IBOutlet
#IBOutlet private var toolbarView: UIView!
#IBOutlet private var textView: UITextView!
In ViewDidload I used below code
override func viewDidLoad() {
super.viewDidLoad()
textView.inputAccessoryView = toolbarView
}
In Button action now I am calling like below
#IBAction func CircleClick(_ sender: Any) {
self.textView.becomeFirstResponder()
}
You need to define an outlet for textfield for referencing it.
#IBOutlet weak var textfield:UITextField!
You can activate any text field by calling becomeFirstResponder() on the UITextfield object.
textfield.becomeFirstResponder()
You can call this function in the IBAction of any action of UIButton.
#IBAction func btnShowKeyboardClicked(){
textfield.becomeFirstResponder()
}
For maintaining the custom toolbar as the accessory view, you need to set it to the text field object. First either create the custom toolbar view from code or load using XIB, and assign it to the inputAccessoryView of textfield.
let customInputAccessoryView = CustomView() // Load from XIB or from Code
textfield.inputAccessoryView = customInputAccessoryView
I would like demonstrate it from scratch, so you can learn from this guide. First off all you should create a view, simply click Command+N button or choose File-New-File from the menu of Xcode. Choose a View template under User Interface section as shown below. Give it a name, in this case a Header (you can name it whatever you want).
And create a class to it, again click Command+N or from menu as I mentioned above. In this case choose a Cocoa Touch Class under Source section as shown below. And name it, as a HeaderView. Subclass of UIView
Open up your Header.xib file from the Project Manage. Click your view, give it a size as a freeform, Top bar to none, and Bottom bar to none. Add a UIButton to this view, I guess you know already, how to do it. And click this view, go to the Identity Inspector. And give it a class, in this a HeaderView.swift is our class.
Connect your button as shown below and we are done:
Now all of our focus in code, insert following line of code to the viewDidLoad().
override func viewDidLoad() {
super.viewDidLoad()
// Load the view using bundle.
// Make sure a nib name should be correct
// And cast it to the class, something like this
if let headerView = Bundle.main.loadNibNamed("Header", owner: self, options: nil)?.first as? HeaderView {
// Do some stuff, configuration of the view
headerView.frame = CGRect.init(x: 0, y: 0, width: self.view.frame.width, height: 44)
headerView.button.setTitle("Done", for: .normal)
headerView.button.addTarget(self, action: #selector(self.doneAction(sender:)), for: .touchUpInside)
// Add this view as an accessory to the text field or text view, in this case I have added this to the text field
self.textField.inputAccessoryView = headerView
}
}
Create a custom function to the done button:
#objc func doneAction(sender: UIButton) {
// Do something
// Resing your text field or text view
self.textField.resignFirstResponder()
}
Congrats! You're done. I hope it will help.
I made a prototype cell and I have data from a database to load into the cells in a table.
Each cell has a label and 3 buttons just like this:
If I click on a button for example "Meets Standard", how can I identify in which row I tapped the button?
So for example when I press the "Meets Standard" button at a given row I'd like to change the background color of that row to red. How can I do it?
I have a CustomCell.swift class where I configure the prototype cell and a TableView.swift class where I configure the table.
Try control dragging the button to your CustomCell.swift class and typing a name and selecting "Action" on the popup menu. Then, inside the generated method, you can call self.backgroundColor = UIColor.redColor() or perform any other operations that you'd like.
Edit:
Here's what I think you should do to change the height:
Make a boolean in your cell class called "expanded" or something. Then, go into your table view class and implement the heightForRowAtIndexPath method. In that method, retrieve the cell and check if it's expanded, and if so, return a larger height. Now, to make it reload, you will need to store a reference to the table view in each cell, as it says here: Reference from UITableViewCell to parent UITableView?
In that clicked method you already made, where the background is set to red, you will need to call:
tableView.beginUpdates()
tableView.endUpdates()
where tableview is the weak reference you already stored. Also, in that method, you need to add self.expanded = true of course.
Edit 2:
You know what, maybe it's easier to just do this:
weak var _tableView: UITableView!
...
func tableView() -> UITableView! {
if _tableView != nil {
return _tableView
}
var view = self.superview
while view != nil && !(view?.isKindOfClass(UITableView))! {
view = view?.superview
}
self._tableView = view as! UITableView
return _tableView
}
I need to drag a Cell from CollectionView One and drop it to
CollectionView Two.
The Drag & Drop inside one CollectionView is no Problem, but how
can i get the Cell out of CollectionView One to CollectionView Two?
Any ideas? Any projects or frameworks that have already solved this problem?
Thanks for helping!
https://github.com/Ice3SteveFortune/i3-dragndrop Check this out - its a helper I'm working on to achieve just that. It also supports tableviews
UPDATE
I've recently released the second version of this codebase, called BetweenKit. Its now a fully-fledged drag-and-drop framework.
Hope it proves useful !
When you select the cell from the first collection view, remove it from this collection view, create a new view as copy of that cell place it as subview of the superview on top of all views. Make that view movable using pan gestures. As soon as you "drop" this intermediary cell, detect its position and add it to the current collection view.
Ok, here is the simplest flow ever for the following example:
Add UIGestureRecognizer for every of UICollectionView.
Connect every gesture recognizer with one method:
#IBAction func longPressGestureChanged(recognizer: UILongPressGestureRecognizer) { ... }
Within UIViewController add #IBOutlet for each of UICollectionView:
#IBOutlet var collectionViewGreen: UICollectionView!
#IBOutlet var collectionViewYellow: UICollectionView!
Implement gesture recognizer method to detect changes:
#IBAction func longPressGestureChanged(recognizer: UILongPressGestureRecognizer) {
let globalLocation = recognizer.locationInView(view)
if CGRectContainsPoint(collectionViewGreen.frame, globalLocation) {
//you cover green collection view
let point = view.convertPoint(globalLocation, toView: collectionViewGreen)
if let indexPath = collectionViewGreen.indexPathForItemAtPoint(point) {
//you cover cell in green collection view
} else {
//you do not cover any of cells in green collection view
}
} else if CGRectContainsPoint(collectionViewYellow.frame, globalLocation) {
//you cover yellow collection view
let point = view.convertPoint(globalLocation, toView: collectionViewYellow)
if let indexPath = collectionViewYellow.indexPathForItemAtPoint(point) {
//you cover cell in yellow collection view
} else {
//you do not cover any of cells in yellow collection view
}
} else {
//you do not cover any of collection views
}
}
I have in my View a long UIScrollView (about 1000 px in height), and at the end of this UIScrollView I have a UITableView.
The cellForRowAtIndexPath is never called (surely i checked the delegate and datasource if they are connected right, and the IBOutlet of the table is strong) but numberOfRowsInSection is getting called.
I tried reloading the TableView when the UIScrollView scrolls so when the table is at focus the cellForRowAtIndexPath might get called, but with no luck.
Did anyone encounter a similar behaviour when trying to use tableview and scrollview together?
Your hierarchy is like this:
A parentView is there. Inside the parent view there is a scroll view and there is a table view. So, your tableview is somewhere at 1000 from origin of parentview.
So, tableview will never become visible to your parentview and no delegates will be fired.
Include your view as a headerView of your UITableView like that:
Update for 2020, swift 5.X. To create a custom UITableView that allows your tableview inside a scrollview!
1) Create a subclass of UITableView:
import UIKit
final class ContentSizedTableView: UITableView {
override var contentSize:CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
2) Add a UITableView to your layout and set constraints on all sides. Set the class of it to ContentSizedTableView.
3) You should see some errors, because Storyboard doesn't take our subclass' intrinsicContentSize into account. At runtime it will use the override in our ContentSizedTableView class