Multiple animations are messed up - swift

In collection view I have cells with image for every cell.
When the delegates of the collection being called, I set a different animation for every cell image according to data.
Every new cell that being added, I remove all other cells and reload the data of the collection.
What happens is that after I add a few cells, say cell 1 has stretch animation and cell 3 has scale animation, then cell 1 get stretch+scale .
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! FlowViewCell
cell.image.image=UIImage(named: moduleImage as String)
animate(moduleAnimation, image: cell.image)
....
func animate (kind:NSString, image:UIImageView)
// here I check what animation to apply (different between cells)
// *** can be
CABasicAnimation(keyPath: "transform.rotation")
//**** or
UIView.animateWithDuration(2.0, delay: 0.0, options: [.Repeat, .CurveEaseOut, .Autoreverse], animations: {
image.transform = CGAffineTransformMakeScale(0.15, 1.0)
Is there anything I can do to clear stuff? I think the reusable cells has something to do with it.
EDIT:
Have tried : cell.image.image=nil , no success .

Fixed it with this :
let index = data.count-1
let indexPath = NSIndexPath(forItem: index, inSection: 0)
collectionView.insertItemsAtIndexPaths([indexPath])
One should not use the reloadData function because there is no guarantee it will use the same cells again, and its not that good for performance, so instead update the cell that relevant.

Related

How I can sync animations in Table View with Swift

I have a table view with animation in each cell, the animation is a circle blinking but when made scroll the new row blink in different time. The idea is all circles blink at same time.
Thanks by any help. I had 2 days try different things. The last is make my own animation with a timer and save the time in global variable. But i think that core animation should have something for do that.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myClassCell", for: indexPath) as! MyClassCell
cell.circleBlinking.alpha = 0
View.animate(withDuration: 1, delay: 0, options: [.repeat, .allowUserInteraction, .curveLinear], animations: {
cell.circleBlinking.alpha = 1} )
}
return cell
}
Finally i found a solution for the requirement. I made the animation with a timer.
I created a global timer that change a global variable each 1/24 secs from 0 to 1 and from 1 to 0
When pass by cellForRowAt I create other timer just for that cell but the function is just give the value alpha from my global variable that is doing modified by the main timer. So that way I have all circles sync
If somebody know how do that with animate welcome with your answer.
Already I uploaded the code to Github with solution.
https://github.com/wilmanro77/TableViewWithAnimationInCells

NSTableView start cells from bottom

I have a osX project with NSTableview
[Screen]
[a]
[b]
[c]
[d]
no cell
no cell
[Screen]
is is posible to change direction of this tableview to look like this?
[Screen]
no cell
no cell
[d]
[c]
[b]
[a]
[Screen]
i have tried transform like in iOS but it throwing errors
tableView.transform = CGAffineTransform(scaleX: 1, y: -1)
same goes for cell
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
what must be done to access transform property in OSX like in iOS?
From what I think you want, you don't need to use CGAffineTransform .
You just need to organise your data set as you wish and populate the cells accordingly.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as? CustomTableViewCell else {
return UITableViewCell()
}
cell.updateTitle(customCellTitles[indexPath.row])
return cell
}
instead of having your data set as:
customCellTitles = ["a","b","c","d"]
make it:
customCellTitles = ["d","c","b","a"]
In addition to this, I would go for the following setup of your layout:
Notice there is no top constraint.
Next, create an outlet from your table view height constraint and update it when you have your data set ready.
In the simple scenario where your cell size is the same (or independent from the content you display) update your height constraint based on the cell size:
tableViewHeightConstraint.constant = cellSize * numberOfCells
view.setNeedsLayout()

Changing UI elements in a custom CollectionViewCell using didSelect method

I'm working on a simple flashcard app. The cards are loaded into a collection view. When someone clicks on the card I want a rotation animation to occur and the text label to change to the answer.
func animateRotationY(view: UIImageView) {
let animation = CABasicAnimation(keyPath: "transform.rotation.y")
let angleRadian = CGFloat.pi * 2
animation.fromValue = 0
animation.byValue = angleRadian
animation.toValue = angleRadian
animation.duration = 1.0
animation.repeatCount = 1
view.layer.add(animation, forKey: nil)
}
Im calling this animation function in the didSelect method as such
extension FlashCardsViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = flashCardsView.collectionView.dequeueReusableCell(withReuseIdentifier: "FlashCardCell", for: indexPath) as! FlashCardCollectionViewCell
let row = indexPath.row
let selectedCard = flashCards[row]
animateRotationY(view: cell.imageView)
selectedIndexPath = row
cell.textLabel.text = selectedCard.answer
self.flashCardsView.collectionView.reloadData()
}
Problem is, not only will the animation not show, but the textLabel wont even update even though the breakpoints are hitting those lines. Does anyone have any idea how I can update UI in the didSelect?
When you call dequeueReusableCell(withReuseIdentifier:for:), you're not getting the cell that is already shown and you want to change.
You should call flashCardsView.collectionView.cellForItem(at: indexPath) instead.
Also, calling reloadData() is causing collectionView(_:cellForItemAt:) to be called for every index path, which might be overriding whatever changes you made after selecting the cell.

Independently auto fade UITableView rows starting with the bottom row

Examples of row deletion usually implement textFieldDidEndEditing or some other gesture / user input method.
My version of an auto-deletion feature is to use animateWithDuration with alpha. It's simple and looks good.
The challenge is I would like to do this automatically via NSTimer or animateWithDuration independently of any user scrolling and user input. Just a simple fade-out starting with the newest bottom row and have it stay alpha 0 as it moves up the table.
Currently you don't see any rows when you open the app because the rows have already faded out. This is good. The problem occurs every time a user sends a new posts all the "invisible" rows appear again starting at alpha 1 and then all fade out together.
I need the previous rows above to stay at alpha 0 with only the new bottom row having alpha 1 then it fades away to alpha 0.
Is it because I need to use cellForRowAtIndexPathinstead? Or do I need to use the dequeueReusableCellWithIdentifier method?
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! CHEFTALKRecipeViewCell
let recipe = recipes[indexPath.item]
if recipe.posterId == posterId {
cell.textView!.textColor = UIColor.blackColor()
// STEP 1
cell.contentView.alpha = 1
} else {
// do something
}
return cell
}
// STEP 2
override func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
UIView.animateWithDuration(2.0) {
cell.contentView.alpha = 0
}
}
As much as I understand your problem is that all cells animate. Even the ones at the top.
If so, you can retrieve -visibleCells from UICollectionView and start animation if only their position is at the bottom of the screen.

Custom expanding/collapsing Date Picker expands off view when it's in the bottom cell of table view - Swift

I have a custom inline date picker that expands and collapses just like the Apple Calendar events date pickers. The problem is that I need the Date Picker to in a UITableViewCell that is at the bottom of the UITableView, but when it expands, you cannot see the Picker without scrolling the view down manually. For a similar issue (UITextField disappears behind keyboard when it's being edited if it's below the height of the keyboard) I was able to fix it with an animation in the beginEditing and endEditing delegate functions:
let keyboardHeight: CGFloat = 216
UIView.animateWithDuration(0.25, delay: 0.25, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
self.view.frame = CGRectMake(0, (self.view.frame.origin.y - keyboardHeight), self.view.bounds.width, self.view.bounds.height)
}, completion: nil)
Does anyone know of a similar animation that would work for maybe placing in didSelectRowAtIndexPath, and if it's a date picker the screen will adjust by scrolling down to show the full date picker expanded, and then it will adjust back when the row is not selected anymore - or something along these lines?
I'm not sure if the fact that there's already an animation occurring to expand/collapse the date picker would conflict with this or if it's just a matter of precedence for the animations to occur. Anyways I will post some code below:
When the DatePicker is selected in the tableView:
/**
Used to notify the DatePickerCell that it was selected. The DatePickerCell will then run its selection animation and expand or collapse.
*/
public func selectedInTableView() {
expanded = !expanded
UIView.transitionWithView(rightLabel, duration: 0.25, options:UIViewAnimationOptions.TransitionCrossDissolve, animations: { () -> Void in
self.rightLabel.textColor = self.expanded ? self.tintColor : self.rightLabelTextColor
}, completion: nil)
}
didSelectRowAtIndexPath function:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Deselect automatically if the cell is a DatePickerCell.
let cell = self.tableView(tableView, cellForRowAtIndexPath: indexPath)
if (cell.isKindOfClass(DatePickerCell)) {
let datePickerTableViewCell = cell as! DatePickerCell
datePickerTableViewCell.selectedInTableView()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
} else if(cell.isKindOfClass(PickerCell)) {
let pickerTableViewCell = cell as! PickerCell
pickerTableViewCell.selectedInTableView()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
tableView.beginUpdates()
tableView.endUpdates()
}
I think I came up with a solution that seems to work as needed, I wrote this code in the didSelectRowAtIndexPath delegate function after the call to selectedInTablView():
if(datePickerTableViewCell.isExpanded() && datePickerTableViewCell.datePicker == billDatePicker.datePicker) {
tableView.contentOffset = CGPoint(x: 0, y: self.view.frame.height + datePickerTableViewCell.datePickerHeight())
}