Reputation: 2870
How do you set a custom font for the title in UIContextualAction
?
I have tried UIAppearance
but without any luck...
Cheers! :)
Upvotes: 3
Views: 7163
Reputation: 21
I found a very simple method that helped me All you have to do is create your own View and add a label, image or whatever you want
Outwardly customize everything in this view and then convert it to an image using the code below Next, add an image to the action button and that's it
deleteAction.image = createDeleteImage() /// this is my function that creates a View and then using the extension below, it converts it into an image
Before doing this, don't forget to make the title of the button equal to the empty string ""
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
How to convert a UIView to an image
Upvotes: 1
Reputation: 1638
The following function allows you to set a font as well as a tint color to your swipe actions.
To get started, add an extension to UITableView
.
extension UITableView {
/// Iterates over all subviews of a `UITableView` instance and applies the supplied font to all labels withing the UISwipeAction's array.
/// - Parameter font: The font that should be applied to the labels.
/// - Parameter tintColor: The tint color that should be applied to image views and labels
/// - Parameter ignoreFirst: Whether or not the first swipe action should be ignored when applying tints
public func setSwipeActionFont(_ font: UIFont, withTintColor tintColor: UIColor? = nil, andIgnoreFirst ignoreFirst: Bool = false) {
for subview in self.subviews {
//Confirm that the view being touched is within a swipe container
guard NSStringFromClass(type(of: subview)) == "_UITableViewCellSwipeContainerView" else {
continue
}
//Re-iterate subviews and confirm that we are touching a swipe view
for swipeContainerSubview in subview.subviews {
guard NSStringFromClass(type(of: swipeContainerSubview)) == "UISwipeActionPullView" else {
continue
}
//Enumerate subviews and confirm that we are touching a button
for (index, view) in swipeContainerSubview.subviews.filter({ $0 is UIButton }).enumerated() {
//Set Font
guard let button = view as? UIButton else {
continue
}
button.titleLabel?.font = font
//Set Tint Conditionally (based on index)
guard index > 0 || !ignoreFirst else {
continue
}
button.setTitleColor(tintColor, for: .normal)
button.imageView?.tintColor = tintColor
}
}
}
}
}
Within your delegate, add the following functionality to your UITableViewDataSource.WillBeginEditing(UITableView, IndexPath)
method. Replace the font and colour params as you need. Tint colour is optional.
self?.tableView.setSwipeActionFont(.systemFont(ofSize: 24.0, withTintColor: .systemRed)
Upvotes: 2
Reputation: 2399
FOR OBJECTIVE C
Create a method
- (UIImage *)createImageFromLabel:(UILabel *)label
{
UIGraphicsBeginImageContext(label.bounds.size);
[label.layer renderInContext:UIGraphicsGetCurrentContext()];;
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
This method will return image from your label.
Now in tableview datasource method
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIContextualAction *action = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:nil handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
//Your code here
}];
action.backgroundColor = [UIColor redColor];
// Create label as you want view for delete button
UILabel *label = [[UILabel alloc] init];
label.font = [UIFont systemFontSize:14];
label.text = @"Your Text";
label.textColor = [UIColor whiteColor];
[label sizeToFit];
UIImage *image = [self createImageFromLabel:label];
action.image = image;
UISwipeActionsConfiguration *actions = [UISwipeActionsConfiguration configurationWithActions:@[action]];
return actions;
}
Upvotes: -1
Reputation: 147
I recently found out a way to do this by using the button titleLabel instead of the image property, so that you keep the ability to have an action with text and image.
As you will see, we need to do something awkward...
func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
if #available(iOS 13.0, *) {
for subview in tableView.subviews {
if NSStringFromClass(type(of: subview)) == "_UITableViewCellSwipeContainerView" {
for swipeContainerSubview in subview.subviews {
if NSStringFromClass(type(of: swipeContainerSubview)) == "UISwipeActionPullView" {
for case let button as UIButton in swipeContainerSubview.subviews {
button.titleLabel?.font = .systemFont(ofSize: 12)
}
}
}
}
}
} else {
for subview in tableView.subviews {
if NSStringFromClass(type(of: subview)) == "UISwipeActionPullView" {
for case let button as UIButton in subview.subviews {
button.titleLabel?.font = .systemFont(ofSize: 12)
}
}
}
}
}
Upvotes: 8
Reputation: 2870
I have found a way to do this by using the image property instead of the title...
Standard font (Remove/Rename)
Custom font (Remove/Rename)
To create an image of a label I have this extension:
extension UIImage {
/// This method creates an image of a view
convenience init?(view: UIView) {
// Based on https://stackoverflow.com/a/41288197/1118398
let renderer = UIGraphicsImageRenderer(bounds: view.bounds)
let image = renderer.image { rendererContext in
view.layer.render(in: rendererContext.cgContext)
}
if let cgImage = image.cgImage {
self.init(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up)
} else {
return nil
}
}
}
And then I simply have:
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .destructive, title: nil) { action, view, completion in
// Your swipe action code!
}
let label = UILabel()
label.text = // Your swipe action text!
label.font = // Your custom font!
label.sizeToFit()
action.image = UIImage(view: label)
return UISwipeActionsConfiguration(actions: [action])
}
Upvotes: 15