I am setting view when swipe tableview cell like as 1st view in table it need to be stick on as second view and change its color.
Is it possible in Swift 4 and iOS?
Once you are getting the swipe gesture in view controller you do the next:
func didSwipe(_ cell: UITableViewCell) {
let indexPath = tableView.indexPath(for: cell)
if indexPath.row + 1 < myViewModels.count - 1 {
// Store the info from the next view model to the current one
myViewModels[indexPath.row].update(with: myViewModels[indexPath.row + 1])
tableView.reloadItems(at: [indexPath])
}
}
myViewModels is an array of object(contains data, colors, etc) that you are displaying
Instead of update you can manually update necessary fields
The code may have an errors but the idea should be clear
Related
I have custom layout with fullscreen cells. When removing cell from the left (it's not visible at the time), UICollectionView jumps to the next cell.
It's like current cell was at index 4 and when cell on the left removed the next cell has index 4 now and immediately scroll to the next cell.
Describing in 3 steps (A is cell that need to be fullscreen, x will be removed, o other cells, large letter is fullscreen):
ooooAoo
oooxAoo
oooaOo
But must keep this oooAoo
Here is my solution if it can help to anybody, did not found how to achieve desired offset natively, so just scrolling contentOffset to the desired position right after reloadData():
var currentCell: MyCollectionViewCell? {
return (visibleCells.sorted { $0.frame.width > $1.frame.width }.first) as? MyCollectionViewCell
}
//-----------------------------------------
//some model manipulating code, removing desired items here...
let currentList = currentCell?.parentList
reloadData()
if let list = currentList, let index = self.lists.firstIndex(of: list) {
self.scrollToItem(at: IndexPath(row: index, section: 0), at: .centeredHorizontally, animated: false)
}
currentCell is computed property, returns optional middle cell.
Detect which cell is the largest, because of custom flowlayout logic.
parentList is the model item, I can compare cell by it to make life
easier. I check which list was attached to the cell before
reloadData().
Intro
I know that this topic has been discussed a lot on StackOverflow and
am aware that a Collection View recycles its cells.
However, I have not found a suitable explanation for the problem I
describe below.
Problem
In my app, I have a collection view that has multiple cell types in it - each cell only exists once in the collection view.
The collection view acts like a form in which the user can enter different things - split up on a few cells.
If I now scroll down, the first cell is not visible anymore. However, it is also not removed from the collection view as the entered data is still correctly displayed if I scroll back to the top.
If a user clicks a button, I am fetching every collection view cell
from the collection view and run a validation method on it.
Just like the following:
let firstCell = myCollectionView.cellForItem(at: IndexPath(row: 0, section: 0)) as! DefaultElementCell // get the cell
firstCell.validateEntries() // validates entries and highlights incorrect fields
If I now scroll to the bottom of the collection view (the last cell), I get an error "unexpectedly found nil while unwrapping an optional value". The optional value in this case is the Cell that should be returned by cellForItemAt().
So, I think that the cell has already been removed but on the other
hand the text entered into the fields and everything are still there
if I scroll back to the first cell.
What I tried:
if let firstCell = myCollectionView.dataSource?.collectionView(self.myCollectionView, cellForItemAt: IndexPath(row: 0, section: 0)) {
print((firstCell as! DefaultElementCell).validateEntries()) // does nothing
}
Now, I don't get the error "unexpectedly found nil" anymore but validateEntries() also does nothing anymore.
Is there any way I can correctly get the invisible collection view cells or prevent the collection view from re-using cells? As already mentioned, every cell type only exists once in the collection view.
I would appreciate any help!
You need to create an array of same size as you number of cells then
var arr = [String]()
// inside cellForRowAt
cell.textfield.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged
cell.textfield.tag = indexPath.item
and
#objc func textFieldDidChange(_ textField: UITextField) {
arr[textfiled.tag] = textfield.text!
}
then validate you entry from arr values
I want to change my progress bar one by one in tableview. but when my use invisible cell in code, then it produces nil.
I use the tableview.cellforRowAt(IndexPath) in our code , Please resolve my problem
UITableViewCell is reusable, you cannot update UI of cells that are not displayed (visible), they just do not exist or being reused for another cell.
Reusable means that cell's view (UITableViewCell) will be used for any other cell that might just got in to the tableView bounds, this happens when you delete a row, or when you scroll away and the cell gets out of tableView bounds etc...
So, its not a problem, but by design.
BTW, you are using the correct method tableView.cellForRow(at: IndexPath), it will return a cell only if one is displayed.
You should instead update your data source and keep the progress value, when the cell next time being displayed it will show the value from data source, like so:
struct CellData {
var progress: Float
}
var dataSource: [CellData]
Now when you need to update the progress of cells, you can just update dataSource, like so
dataSource[index].progress = value
Then you call either call UITableView.realoadData() to refresh the UI of all cells that are visible, or you can update only that particular index, like so:
if let cell = self.tableView.cellForRow(at: IndexPath(row: index, section: 0)) as? CustomCell {
cell.progressView.setProgress(value, animated: true)
}
So basically I have a progress view, among others, within a UITableViewCell that is dynamic. How would I access the progress view (or any view) of a specific cell? I want to change the progress based on a value stored for that specific cell.
Thank you in advance.
You should have a view controller (class) level property for progress and eventually implement a property observer so that you can refresh the view as soon as progress gets updated.
var progress: Double = 0.0 {
didSet{
updateProgressCell()
}
}
Supposing that you know where (what's the row number - progressCellRowNumber) in your table is the progress view this is how you can implement the cell refreshing:
fund updateProgressCell() {
var indexPath = NSIndexPath(forRow: progressCellRowNumber, inSection: 0)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
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
}
}