Titanium Module: Passing Titanium.UI.Button into module to display UIPopoverController - titanium

I am developing a module which will work for both iPhone and iPad. In this module, I am trying to mimic UIActivityViewController and will display custom for both iPhone and iPad.
Problem: The Popover is displayed at top, left corner in iPad screen. The button from which I display Popup is created into Titanium SDK and I am passing the same Button as parameter into the module, which in turn, will use the same to display Popover at particular position.
Please check my code below: [The code is much bigger than the pasted code but I have simplified the code and pasted only the basics showing how my code works.]
Titanium Code:
root = {};
var w = Titanium.UI.createWindow({
top : 0,
left : 0,
right : 0,
bottom : 0,
navBarHidden : true,
orientationModes : [Ti.UI.PORTRAIT, Ti.UI.UPSIDE_PORTRAIT, Ti.UI.LANDSCAPE_LEFT, Ti.UI.LANDSCAPE_RIGHT]
});
w.open();
var shareItButton = Titanium.UI.createButton({
top : 10,
right : 40,
width: 90,
height: 30,
backgroundImage : 'images/shareit.png'
});
baseview.add(shareItButton);
// Display Popover when shareItButton is clicked
shareItButton.addEventListener('click', function(e) {
var ShareView = require('com.xyz.sharing');
root.shareController = ShareView.shareViewController; // The proxy controller
root.shareController.shareContent({
message: "Share Message",
url: "http://www.google.com",
title: "Share Title",
file: "File path for iBooks functionality",
shareButton: e.source // e.source is actually a button
});
});
Titanium Module: com.xyz.sharing
Module.h
#import "TiModule.h"
#interface ComXYZSharingModule : TiModule {
}
- (id) shareViewController;
#end
Module.m
#implementation ComXYZSharingModule
// Ignoring built-in methods, I have pasted only Custom methods
- (id) shareViewController {
ComXYZSharingProxy *proxy = [[ComXYZSharingProxy alloc] init];
proxy.module = self;
return proxy;
}
#end
Proxy.h
#interface ComXYZSharingProxy : TiProxy
#property (nonatomic, strong) ComXYZSharingModule *module;
#property (nonatomic, strong) NSDictionary *content;
#property (strong, nonatomic) TiViewProxy *exportView;
- (void) shareContent : (id) args;
#end
Proxy.m
#implementation ComXYZSharingProxy
- (void) shareContent : (id) args {
ENSURE_UI_THREAD(shareContent, args);
NSArray *val = args;
NSDictionary *dict = [val objectAtIndex: 0];
self.content = dict;
if ([dict objectForKey: #"shareButton"]) {
self.exportView = [dict objectForKey: #"shareButton"]; // This is the Button which gives me wrong values
NSLog(#"Button Found", nil);
NSLog([self.exportView description], nil);
CustomActivityController *controller = [[CustomActivityController alloc] init]; // We have just created the controller which is just customization of UIActivityViewController and that's the main view which will be displayed in Popover for iPad and in modal control for iPhone
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:controller];
//[self setPopoverController:popover];
//[popover setDelegate:self];
[popover setBackgroundColor: [UIColor greenColor]];
popover.popoverContentSize = CGSizeMake(320, 250);
CGRect rect = [TiUtils rectValue: [self.exportView rect]];
NSLog([NSString stringWithFormat: #"Size: x: %f,y: %f, width: %f, height: %f", rect.origin.x, rect.origin.y
, rect.size.width, rect.size.height], nil);
[popover presentPopoverFromRect:rect inView:[[TiApp app] controller].view permittedArrowDirections:arrowDirections animated:animated];
}
}
#end
Output when Program runs
Button Found
Size: x: 0.00,y: 0.00, width: 0.00, height: 0.00 [This should be actual size of Button but somehow it's not]
Due to this problem my Popover displays at top left corner of the iPad screen. Anyone would help to solve the issue? If I try to use TiUIButton or TiUIButtonProxy then also the result is same.

You're working too hard.
[popover presentFromRect:self.exportView.bounds
inView:self.exportView
permittedArrowDirections:arrowDirections
animated:animated];
The Ti.AirPrint module demonstrates this in action: https://github.com/appcelerator/titanium_modules/blob/master/airprint/mobile/ios/Classes/TiAirprintModule.m#L119

I just replaced following code
[popover presentPopoverFromRect:rect inView:[[TiApp app] controller].view permittedArrowDirections:arrowDirections animated:animated];
with
[popover presentPopoverFromBarButtonItem:[view barButtonItem] permittedArrowDirections:UIPopoverArrowDirectionAny animated: animated];
in shareContent function and this resolved my issue.

Related

Adding UISearchBar in UINavigationBar with constraints

All,
I want to add UISearchBar to UINavigationbar, I dont dont want to use UISearchController, Just UISearchbar programmatically and it must work in landscape as well.
I tried it is working well in Portrait well, but in Landscape, i have issues in iPhone X width. Can we use Constraints.
Below is the code
CGFloat width = [UIScreen mainScreen].bounds.size.width;
search = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, width - 2 * 44 - 2 * 15, 44)];
search.delegate = self; // search.tintColor = [UIColor redColor];
search.searchBarStyle = UISearchBarStyleMinimal;
search.placeholder = #"Search";
search.translucent = NO;
search.opaque = NO;
search.showsCancelButton = NO;
[search setBackgroundImage:[[UIImage alloc] init]];
//customize textfield inside UISearchBar
#try {
for (id object in [[[search subviews] firstObject] subviews])
{
if (object && [object isKindOfClass:[UITextField class]])
{
UITextField *textFieldObject = (UITextField *)object;
textFieldObject.backgroundColor = [UIColor whiteColor];
textFieldObject.borderStyle = UITextBorderStyleRoundedRect;
textFieldObject.layer.borderColor = (__bridge CGColorRef _Nullable)([brandingObj getValueForKey:navBarTitleColor]);
textFieldObject.layer.borderWidth = 1.0;
break;
}
}
}
#catch (NSException *exception) {
NSLog(#"Error while customizing UISearchBar");
}
#finally {
}
I don't understand why you want to use UISearchDisplayController, its highly configurable and recommended by apple, working with geometry (CGRecr, CGFrame, etc.) to adjust UIKit objects layout could be a pain, use auto layout avoiding UIKits convenience initializers, to adjust later constraints.
Anyway if you want explicitly do with this way, this should work.
#import "ViewController.h"
#interface ViewController ()<UISearchBarDelegate>
#property UISearchBar *searchbar;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_searchbar = [UISearchBar new];
_searchbar.delegate = self;
_searchbar.searchBarStyle = UISearchBarStyleMinimal;
self.navigationItem.titleView = self.searchbar;
// Do any additional setup after loading the view, typically from a nib.
}
Maybe you should need configure appearance , take a look here
Cheers.

Try to add UIFont to XCode project

I try to add OpenSans-Regular.ttf to my Xcode project:
1)I add the file into the project.
2) add font in plist.
3)check if the file add to Bundle resources
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *myLable = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 50)];
myLable.text = #"TEST RR";
[myLable setFont:[UIFont fontWithName:#"OpenSans-Regular" size:30]];
myLable.textColor = [UIColor whiteColor];
myLable.backgroundColor = [UIColor blackColor];
[self.view addSubview:myLable];
NSLog (#"Font families: %#", myLable.font.familyName);
}
and the font not work !
As suggested by #keyur bhalodiya you have to use the font name like #"OpenSnas" for regular fonts
Create a custom label subclass of UILabel 'CustomFontLabel'
in CustomFontLabel.h define property to set the font name
#interface CustomFontLabel : UILabel
#property (nonatomic) IBInspectable NSString *overrideFontName;
#end
In the .m file add the below code
- (void)setOverrideFontName:(NSString *)overrideFontName
{
if (![_overrideFontName isEqualToString:overrideFontName])
{
_overrideFontName = overrideFontName;
self.font = self.font;
}
}
- (void)setFont:(UIFont *)font
{
NSString *overrideFontName = self.overrideFontName;
if (overrideFontName != nil)
{
font = [UIFont fontWithName:overrideFontName size:font.pointSize];
}
[super setFont:font];
}
With the IBInspectable you can even set the overrideFontName property from Storyboard also. Don't forget to set the label class to CustomLabel in the storyboard. Try that and let me know, if it's working or not..!

BannerView not showing iAd

I have gone through many tutorials and believe have done everything, but still can not figure it out, the bannerview does not show ad anytime, I have even put log messages in bannerViewDidLoadAd, didFailToReceiveAdWithError , but those do not get displayed also. Here is the code
I have registered my account in iTunesConnect under monetize, but tax information is pending.Also my app runs only in potrait mode, so no need to handle landscape.
In .h file :
#import <UIKit/UIKit.h>
#import <iAd/iAd.h>
#interface MBViewController : UIViewController <ADBannerViewDelegate>
#property (strong, nonatomic) ADBannerView *bannerView;
#end
In .m file :
- (void)viewDidLoad
{
[super viewDidLoad];
_bannerView = [[ADBannerView alloc] initWithFrame:CGRectZero];
_bannerView.delegate = self;
_bannerView.hidden = YES;
[self.view addSubview:_bannerView];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(#"bannerViewDidLoadAd");
CGRect bannerFrame = CGRectMake(0.0, (self.view.frame.size.height - 50), 0.0, 0.0);
[self.bannerView setFrame:bannerFrame];
self.bannerView.hidden = NO;
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(#"Error receive ad: %#", error);
self.bannerView.hidden = YES;
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner
willLeaveApplication:(BOOL)willLeave
{
return YES;
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
}
What about giving a size to your bannerView ?
From your code:
_bannerView = [[ADBannerView alloc] initWithFrame:CGRectZero];
Width = 0, Height = 0
And here you just update the position:
CGRect bannerFrame = CGRectMake(0.0, (self.view.frame.size.height - 50), 0.0, 0.0);
Width = 0, Height = 0
I had the same problem. I ended up going to iTunes Connect, and clicked on the iAd section. Then I agreed to some contract and went to the iAd Workbench area. There, I didn't bother doing anymore because I'm not at the point where I want to advertise the game I'm developing yet.
I didn't change any code, but my iOS game was still running. To my surprise, the ads started to show up right after I agreed to the iAd agreement in iTunes Connect!

Does it make sense to add ATMHud to tabBarController.view

When i try to add ATMHud to uitableviewcontroller subview it does work but it doesn't disable the scrolling and if the tableview is not on top i can't see the hud view. What i did was added to teh tabBarController.view that works but i want find out if this is a good idea or later on i might have issues with it.
Another question is tabBarController.view frame is that the whole screen or just the bottom part. How come atmhud shows in the middle of the screen?
Thanks in advance!
Yan
============
Found a blog post that shows how to reset self.view and add tableview separately in uitableviewcontroller
UITableViewController and fixed sub views
- (void)viewDidLoad {
[super viewDidLoad];
if (!tableView &&
[self.view isKindOfClass:[UITableView class]]) {
tableView = (UITableView *)self.view;
}
self.view = [[[UIView alloc] initWithFrame:
[UIScreen mainScreen].applicationFrame] autorelease];
self.tableView.frame = self.view.bounds;
self.tableView.contentInset = UIEdgeInsetsMake(44.0, 0.0, 0.0, 0.0);
[self.view addSubview:self.tableView];
UIView *fixedBar = [[UIView alloc] initWithFrame:
CGRectMake(0.0, 0.0, self.view.bounds.size.width, 44.0)];
fixedBar.backgroundColor = [UIColor colorWithRed:
0.0 green:1.0 blue:0.0 alpha:0.7];
[self.view addSubview:fixedBar];
[fixedBar release];
}
After this when add hud to self.view you will be able to disable the tableview on the bottom.
Let me know if this a good way to setup the tableview
The problem with using the tab bar is that the hud is now modal, and the user cannot change the tab.
It sounds like the tableview is not your primary viewm, as it can get "covered up". If its not the primary view, then add the ATMHud to self.view. If the tableView is the same as self.view, then add a new transparent view to it, then add the HUD to that view.
The tabBarController.view is the view that hosts the tabbed views - if you want to see its size (or frame) log it using NSStringFromCGRect(self.tabBarController.frame);
EDIT: I just did a test, the ATMHud DOES block the UI. All I can think of is that you have not inserted it where you need to (at the top of current view's subviews.) I have a demo project where I do this:
hud = [[ATMHud alloc] initWithDelegate:self];
[self.view addSubview:hud.view];
[hud setCaption:#"Howdie"];
[hud setActivity:YES];
[hud show];
[hud hideAfter:5];
A button under the hud is not active - in fact nothing in the view is active (probably the Nav Bar would be live though)
If you want an ARCified and field tested version, you can grab it here
EDIT2: The solution to your problem is below. Note that ATMHud blocks clicks from getting to the table, and the code below stops the scrolling:
- (void)hudWillAppear:(ATMHud *)_hud
{
self.tableView.scrollEnabled = NO;
}
- (void)hudDidDisappear:(ATMHud *)_hud
{
self.tableView.scrollEnabled = YES;
}
Dump the views:
#import <QuartzCore/QuartzCore.h>
#import "UIView+Utilities.h"
#interface UIView (Utilities_Private)
+ (void)appendView:(UIView *)v toStr:(NSMutableString *)str;
#end
#implementation UIView (Utilities_Private)
+ (void)appendView:(UIView *)a toStr:(NSMutableString *)str
{
[str appendFormat:#" %#: frame=%# bounds=%# layerFrame=%# tag=%d userInteraction=%d alpha=%f hidden=%d\n",
NSStringFromClass([a class]),
NSStringFromCGRect(a.frame),
NSStringFromCGRect(a.bounds),
NSStringFromCGRect(a.layer.frame),
a.tag,
a.userInteractionEnabled,
a.alpha,
a.isHidden
];
}
#end
#implementation UIView (Utilities)
+ (void)dumpSuperviews:(UIView *)v msg:(NSString *)msg
{
NSMutableString *str = [NSMutableString stringWithCapacity:256];
while(v) {
[self appendView:v toStr:str];
v = v.superview;
}
[str appendString:#"\n"];
NSLog(#"%#:\n%#", msg, str);
}
+ (void)dumpSubviews:(UIView *)v msg:(NSString *)msg
{
NSMutableString *str = [NSMutableString stringWithCapacity:256];
if(v) [self appendView:v toStr:str];
for(UIView *a in v.subviews) {
[self appendView:a toStr:str];
}
[str appendString:#"\n"];
NSLog(#"%#:\n%#", msg, str);
}
#end

UIPageControl doesn't properly react to taps

In my TestApp, I created a class "Carousel" which should let me create a swipe menu with a UIPageControl in an easy way (by simply creating an instance of the class Carousel).
Carousel is a subclass of UIView
At init, it creates an UIView, containing UIScrollView, UIPageControl
I can add further UIViews to the scroll view
I don't know if this is the proper way to do it, but my example worked quite well in my TestApp. Swiping between pages works perfectly and the display of the current page in the UIPageControl is correct.
If there were not one single problem: The UIPageControl sometimes reacts to clicks/taps (I only tested in Simulator so far!), sometimes it doesn't. Let's say most of the time it doesn't. I couldn't find out yet when it does, for me it's just random...
As you can see below, I added
[pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventValueChanged];
to my code. I thought this would do the proper handling of taps? But unfortunately, pageChange doesn't get always called (so the value of the UIPageControl doesn't change every time I click).
I would appreciate any input on this because I couldn't find any solution on this yet.
This is what I have so far:
Carousel.h
#import <UIKit/UIKit.h>
#interface Carousel : UIView {
UIScrollView *scrollView;
UIPageControl *pageControl;
BOOL pageControlBeingUsed;
}
- (void)addView:(UIView *)view;
- (void)setTotalPages:(NSUInteger)pages;
- (void)setCurrentPage:(NSUInteger)current;
- (void)createPageControlAt:(CGRect)cg;
- (void)createScrollViewAt:(CGRect)cg;
#end
Carousel.m
#import "Carousel.h"
#implementation Carousel
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Create a scroll view
scrollView = [[UIScrollView alloc] init];
[self addSubview:scrollView];
scrollView.delegate = (id) self;
// Init Page Control
pageControl = [[UIPageControl alloc] init];
[pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventValueChanged];
[self addSubview:pageControl];
}
return self;
}
- (IBAction)pageChange:(id)sender {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * pageControl.currentPage;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:TRUE];
NSLog(#"%i", pageControl.currentPage);
}
- (void)addView:(UIView *)view {
[scrollView addSubview:view];
}
- (void)createPageControlAt:(CGRect)cg {
pageControl.frame = cg;
}
- (void)setTotalPages:(NSUInteger)pages {
pageControl.numberOfPages = pages;
}
- (void)setCurrentPage:(NSUInteger)current {
pageControl.currentPage = current;
}
- (void)createScrollViewAt:(CGRect)cg {
[scrollView setPagingEnabled:TRUE];
scrollView.frame = cg;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width*pageControl.numberOfPages, scrollView.frame.size.height);
[scrollView setShowsHorizontalScrollIndicator:FALSE];
[scrollView setShowsVerticalScrollIndicator:FALSE];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
float frac = scrollView.contentOffset.x / scrollView.frame.size.width;
NSUInteger page = lround(frac);
pageControl.currentPage = page;
}
#end
ViewController.m (somewhere in viewDidLoad)
Carousel *carousel = [[Carousel alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
for (int i=0; i<5; i++) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(i * 320, 0, 320, 420)];
UIColor *color;
if(i%3==0) color = [UIColor blueColor];
else if(i%3==1) color = [UIColor redColor];
else color = [UIColor purpleColor];
view.backgroundColor = color;
[carousel addView:view];
view = nil;
}
[carousel setTotalPages:5];
[carousel setCurrentPage:0];
[carousel createPageControlAt:CGRectMake(0,420,320,40)];
[carousel createScrollViewAt:CGRectMake(0,0,320,420)];
Your code is correct. Most likely the frame of your pageControl is pretty small, so theres not a lot of area to look for touch events. You would need to increase the size of the height of pageControl in order to make sure taps are recognized all of the time.