In the editing mode of UITableView, I need three things, the first two are easy to get using UITableView delegate methods:
Delete (- in red) button on the left of the row,
Reorder (three bars) row button on the right of the row,
A custom defined action (with title & background color) appearing on the left side of reorder (three bars) button.
How is it possible to get these three actions together?
Hi yes it is possible to make or add your own custom action by implementing the tableView delegate
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let archiveAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: " ") { (rowAct, index) in
}
let deleteAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: " ") { (rowAct, index) in
}
let archiveImg = UIImageView(image: UIImage(named: "archive_btn"))
archiveImg.contentMode = .scaleAspectFit
archiveAction.backgroundColor = UIColor(patternImage:archiveImg.image!)
let deleteImg = UIImageView(image: UIImage(named: "delete_btn"))
deleteImg.contentMode = .scaleAspectFit
deleteAction.backgroundColor = UIColor(patternImage:deleteImg.image!)
return [deleteAction,archiveAction]
}
Related
How do I get the edit contact button to show when swiping on a UITableViewCell? The event is never raised and the edit button never appears.
For Swift 4 & iOS 11+
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
// since the style is destructive, so it will have a red background by default.
// change it to .normal and it will have a blue background by default..
let editAction = UIContextualAction(style: .destructive, title: "Edit Contact") { _, _, complete in
// continue your logic..
// write your code to move to next screen.. Perform segue or move using storyboards..
complete(true)
}
// if you want to add icon, then you can do it this way..
editAction.image = UIImage(named: "editContact")
// you can set your own background color for the button like this..
editAction.backgroundColor = .orange
let configuration = UISwipeActionsConfiguration(actions: [editAction])
//set to false to prevent a full swipe from performing the first action..
configuration.performsFirstActionWithFullSwipe = true
return configuration
}
Evening ladies and gentleman,
I am currently getting used to Swift and wanted to start with a little todo app. So far I can add an item and safe it persistently in a context. When an item has been added, it will be shown in a tableview. Now, I want to use a check swipe to strikethrough items, which have been added and safe this information in my context. Deleting using a swipe works perfectly fine.
Has anybody an idea how realize this? I tried to solve it by myself, but couldnt get it done. A similar question has been asked here before, but didnt get a proper answer: Add strikethrough to tableview row with a swipe
func checkAccessoryType(cell: UITableViewCell, isCompleted: Bool) {
if isCompleted {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let todo = CoreDataManager.shared.getTodoItem(index: indexPath.row)
todo.completed = !todo.completed
CoreDataManager.shared.safeContext()
if let cell = tableView.cellForRow(at: indexPath){
checkAccessoryType(cell: cell, isCompleted: todo.completed)
}
}
Assuming you are trying to strikethrough the title of your task -- which should be defined as a label -- here is the approach to take:
1- Make sure your label is set to attributed text rather than plain. To do that, go to Main.storyboard, select your label, and inside the attribute inspector, set text to Attributed.
2- Inside your completion block (that is the completion block executed after a swipe) add the following code:
(SWIFT 5)
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: taskLabel.text)
attributeString.addAttribute(.strikethroughStyle, value: 1, range: NSRange(location: 0, length: taskLabel.text.count))
taskLabel.attributedText = attributeString
Just a little advice: it's always helpful if you add some code when you ask a question.
Let me know if anything doesn't make sense.
Looking at the link that you provided, you need swipe action on your UITableViewCell.
Try looking into:
leadingSwipeActionsConfigurationForRowAt
trailingSwipeActionsConfigurationForRowAt
You need this action to perform the strikethrough label or delete:
func tableView(_ tableView: UITableView,
leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
{
let closeAction = UIContextualAction(style: .normal, title: "Close", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
print("OK, marked as Closed")
success(true)
})
closeAction.image = UIImage(named: "tick")
closeAction.backgroundColor = .purple
return UISwipeActionsConfiguration(actions: [closeAction])
}
func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
{
let modifyAction = UIContextualAction(style: .normal, title: "Update", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
print("Update action ...")
success(true)
})
modifyAction.image = UIImage(named: "hammer")
modifyAction.backgroundColor = .blue
return UISwipeActionsConfiguration(actions: [modifyAction])
}
Source: https://developerslogblog.wordpress.com/2017/06/28/ios-11-swipe-leftright-in-uitableviewcell/
I'm using SwipeCellKit for my TO DO List app. When the user swipes left it deletes the item, but when the user swipes right I want him to be able to set a reminder on this item, so I've created an actionset a reminder
this action should perform a segue which brings the user to a custom popup with a date picker in it. The problem is that when I click on the button to set a reminder the simulator quits with an uncaught exception. I've already tried to perform deletion from this button it works perfectly, I've also tried to perform another segue to another view controller from this button the simulator quits. Could someone tell me what I'm doing wrong here? Here's my code:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? { if orientation == .left {
guard isSwipeRightEnabled else { return nil }
let setReminder = SwipeAction(style: .default, title: "Set a reminder") { action, indexPath in
self.updateModelByAddingAReminder(at: indexPath)
}
setReminder.image = UIImage(named: "reminder-icon")
return[setReminder]
}else{
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
self.updateModel(at: indexPath)
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete-icon")
// return [setReminder, deleteAction]
return [deleteAction]
}
Ok, I found problem in your options for cell.
From doc
The built-in .destructive, and .destructiveAfterFill expansion styles are configured to automatically perform row deletion when the action handler is invoked (automatic fulfillment).
And you need use destructive style for cell in editActionsForRowAt. Or use another options, for example
func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeTableOptions {
var options = SwipeTableOptions()
options.transitionStyle = .border
if orientation == .left{
//or none
options.expansionStyle = .selection
}else{
options.expansionStyle = .destructive
}
return options
}
Hope it's help.
I am preparing a table in which when I swipe the cell I need to get two rounded buttons. Each button should have one image and and a label.
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
var hello = UITableViewRowAction(style: .Default, title: "Image") { (action, indexPath) in
// do some action
if let buttonImage = UIImage(named: "Image") {
// self.bgColor = UIColor.imageWithBackgroundColor(image: buttonImage, bgColor: UIColor.blueColor())
}
return editButtonItem()
}
First of all, there are some problems with your code :
You return the result of editButtonItem() method, which basically discards your hello action. I'm gonna assume from the name of it, that this method returned a single action, and not two as you wanted.
In your action handler, you tried to set the background on self. Blocks capture variables from their parent scope, so self in this block didn't relate to hello action, but rather to the class in which your editActionsForRowAtIndexPath method was implemented.
How to achieve what you need (two buttons with title and image) :
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
var firstAction = UITableViewRowAction(style: .Default, title: "First") { (action, indexPath) in
// action handler code here
// this code will be run only and if the user presses the button
// The input parameters to this are the action itself, and indexPath so that you know in which row the action was clicked
}
var secondAction = UITableViewRowAction(style: .Default, title: "Second") { (action, indexPath) in
// action handler code here
}
firstAction.backgroundColor = UIColor(patternImage: UIImage(named: "firstImageName")!)
secondAction.backgroundColor = UIColor(patternImage: UIImage(named:"secondImageName")!)
return [firstAction, secondAction]
}
We create two separate actions, assign their background colors to use pattern images and return an array containing both our actions. This is the most you can do to alter the appearance of UITableViewRowAction - we can see from the docs, that this class doesn't inherit from UIView.
If you wanted to customize the appearance more, you should look for an external library or implement your own solution from the scratch.
I want to custom my delete button of the UITableViewCell like these codes:
let deleteAciont = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: nil, handler: {action, indexpath in
do some thing
});
deleteAciont.backgroundColor = UIColor(patternImage: UIImage(named: "delete")!)
the height of the UITableViewCell is 70 like this:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 70
}
and the images are these size: delete.png:70*70\delete#2x.png:140*140\delete#3x.png:210*210
but when i swipe left, the image only show half:
I have been confusing about this for a long time and thanks for your help
the length of the tableViewRowAction will be the title's length
let deleteAciont = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: " type more space here ", handler: {action, indexpath in
do some thing
});