How can you customize UIActivityViewController to ONLY include custom UIActivity types?
My colleague was able to figure this out. For anyone wondering how to display only the applicationActivities
(custom activities) on the share sheet, this is how I did it.
For activityItems
rather than creating an array of strings, create an array of your custom data objects. Then override the canPerform(withActivityItems activityItems: [Any])
method in your custom UIActivity
(subclass of UIActivity
) to return true if activityItems[o] is CustomItem
. Since your activityItems
are custom, system will not display other apps on the share sheet. That's it.
In the example below, only your CustomUIActivity
will be displayed on the share sheet.
let items = [CustomItem("Hello world")]
let activitySheet = UIActivityViewController(
activityItems: items,
applicationActivities: [
CustomUIActivity()
]
)
class CustomItem {
let value: String
required init(value: String) {
self.value = value
}
func getValue() -> String {
return self.value
}
}
@objc(CustomUIActivity)
class CustomUIActivity: UIActivity {
override class var activityCategory: UIActivity.Category {
return .share
}
override var activityType: UIActivity.ActivityType? {
return .customuiactivity
}
override var activityTitle: String? {
return "Custom"
}
override var activityImage: UIImage? {
return UIImage(named: "custom-icon")
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
if activityItems.count == 1 && activityItems[0] is CustomItem {
return true
}
return false
}
var textToShare: String?
override func prepare(withActivityItems activityItems: [Any]) {
if let activityItem = activityItems.first as? CustomItem {
self.textToShare = activityItem.getValue
}
}
override func perform() {
// perform your custom activity with `textToShare`
activityDidFinish(true)
}
}
extension UIActivity.ActivityType {
static let customuiactivity =
UIActivity.ActivityType("com.ceylonese.mobile.customuiactivity")
}
How can I add a ActivityItem to upper activity bar in UIActivityViewController?
In your custom UIActivity
subclass you have to simply override one method:
+ (UIActivityCategory)activityCategory
{
return UIActivityCategoryShare;
}
There are to possible categories: action and share.
It's important, this is class method, not instance. Also, it's iOS 7 specific - all action activities are placed in bottom line (if any), then above the share activities and then above AirDrop. So, if you want to get rid of bottom line for example, simply exclude all action activities. If you want to put something in share/action line - override activityCategory
. default is UIActivityCategoryShare;
how to add a custom entry in UIActivityViewController
I believe you are asking about two separate things.
UIActivityViewController:
Here's my code in my app.
let vc = UIActivityViewController(activityItems: [shareImage], applicationActivities: [])
vc.excludedActivityTypes = [
UIActivityType.airDrop,
UIActivityType.assignToContact,
UIActivityType.addToReadingList,
//UIActivityType.copyToPasteboard,
//UIActivityType.mail,
//UIActivityType.message,
//UIActivityType.openInIBooks,
//UIActivityType.postToFacebook,
//UIActivityType.postToFlickr,
UIActivityType.postToTencentWeibo,
//UIActivityType.postToTwitter,
UIActivityType.postToVimeo,
UIActivityType.postToWeibo,
UIActivityType.print,
//UIActivityType.saveToCameraRoll
]
present(vc,
animated: true,
completion: nil)
vc.popoverPresentationController?.sourceView = self.view
vc.completionWithItemsHandler = {(activity, success, items, error) in
}
Pay attention to the excludedActiviyTypes code. My app is an image effect app, so I commented out the things I wish to have in the popup - Weibo, print, assignToContact, ReadingList, Vimeo, and TencentWeibo. Here's the thing - I kept the full list of activities for quick reference. (I've never found it on ADC and end up getting it by using code complete.)
UIActivityType is an extended struct, so if you want to go the route of using it this way I think you'll have to (1) subclass UIActivityViewController, (2) write your own extension to UIActivityType, and (3) provide any/all code needed to use a service that isn't listed above.
A Document Provider is what I think you are looking for. Either that, or Universal - sometimes called Deep - Linking. (The links are to Apple documentation for using each.)
I've obviously used UIActivityiewController, but haven't (yet) had any need to these other two.
If you have questions about setting up a UIActivityViewController, post them in the comments. If someone else has a way to "extend" it in any way other than I described, let me know and I'll remove this answer.
UIActivity View Controller with custom row (Like what's App did in edit photo)
You can use an UIAlertController for this:
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel"), style: .cancel)
{
_ in
}
alert.addAction(cancel)
let take = UIAlertAction(title: "Take Photo", style: .default)
{
_ in
// TODO Do something
}
alert.addAction(take)
let choose = UIAlertAction(title: "Choose Photo", style: .default)
{
_ in
// TODO Do something
}
alert.addAction(choose)
let deletePhoto = UIAlertAction(title: "Delete Photo", style: .destructive)
{
_ in
// TODO Do something
}
alert.addAction(deletePhoto )
self.present(alert, animated: true, completion: nil)
How can I create a custom UIActivity in iOS?
First, create the files. I chose to name mine ActivityViewCustomActivity
Make ActivityViewCustomActivity.h look like this:
#import <UIKit/UIKit.h>
@interface ActivityViewCustomActivity : UIActivity
@end
Make ActivityViewCustomActivity.m look like this:
#import "ActivityViewCustomActivity.h"
@implementation ActivityViewCustomActivity
- (NSString *)activityType
{
return @"yourappname.Review.App";
}
- (NSString *)activityTitle
{
return @"Review App";
}
- (UIImage *)activityImage
{
// Note: These images need to have a transparent background and I recommend these sizes:
// iPadShare@2x should be 126 px, iPadShare should be 53 px, iPhoneShare@2x should be 100
// px, and iPhoneShare should be 50 px. I found these sizes to work for what I was making.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
return [UIImage imageNamed:@"iPadShare.png"];
}
else
{
return [UIImage imageNamed:@"iPhoneShare.png"];
}
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
NSLog(@"%s", __FUNCTION__);
return YES;
}
- (void)prepareWithActivityItems:(NSArray *)activityItems
{
NSLog(@"%s",__FUNCTION__);
}
- (UIViewController *)activityViewController
{
NSLog(@"%s",__FUNCTION__);
return nil;
}
- (void)performActivity
{
// This is where you can do anything you want, and is the whole reason for creating a custom
// UIActivity
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=yourappid"]];
[self activityDidFinish:YES];
}
@end
This is what my image looked like:
Here is the .PSD I made: -- malicious link removed --
And here is the original 250 px .png http://i.imgur.com/pGWVj.png
Now in your view controller do this:
#import "ActivityViewCustomActivity.h"
And now wherever you want to display your UIActivityViewController
:
NSString *textItem = @"Check out the yourAppNameHere app: itunes http link to your app here";
UIImage *imageToShare = [UIImage imageNamed:@"anyImage.png"];
NSArray *items = [NSArray arrayWithObjects:textItem,imageToShare,nil];
ActivityViewCustomActivity *aVCA = [[ActivityViewCustomActivity alloc]init];
UIActivityViewController *activityVC =
[[UIActivityViewController alloc] initWithActivityItems:items
applicationActivities:[NSArray arrayWithObject:aVCA]];
activityVC.excludedActivityTypes = @[UIActivityTypePostToWeibo, UIActivityTypeAssignToContact, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeSaveToCameraRoll];
activityVC.completionHandler = ^(NSString *activityType, BOOL completed)
{
NSLog(@"ActivityType: %@", activityType);
NSLog(@"Completed: %i", completed);
};
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:activityVC];
CGRect rect = [[UIScreen mainScreen] bounds];
[self.popoverController
presentPopoverFromRect:rect inView:self.view
permittedArrowDirections:0
animated:YES];
}
else
{
[self presentViewController:activityVC animated:YES completion:nil];
}
How to add custom buttons to UIActivityViewController?
Well you have to create your own custom UIActivity, in your case for Instagram.
Have a look at this, even if the question is about on how to do it on iOS 6, the solution is exactly the same on iOS 7.
You can also have a look at this project on github, basically is a collection of custom UIActivity for the most common services Instagram included.
Adding an obvious (custom) button to UIActivityViewController
As nevo shalev said you need to subclass UIActivity class
Here is an example:
UrlActivity.h
#import <UIKit/UIKit.h>
@interface UrlActivity : UIActivity
@end
UrlActivity.m:
#import "UrlActivity.h"
@implementation UrlActivity
- (NSString *)activityType
{
return @"your Custom Type";
}
- (NSString *)activityTitle
{
return @"Title to display under your icon";
}
- (UIImage *)activityImage
{
return [UIImage imageNamed:@"your icon.png"];
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
// basically in your case: return YES if activity items are urls
}
- (void)prepareWithActivityItems:(NSArray *)activityItems
{
//open safari with urls (activityItems)
}
+(UIActivityCategory)activityCategory
{
return UIActivityCategoryShare; // says that your icon will belong in application group, not in the lower part;
}
@end
And in your main file (after importing UrlActivity.h):
#pragma mark - Share the link
- (IBAction)activityButtonPressed:(id)sender {
NSString *textToShare = @"I just shared this from my App";
// UIImage *imageToShare = [UIImage imageNamed:@"Image.png"];
NSURL *urlToShare = [NSURL URLWithString:@"http://www.google.com"];
NSArray *activityItems = [NSArray arrayWithObjects:textToShare, urlToShare,nil];
// create an array with your custom activity and add it to the activityVC
NSArray *appActivities = [NSArray arrayWithObjects:[[UrlActivity alloc] init]]];
UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:activityItems applicationActivities:appActivities];
//This is an array of excluded activities to appear on the UIActivityViewController
//activityVC.excludedActivityTypes = @[UIActivityTypeMessage, UIActivityTypeCopyToPasteboard,UIActivityTypeSaveToCameraRoll];
[self presentViewController:activityVC animated:TRUE completion:nil];
}
Related Topics
How to Remove the Bottom Gap of Uipageviewcontroller
How to Change an iOS Device Volume Programmatically
How to Register Undomanager in Swift
Game Engine Collison Bitmask... Why 0X01 etc
Swift Unsafemutablepointer<Unmanaged<Cfstring>> Allocation and Print
Rounding Uiimage and Adding a Border
Xcode:Why Launchoptions in Didfinishlaunchingwithoptions Always Nil
Using Two Versions of a Cocoapod Dependency
Document or Cache Path Changes on Every Launch in iOS 8
iOS 11 Search Bar Jumping to Top of Screen
Open an External Link in Safari (Cordova)
Makekeywindow VS Makekeyandvisible
How to Add Firebase to Today Extension iOS