I've subclassed a UINavigationController by adding a UICollectionViewController as a child view controller when I init the subclass:
-(id)init{
self = [super init];
if(self){
UICollectionViewController *collectionViewController = [[UICollectionViewController alloc] initWithCollectionViewLayout:[self getLayout]];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelPressed)];
collectionViewController.navigationItem.rightBarButtonItem = cancelItem;
[self addChildViewController:collectionViewController];
}
return self;
}
To initialize the layout I call the getLayout method:
- (UICollectionViewFlowLayout *)getLayout {
CGFloat itemWidth = self.view.frame.size.width;
CGSize itemSize = CGSizeMake(itemWidth, itemWidth);
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:itemSize];
return flowLayout;
}
However, when I use this code no navigation bar items are shown for iOS 7 apps (iOS 8 still works). However, if I change the line:
CGFloat itemWidth = self.view.frame.size.width;
to
CGFloat itemWidth = [[UIScreen mainScreen] bounds].size.width;
All works well. Both lines return the same value. Any ideas why this is happening?
Related
how to change the width of the UIPickerView in objective C, I am using the following code,
tempFiled = Data;
[tempFiled resignFirstResponder];
CGSize sizeOfPopover = CGSizeMake(200, 200);
CGPoint positionOfPopover = CGPointMake(32, 325);
[popOverControllerWithPicker presentPopoverFromRect:CGRectMake(positionOfPopover.x, positionOfPopover.y+10, 500, sizeOfPopover.height)
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
But when i am trying to change the width in CGSize sizeOfPopover = CGSizeMake(200, 200); its not changing, i want to reduce the size of the picker.
I had this problem and solved it this way:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGRect frame = bpsPicker.frame;
frame.size.width = 100; // width to be displayed on popover controller
bpsPicker.frame = frame;
}
Using ViewDidLoad() is too early to alter this value.
To be clear the viewWillAppear is in the UIViewController that is passed to the UIPopover (here called 'MyViewController.m').So,
self.myViewController = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil] ;
self.myViewController.delegate = self;
self.myViewController.contentSizeForViewInPopover = CGSizeMake(320, 360); // or whatever
self.myViewControllerPopover = [[UIPopoverController alloc] initWithContentViewController:self.myViewController] ;
[self.myViewControllerPopover presentPopoverFromBarButtonItem:self.myToolBarButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
I am showing a UIImagePicker (itself in a UIView) via a UIPopOver. This works fine, however when the iPad is rotated onto its right side I get a strange black bar along the left hand side of the popover as per the image below. The cancel button is also partially off the right hand of the screen. This doesn't happen in any other orientation which is odd.
The code is also listed below. Can anyone suggest why I am getting this black bar ?
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
UIViewController *containerController = [[UIViewController alloc] init];
containerController.contentSizeForViewInPopover = CGSizeMake(width, height);
[imagePickerController.view setFrame:containerController.view.frame];
[containerController.view addSubview:imagePickerController.view];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
Class cls = NSClassFromString(#"UIPopoverController");
if (cls != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:containerController];
[popoverController presentPopoverFromRect:selectedRect inView:self.view permittedArrowDirections:4 animated:YES];
[containerController release];
}
For some strange reason, the view's frame does change in landscape right.
To come over this, set the frame after you present the popover (view code below).
That should do the trick.
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
UIViewController *containerController = [[UIViewController alloc] init];
containerController.contentSizeForViewInPopover = CGSizeMake(width, height);
[containerController.view addSubview:imagePickerController.view];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
Class cls = NSClassFromString(#"UIPopoverController");
if (cls != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:containerController];
[popoverController presentPopoverFromRect:selectedRect inView:self.view permittedArrowDirections:4 animated:YES];
[imagePickerController.view setFrame:containerController.view.frame];
[containerController release];
}
Also, in your controller, add this to reset the frames when the rotation occurs:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[imagePickerController.view setFrame:imagePickerController.view.superview.frame];
}
The above approach works with iOS 5 and above but on iOS 4 and prior it's not possible to add the UIImagePickerController as a subview and then show it. It always has to be presented as a ModalViewController.
Try this. Reposting one solution I found using [currentDevice endGeneratingDeviceOrientationNotifications]
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self;
// Display the camera.
[self presentModalViewController:picker animated:YES];
// Given by default your orientation is in landscape right already
while ([currentDevice isGeneratingDeviceOrientationNotifications])
[currentDevice endGeneratingDeviceOrientationNotifications];
Source: Disable rotation in UIImagePicker
I created view-based application.
I have got a sampleGameViewContrioller.xib, which contains main View, and child View, which connected with class Behavior.
SampleViewController.xib:
View
View <- Behavior
In sampleViewContoller.m I create instance of the class Behavior:
Behavior *b = [[Behavior alloc] initilizeWithType:#"type" position:rect mapArray:arrMap];
Behavior.m:
-(id) initilizeWithType:(NSString *)type position:(CGRect) pos mapArray:(NSMutableArray *) mapArr {
self = [super initWithFrame:CGRectMake(0, 0, 1024, 570)];
if (self != nil) {
if ([type isEqualToString:#"type"]) {
arrMap = mapArr;
self.rectForDraw = pos;
self.file = [[NSString alloc]initWithString:#"girl.png"];
UIImageView *imgg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"girl.png"]];
imgg.frame = rect;
[self addSubview:imgg];
timer = [NSTimer scheduledTimerWithTimeInterval:0.015 target:self selector:#selector(moving:) userInfo:nil repeats:YES];
}
}
return self;}
But it doesn't work. Image doesn't add to my View.
if I add imageView in -(void)drawRect:(CGRect) rect, it's working:
- (void)drawRect:(CGRect)rect {
self.img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"girl.png"]];
self.img.frame = CGRectMake(100, 100, 100, 100);
[self addSubview:self.img]; }
But i should send parameters of drawing in class Behavior through constructor. How to add imageView without method drawRect, with my constructor?
sorry for my English :)
If u want to add an image view over simple UIView then just do [self.view addSubview:imageview]; If you are getting that Image from Behaviour class method then return UIImageView from that method and the add it to your view
Try this:
Behavior *b = [[Behavior alloc] init];
Then write one method in Behaviour class
-(UIImageView*) initilizeWithType:(NSString *)type position:(CGRect) pos mapArray:(NSMutableArray *) mapArr {
// Your Logic
return imgView; //UIImageView object
}
Then call this method in your viewcontroller as
UIImageView *imgView=[b initilizeWithType:#"YOUR STRING" position:YOUR RECT pos mapArray:YOUR ARRAY ];
imgg.frame = rect;
This line assigns your imageView frame to... nothing as far as I can see. Should this be pos or rectForDraw? When adding to your view in drawRect you are explicitly setting a real frame so this is probably where the difference lies.
I have a very tricky problem and after long searching (google, stackoverflow, ...) i didn't get the solution that works for me.
Let me introduce you in my current choosen architecture:
I have a a AppDelegate, which has a UIView that contains a UINavigationController and the application didFinishLaunchingWithOptions: contains:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 400)];
UIViewController *myController = [[UIViewController alloc] init];
myController.view = myView;
FSCScrumRootView * myRootView = [[FSCScrumRootView alloc] initWithNibName:#"FSCScrumRootView" bundle:[NSBundle mainBundle]];
[myController.view addSubview:myRootView.navigation.view];
[self.window addSubview:myController.view];
[self.window makeKeyAndVisible];
return YES;
}
In my FSCScrumRootView (inherits from UIViewController) i init the view like this:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.navigation = [[[UINavigationController alloc] init] autorelease];
self.scrumProjectsList = [[[FSCScrumProjectListView alloc] init] initWithNibName:#"FSCScrumProjectListView" bundle:nil];
[navigation pushViewController:scrumProjectsList animated:YES];
[navigation view];
}
return self;
}
In my FSCScrumProjectListView (it is inherited from UITableViewController) i have implemented the viewDidLoad as following:
- (void)viewDidLoad
{
[super viewDidLoad];
//Set the title
self.navigationItem.title = #"Scrum Projects";
UIBarButtonItem *myRefreshButton = [[[UIBarButtonItem alloc] initWithTitle:#"Refresh" style:UIBarButtonSystemItemRefresh target:self action:#selector(refreshList)] autorelease];
self.navigationItem.leftBarButtonItem = myRefreshButton;
UIBarButtonItem *myLogoutButton = [[UIBarButtonItem alloc] initWithTitle:#"Logout" style:UIBarButtonSystemItemCancel target:self action:#selector(logout)];
self.navigationItem.rightBarButtonItem = myLogoutButton;
//Initialize the toolbar
toolbar = [[UIToolbar alloc] init];
toolbar.barStyle = UIBarStyleDefault;
//Set the toolbar to fit the width of the app.
[toolbar sizeToFit];
//Caclulate the height of the toolbar
CGFloat toolbarHeight = [toolbar frame].size.height;
//Get the bounds of the parent view
CGRect rootViewBounds = self.parentViewController.view.bounds;
//Get the height of the parent view.
CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds);
//Get the width of the parent view,
CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds);
//Create a rectangle for the toolbar
CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight, rootViewWidth, toolbarHeight);
//Reposition and resize the receiver
[toolbar setFrame:rectArea];
//Create a button
UIBarButtonItem *infoButton = [[UIBarButtonItem alloc]
initWithTitle:#"Info" style:UIBarButtonItemStyleBordered target:self action:#selector(info_clicked:)];
[toolbar setItems:[NSArray arrayWithObjects:infoButton,nil]];
//Add the toolbar as a subview to the navigation controller.
[self.navigationController.view addSubview:toolbar];
//Reload the table view
[self.tableView reloadData];
}
This results finally in the following screen (as i'd like to have it):
View iOS Mockup of current result
The Problem:
My Problem now is, that i can click ONLY on the Refresh Button. The other two buttons (Info and Logout) cannot be clicked. And i don't understand why? What I am doing wrong here?
Your help is kindly appreceated!
Try autoreleasing the second two buttons like your first one (the refresh).
UIBarButtonItem *myLogoutButton = [[[UIBarButtonItem alloc] initWithTitle:#"Logout" style:UIBarButtonSystemItemCancel target:self action:#selector(logout)]autorelease];
UIBarButtonItem *infoButton = [[[UIBarButtonItem alloc]
initWithTitle:#"Info" style:UIBarButtonItemStyleBordered target:self action:#selector(info_clicked:)]autorelease];
People, i have found the reason for my problem and i have to say, it was a very very silly one.
The first line of this project was responsible for all the troubels:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 400)];
Since the View i created there is only sized 200x400, it is to small to recognize any events that appear in the outside of this view (although everything is visible).
If i change the size of this view, all works as expected:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 500)];
But the more dynamic solution would probably be:
CGRect cgRect =[[UIScreen mainScreen] bounds];
CGSize cgSize = cgRect.size;
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cgSize.width, cgSize.height)];
Maybe there is an even better solution for getting the dynamic screen size?
I create a custom view in cocoa touch that is superclassed by UIView and in my main controller I initialize it and then add it as a subview to the main view, but when I add it to the main view it calls my initializer method again and causes an infinite loop. Am I going about creating my custom view wrong?
Here is the mainView
- (void)loadView {
UIImage* tempImage = [UIImage imageNamed: #"image1.jpg"];
CustomImageContainer *testImage = [[CustomImageContainer alloc] initWithImage: tempImage andLabel: #"test image" onTop: true atX: 10 atY: 10];
[self.view addSubview: testImage];
}
and the CustomImageContainer
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
imageview_to_add.frame = CGRectMake(0, 0, imageToAdd.size.width, imageToAdd.size.height);
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
[self addSubview: imageview_to_add];
self.frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
//[self addSubview: label_to_add];
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
[super init];
return self;
}
Why did you put the [super init] statement at the end of the initializer ? When subclassing, you usually put this statement at the start of method.
For UIView subclasses, the designated initializer when creating views in code is initWithFrame:, so you should call it before adding the label and the image. You can use the image to compute the frame needed by the custom view.
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
// The view will gets its frame to the size of the image
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
// Call the designated initializer
CGRect frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
self = [super initWithFrame:frame];
[self addSubview: imageview_to_add];
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
return self;
}
If you still have an infinite loop, pause the debugger and search for the recurrent method pattern in the stack trace. This pattern will gives you where the code enters the infinite loop.