iOS Second Screen - objective-c

I am using the PhoneGap ExternalScreen plugin, but I have modified it slightly to be able to support multiple resolutions. I got some tips from Matt Gemmel's post on iPadVGAOutput (http://mattgemmell.com/2010/06/01/ipad-vga-output/) Here is what my code looks like:
- (void) toggleResolution:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
self.callbackID = [arguments pop];
if ([[UIScreen screens] count] > 1){
externalScreen = [[[UIScreen screens] objectAtIndex:1] retain];
screenModes = [externalScreen.availableModes retain];
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"External Display Size"
message:#"Choose a size for the external display."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil] autorelease];
for (UIScreenMode *mode in screenModes){
CGSize modeScreenSize = mode.size;
[alert addButtonWithTitle:[NSString stringWithFormat:#"%.0f x %.0f pixels", modeScreenSize.width, modeScreenSize.height]];
}
[alert show];
} else {
PluginResult* pluginResult = [PluginResult resultWithStatus:PGCommandStatus_ERROR messageAsString:WEBVIEW_UNAVAILABLE];
[self writeJavascript: [pluginResult toErrorCallbackString:self.callbackID]];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIScreenMode *desiredMode = [screenModes objectAtIndex:buttonIndex];
externalScreen.currentMode = desiredMode;
externalWindow.screen = externalScreen;
[screenModes release];
CGRect rect = CGRectZero;
rect.size = desiredMode.size;
externalWindow.frame = rect;
externalWindow.clipsToBounds = YES;
externalWindow.hidden = NO;
[externalWindow makeKeyAndVisible];
PluginResult* pluginResult = [PluginResult resultWithStatus:PGCommandStatus_OK messageAsString:WEBVIEW_OK];
[self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
}
The resolution is changing just fine, but the content is not being constrained inside of the correct dimensions. An example is as follows:
When the second screen is originally loaded (at 1920x1080), it looks like this: http://cl.ly/F5IV
After changing the resolution to 1280x720, it looks like this: http://cl.ly/F41K
I am relatively new to Objective-C, but am quickly picking it up. Any pointers on solving my problem and/or improving the code altogether would be great. Thanks!
Andrew
EDIT: I also wanted to clarify, I am not manually setting any width/height on any of the views and/or CSS that is being displayed.

Since no one found it, I started to dig into the Objective-C and solved it. I had to add the following to the alertView method:
webView.frame = rect;

As your solution didn't work for me I'll put my solution to this here. I was getting the black bars around the view too although the screens dimension was detected right. I just had to set
[externScreen setOverscanCompensation: UIScreenOverscanCompensationInsetApplicationFrame];
and the bars were gone.

Related

Custom Spinner class with rotation animation problem

I programmed my own view containing an imageview which should be rotating. Here is my rotation animation:
- (void)startPropeller
{
//_movablePropeller = [[UIImageView alloc] initWithFrame:self.frame];
//_movablePropeller.image = [UIImage imageNamed:#"MovablePropeller"];
//[self addSubview:self.movablePropeller];
self.hidden = NO;
CABasicAnimation *rotation;
rotation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotation.fromValue = [NSNumber numberWithFloat:0.0f];
rotation.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
rotation.cumulative = true;
rotation.duration = 1.2f; // Speed
rotation.repeatCount = INFINITY; // Repeat forever. Can be a finite number.
[self.movablePropeller.layer removeAllAnimations];
[self.movablePropeller.layer addAnimation:rotation forKey:#"Spin"];
}
And here is how I start it:
self.loadingPropeller = [[FMLoadingPropeller alloc] initWithFrame:self.view.frame andStyle:LoadingPropellerStyleNoBackground];
self.loadingPropeller.center=self.view.center;
[self.view addSubview:self.loadingPropeller];
[self.loadingPropeller startPropeller];
Problem is: Without any further code. The propeller is not rotating. So I was able to solve it by adding this code into my class implementing to rotating propeller spinner:
-(void)viewDidAppear:(BOOL)animated
{
if(!self.loadingPropeller.hidden){
[self.loadingPropeller startPropeller];
}
}
But I don't like that too much. Isn't it possible to add some code within the Propeller class to solve this issue automatically, without having to add also code in every class in the viewDidAppear method?
The code that doesn't work does two essential things: adding the spinner to the view hierarchy and positioning it. My guess is that the failure is due to positioning it before layout has happened. Try this:
// in viewDidLoad of the containing vc...
self.loadingPropeller = [[FMLoadingPropeller alloc] initWithFrame:CGRectZero andStyle:LoadingPropellerStyleNoBackground];
[self.view addSubview:self.loadingPropeller];
// within or after viewDidLayoutSubviews...
// (make sure to call super for any of these hooks)
self.loadingPropeller.frame = self.view.bounds;
self.loadingPropeller.center = self.view.center;
// within or after viewDidAppear (as you have it)...
[self.loadingPropeller startPropeller];

While using ECSlidingViewController, why doesn't the underRightViewController animate correctly?

I am trying to implement ECSlidingViewController to perform a Zoom effect. While using underLeftViewController and anchorTopViewToRightAnimated, the effect is flawless and exceptional. However, I need to use underRightViewController and anchorTopViewToLeftAnimated in specific cases. When I do so, however, the same View Controller that worked flawlessly on the left acts unpredictable on the right. The views end up in basically the right places, but they do not animate at all. Here's my code for creating and setting up the ECSlidingViewController:
if (self.slidingViewController == nil)
{
self.fieldSearchController = [[FieldSearchTableViewController alloc] initWithNibName:#"FieldSearchTableViewController" bundle:nil];
self.filterVC = [[FieldSearchFilterTableViewController alloc] initWithNibName:#"FieldSearchFilterTableViewController" bundle:nil];
self.slidingViewController = [[ECSlidingViewController alloc] initWithTopViewController:self.fieldSearchController];
//self.slidingViewController.underLeftViewController = self.filterVC;
self.slidingViewController.underRightViewController = self.filterVC;
}
if (self.slidingViewController.parentViewController == nil)
{
[self addChildViewController:self.slidingViewController];
CGRect frame = self.view.bounds;
NSInteger topSize = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
frame.origin.y = topSize;
frame.size.height -= topSize;
self.slidingViewController.view.frame = frame;
[self.view addSubview:self.slidingViewController.view];
}
And here's the main code I am using for the top view:
//0 - Default
//1 - Fold
//2 - Zoom
//3 - Dynamic
NSDictionary *transitionData = self.transitions.all[0];
id<ECSlidingViewControllerDelegate> transition = transitionData[#"transition"];
if (transition == (id)[NSNull null]) {
super.slidingViewController.delegate = nil;
} else {
self.slidingViewController.delegate = transition;
}
NSString *transitionName = transitionData[#"name"];
if ([transitionName isEqualToString:METransitionNameDynamic]) {
self.slidingViewController.topViewAnchoredGesture = ECSlidingViewControllerAnchoredGestureTapping | ECSlidingViewControllerAnchoredGestureCustom;
self.slidingViewController.customAnchoredGestures = #[self.dynamicTransitionPanGesture];
[self.navigationController.view removeGestureRecognizer:self.slidingViewController.panGesture];
[self.navigationController.view addGestureRecognizer:self.dynamicTransitionPanGesture];
} else {
self.slidingViewController.topViewAnchoredGesture = ECSlidingViewControllerAnchoredGestureTapping | ECSlidingViewControllerAnchoredGesturePanning;
self.slidingViewController.customAnchoredGestures = #[];
[self.navigationController.view removeGestureRecognizer:self.dynamicTransitionPanGesture];
[self.navigationController.view addGestureRecognizer:self.slidingViewController.panGesture];
}
[self.slidingViewController anchorTopViewToLeftAnimated:YES];
This is not all of the code, but I think the problem is somewhere in one of these two blocks. Or maybe, the animate to the right just doesn't work like I think it should? I haven't seen any other examples using this approach so I might need to do some more customizations to the control, IDK.
Thanks for any help offered on this.
Short answer: you need to resetTopViewController first.
See: ECSlidingViewController 2 sliding from right to left

ContentOffset and back to Top issue

I have a scrollView with paging. I declare it:
if(_fullPosterScroll == nil) _fullPosterScroll = [[UIScrollView alloc] initWithFrame:rc];
[_fullPosterScroll setDelegate:self];
[_fullPosterScroll setBackgroundColor:[UIColor blackColor]];
[_fullPosterScroll setCanCancelContentTouches:NO];
_fullPosterScroll.indicatorStyle = UIScrollViewIndicatorStyleWhite;
_fullPosterScroll.clipsToBounds = NO;
_fullPosterScroll.pagingEnabled = YES;
_fullPosterScroll.alwaysBounceHorizontal = NO;
_fullPosterScroll.directionalLockEnabled = YES;
And after a tap i call a method:
[_fullPosterScroll setContentOffset:CGPointMake(_selectedPosterPosition*(_fullPosterScroll.frame.size.width), 0) animated:YES];
NSLog(#"%f",_fullPosterScroll.contentOffset.y);
Why after that in Log i have for example 225.00 ?! This should be 0!
I can't see anything wrong with the code you've posted, but you should check to make sure that setContentOffset isn't triggering any delegate methods that are changing offset.
Also, Apple have a sample project, PageControl, that does exactly what you want, so you should look at that if you want a complete example.

problem with changing view

hi I have a problem I made an application based on apples sample app called photoscroller and i want to add a login screen.but when i add it the showed view move upward 10-15 pixels and the main window is visible underneath.I ask why?
Parts of my code:
at view did load:
InfoViewController *infoView = [[InfoViewController alloc] initWithNibName:nil bundle:nil];
self.view = infoView.view;
[infoView release];
then later after validating the login:
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
pagingScrollView.delegate = self;
self.view = pagingScrollView;
...
I do not know why is pushed upward when i add other view.
thank for every answer
Could you past the method - (CGRect) frameForPagingScrollView, without that method it's bit harder to understand your code.
But i guess the self.view.frame and the CGRect returned from that method differ.
Further guess would be, that the difference are not 10-15 pixels, but 20 pixels (for the height of the UIStatusBar), which might be enabled in your .xib-File but is actually not displayed.

Leak when adding subview

So Instruments tells me I have three memory leaks originating in this method (specifically, it points out the line:
[self.view addSubview:menuBar.view];
I can't see a leak and am racking my brains. I'm keeping a reference to the menuBar object and am releasing it. Anyone smarter than me that can explain? Is it a coincidence that I have three menubar items in my XIB and I'm getting three leaks?
Here is the entire method:
//
root vc calls to toggle display state of menu bar on screen
-(IBAction) showToolBar {
//if no toolbar exists, create one and add it to the view
if (!menuBarView) {
MenuBarViewController *menuBar = [[MenuBarViewController alloc] initWithNibName:#"MenuBarViewController" bundle:nil];
menuBar.book = self.selectedTitleDeck;
menuBar.booksArray = self.allTitleDeck;
self.menuBarView = menuBar;
[self.view addSubview:menuBar.view];
[menuBar release];
}
CGRect frame = menuBarView.view.frame;
[UIView beginAnimations:nil context:NULL];
if (self.toolBarIsDisplayed == NO) {
//show the toolbar
frame.origin.y = 725;
self.toolBarIsDisplayed = YES;
} else if (self.toolBarIsDisplayed == YES) {
//hide the toolbar
frame.origin.y = 788;
self.toolBarIsDisplayed = NO;
}
self.menuBarView.view.frame = frame;
[UIView commitAnimations];
}
addSubview: retains the view passed into it (see the reference). Once you call addSubView, you can release that view, like:
MenuBarViewController *menuBar = [[MenuBarViewController alloc] initWithNibName:#"MenuBarViewController" bundle:nil];
menuBar.book = self.selectedTitleDeck;
menuBar.booksArray = self.allTitleDeck;
self.menuBarView = menuBar;
[self.view addSubview:menuBar.view];
[menuBar.view release];
[menuBar release];
}
Show us what happens in MenuBarViewController's dealloc method. I suspect you are forgetting to release its instance variables.
As suggested in the comments to my question, the problem was not in the code but in running my app in the simulator and trying to detect memory leaks.
When Instruments is run against the code on the device, no leaks are reported.
My consolation prize is a far more profound understanding of memory management unearthed in two days of trying to locate a leak that didn't exist.
Thanks to all for your advice, much appreciated.