Can you help me how I can customize cancel and post buttons in SLComposeServiceViewController?
I want to change title and button image.
Can you help me how I can customize cancel and post buttons in SLComposeServiceViewController?
I want to change title and button image.
SLComposeServiceViewController
has very limited options for customizing its UI, and this does not currently include the ability to modify the "cancel" and "post" buttons. In the current version of iOS, the only way to avoid using those buttons is to not use SLComposeServiceViewController
. Share extensions are not required to use that class and may use a fully custom UI. If those buttons are not appropriate, that's your only option.
I came up with this solution. Worst case scenario Apple changes things up and stops using a navigation bar, in which case the buttons will simply revert back to saying 'Post' and 'Cancel'. There should be no crashes.
For this example, I've used an '✖' for cancel and '✔' for post.
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// find the navigation bar
UINavigationBar* bar = self.navigationController.navigationBar;
if (bar == nil)
{
for (UIView* b in self.view.subviews)
{
if ([b isKindOfClass:UINavigationBar.class])
{
bar = (UINavigationBar*)b;
break;
}
}
if (bar == nil)
{
return;
}
}
// find the cancel and post buttons, assuming the post button is on the far right which is a common iOS UI design, to put the positive or confirm action on the right
// also deals with right to left languages (which SLComposeViewController does not support yet), where the post button will be on the left
UIButton* postButton = nil;
UIButton* cancelButton = nil;
BOOL rightToLeft = NO;
if ([UIView.class respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:)])
{
rightToLeft = ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:bar.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft);
}
CGFloat x = (rightToLeft ? FLT_MAX : FLT_MIN);
for (UIView* v in bar.subviews)
{
if ([v isKindOfClass:UIButton.class] && ((rightToLeft && v.frame.origin.x < x) || (!rightToLeft && v.frame.origin.x > x)))
{
x = v.frame.origin.x;
if (postButton != nil)
{
cancelButton = postButton;
}
postButton = (UIButton*)v;
}
}
// if we found a cancel UIButton, set the title
if (cancelButton != nil)
{
[cancelButton setTitle:@"✖" forState:UIControlStateNormal];
}
// if we found a post UIButton, set the title
if (postButton != nil)
{
[postButton setTitle:@"✔" forState:UIControlStateNormal];
}
}
I just found a way to do it:
class CustomServiceViewController: SLComposeServiceViewController {
override func viewDidLoad() {
let navigationBar = view.subviews.first?.subviews?.last? as? UINavigationBar
let postButton = navigationBar?.subviews.last? as? UIButton
let cancelButton = navigationBar?.subviews.last? as? UIButton
postButton?.setTitle("Done", forState: .Normal)
}
}
Be warned - it's a fragile solution, based on undocumented internals of SLComposeServiceViewController