UITableViewCell background color animation while swipe cell - ios

I have a problem with implementing custom animation while swiping table view cell.
The goal is to change cell background color while swipe cell with animation.
Ideally, it's perfect if background color changes depending on the offset on the x-axis.
Or if it's impossible or difficult to do it, it would be good to finish the animation when swiping is finished.
And the background color of the cell should be the same as the action button's one.
"Swiping" means gesture that makes buttons show like as default delete action.
The follow code is current one.
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .normal, title: "", handler: { (action,view,completionHandler ) in
completionHandler(true)
})
action.image = UIGraphicsImageRenderer(size: CGSize(width: 30, height: 30)).image { _ in
UIImage(named:"sell_btn")?.draw(in: CGRect(x: 0, y: 0, width: 30, height: 30))
}
action.backgroundColor = UIColor(hex: "#F4F4F4")
tableView.backgroundColor = .red
let confrigation = UISwipeActionsConfiguration(actions: [action])
return confrigation
}
This code changes the background color when this function called.
PS: I've tried MGSwipeCell and SwipeCellKit too, but they don't provide me exact thing what I want.
Thanks.

Related

Button title gets cropped on click

I have a dropdown menu for the user to be able to change the displayed data. When the user chooses to select an item, among others a button is being updated.
Let's say in the beginning the buttons title was "Cars", and after selection of another item it is "Example", the button is being displayed like this: "E...le".
How can I adjust the button size to its title?
Code for the button:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
...
setButtonCars()
...
let tv: UITableViewController = self.children[0] as! HomeTableViewController
print(self.children[0])
tv.tableView.reloadData()
tv.viewWillAppear(true)
buttonDropdown(self)
tableView.deselectRow(at: indexPath, animated: true)
}
func setButtonCars() {
carsButton.setTitle(currentCar.uppercased(), for: .normal)
let icon = UIImage(named: "chevron")!
carsButton.setImage(icon, for: .normal)
carsButton.imageView?.contentMode = .scaleAspectFit
carsButton.imageEdgeInsets = UIEdgeInsets(top: 11, left: 3, bottom: 1, right: 0)
carsButton.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
carsButton.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
carsButton.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
}
EDIT:
I forgot to mention that the button is inside of a UIBarButtonItem.
Add .sizeToFit() after changing the title:
func changeTitle(_ newTitle: String) -> Void {
carsButton.setTitle(newTitle, for: .normal)
carsButton.sizeToFit()
}
This might be happening because of fixed width of the button which might not be enough to hold icon and text. Try increasing the button width.
Set constraint for minimum width of button. You might also like to give maxwidth also in case the text is too large.
Change the Cars button's frame(increase width) such that is can contain the 'Examples' text.
Hope this helps.

UITableViewCell - Set background as gradient to Delete (Swipeable Action) - Swift 4.2

I have customized my trailing swipe action for UITableViewCell. It has an image along with title and background color. It has been done like this :
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .normal, title: ActionTitle.delete) { (deleteAction, view, handler) in
self.deleteAction(indexPath: indexPath)
return handler(true)
}
deleteAction.image = Common.getImageAndTitleForTableRowAction(title: ActionTitle.delete, actionImage: #imageLiteral(resourceName: "delete"))
deleteAction.backgroundColor = Color.orangeColor
let editAction = UIContextualAction(style: .normal, title: ActionTitle.edit) { (editAction, view, handler) in
self.selectedIndexPath = indexPath
self.editLoanRecord()
return handler(true)
}
editAction.image = Common.getImageAndTitleForTableRowAction(title: ActionTitle.edit, actionImage: #imageLiteral(resourceName: "edit"))
editAction.backgroundColor = Color.blueColor
return UISwipeActionsConfiguration(actions: [deleteAction, editAction])
}
Now I need to set the backgroundColor to a gradient.
Checked lots of questions on stackoverflow but unable to do so. Any help will be appreciated.
You could try to create a color from a gradient image like so :
func linearGradientColor(from colors: [UIColor], locations: [CGFloat], size: CGSize) -> UIColor {
let image = UIGraphicsImageRenderer(bounds: CGRect(x: 0, y: 0, width: size.width, height: size.height)).image { context in
let cgColors = colors.map { $0.cgColor } as CFArray
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(
colorsSpace: colorSpace,
colors: cgColors,
locations: locations
)!
context.cgContext.drawLinearGradient(
gradient,
start: CGPoint(x: 0, y: 0),
end: CGPoint(x: size.width, y:0),
options:[]
)
}
return UIColor(patternImage: image)
}
...
deleteAction.backgroundColor = linearGradientColor(
from: [.red, .blue],
locations: [0, 1],
size: CGSize(width: 100, height: 44)
)
But this code has some limitations. You can not guess the size of the action view. So depending on your needs, you can either repeat the color, stretch it or use a large image. Using a third party lib is also a good option.
In many cases, Apple's default implementations will only take you so far and any further customization requires re-implementing the feature.
This seems like one of those cases, since the contextual action is not a view, so you can't modify it to add a gradient like you would with other views, and its properties are limited.
Your options are: implement your own swiping cell, use a third party library (like this one), or simply use a solid color.

Add Trailing Swipe Actions Configuration with white background color and dark gray icon

I am trying to add Trailing Swipe Actions for UITableView using UIContextualAction but the icon is not visible because the icon becomes white and the background is also white and when I change the background color it is visible. Please help me set the icon as such with its color. I tried searching for tint color property but there is no such property. Below are the codes I have tried.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .normal, title: nil, handler: { (action,view,completionHandler ) in
// Delete the row after API
})
//Solution 1
delete.image = UIImage(named: "deleteicon")
// Solution 2
delete.image = UIGraphicsImageRenderer(size:CGSize(width: 30, height: 30)).image { _ in
UIImage(named:"deleteicon")?.draw(in: CGRect(x: 0, y: 0, width: 30, height: 30))
}
// Solution 3
edit.backgroundColor = UIColor(patternImage: UIGraphicsImageRenderer(size:CGSize(width: 30, height: 30)).image { _ in UIImage(named:"favouriteinactiveicon")?.draw(in: CGRect(x: 0, y: 0, width: 30, height: 30))})
let confrigation = UISwipeActionsConfiguration(actions: [delete])
return confrigation
}

Animated table-view cell when the user picks up with his finger (Swift 3)

I'm trying to make this animation
so i want that when the user picks up with his finger the cell get smaller and then when it stops pressing come back on the original size, important is that i'm not using a custom cell but the default UITableViewCell, here is my code with whom i tried to do the animation (after watching old question and tutorial)
var originalCellSize: CGRect!
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
print("I'm Highlighted at \(indexPath.section)")
guard let cell = tableView.cellForRow(at: indexPath) else {
return
}
originalCellSize = cell.frame
UIView.animate(withDuration: 0.1, animations: {
cell.frame = CGRect(x: cell.frame.origin.x + 20, y: cell.frame.origin.y, width: cell.frame.width - 40, height: cell.frame.height)
})
}
func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) else {
return
}
UIView.animate(withDuration: 0.1, animations: {
cell.frame = CGRect(x: 0, y: self.originalCellSize.origin.y, width: self.view.bounds.width, height: 180)
})
originalCellSize = .zero
}
i don't know why but something is wrong and the animation do not work, can someone help me (it also happens that after pushing on the cell this changes position in a definitive way)
Don't manipulate UITableViewCell's frame directly.
Use it's transform property.
Likewise:
Scale down the cell upon highlight / selection.
UIView.animate(withDuration: 0.3) {
cell.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
cell.layoutIfNeeded()
}
Scale back to normal:
UIView.animate(withDuration: 0.3) {
cell.transform = CGAffineTransform.identity
cell.layoutIfNeeded()
}
Don't forget to call cell.layoutIfNeeded() before the animation block and inside (right after assigning the CGAffineTransform).
You can approach the problem in a different way. You can resize a view inside the Table view cell.
Like you can keep a view with white color and cell background as grey color. In highlight delegate method, you can change the frame of UIView inside the cell and on unhighlight method, you can resize to back to cell size.
WhenEver You want to change layout of cell you must need to call cell.layoutIfNeeded().
Set flag that cell should change size.
Add flag check for heightForRowAtIndexPath
On highlighting use:
table.beginUpdates()
table.reloadRowsAt(...)
table.endUpdates()
Should work just fine.
I'm not sure you can just change frame of the cell. So you can also try try to change cell's content view size. Or your custom view frame itself.

Automatic scrolling animation of the text in a UITableViewCell

I have a long string:
"A very long string"
that won't be displayed fully in a UITableView, i.e. it gets truncated to:
"A very long s..."
Is it possible to have this text in a UITableViewCell automatically scroll horizontally and indefinitely so that it loops around? Perhaps this can be achieved using an attributed string?
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
cell.textLabel?.text = "A very long string"
cell.textLabel?.textAlignment = .center
Thanks in advance for any help with this!
EDIT (my attempt at a solution proposed)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
let frame = CGRect(x: 0.0, y: 0.0, width: cell.bounds.width * 2.0, height: cell.bounds.height)
let scrollView = UIScrollView(frame: frame)
cell.addSubview(scrollView)
let label = UILabel(frame: scrollView.bounds)
scrollView.addSubview(label)
label.text = "some very long text that doesn't quite fit"
label.textAlignment = .center
let newFrame = CGRect(x: label.frame.width, y: 0, width: label.frame.width, height: scrollView.frame.height)
UIView.animate(withDuration: 1.0, delay: 0.0, options: [.repeat, .autoreverse], animations:( { void in
scrollView.scrollRectToVisible(newFrame, animated: true)}),
completion: ({ completed in }))
}
Scrollview inside a table view is a bad idea. Instead you can enable the automaticDimension and estimated row height and tableView will manage the cell height automatically.
self.tableView.estimatedRowHeight = 44
self.tableView.allowsMultipleSelection = true
So as per the content each cell will manage its own height.
Hope this would be helpful!
You would have to make a custom tableview cell, which has a custom scrollview which handles UILabel scrolling. You would need to assign the text and measure the width. If it is wider than the containing view then add a second duplicate label to its right. You then need to animate the scrollview to the left by the width of the label. On complete, jump back to offset 0,0 and animate again.
Usually, to have special effect as such will require customization of an UILabel. To make my life easier, I will always try to search if there is already a working library out there for me to consume.
A simple Google search brings me MarqueeLabel, hope it helps!

Resources