Whenever we show popover the neighbhouring areas show different kind of gray color and the active tab bar icon color changes from blue to gray till pop over is there.
when the popover is dismissed , the grey shade gets removed
I would like to remove the color when the the popover is visible
I googled but I couldn't find anyway seems like this default behaviour.
any help to help me fix the problem is appreciated
Thanks
For achieve this, you can create own custom popover background of UIPopoverBackgroundView.
you can find the below code for creating custom CustomPopoverBgView.
CustomPopoverBgView.h
#import <UIKit/UIKit.h>
#interface CustomPopoverBgView : UIPopoverBackgroundView
{
UIImageView *_borderImageView;
UIImageView *_arrowView;
CGFloat _arrowOffset;
UIPopoverArrowDirection _arrowDirection;
}
#end
CustomPopoverBgView.m
#import "CustomPopoverBgView.h"
#define CONTENT_INSET 10.0
#define CAP_INSET 25.0
#define ARROW_BASE 25.0
#define ARROW_HEIGHT 25.0
-(instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
self.layer.shadowColor = [[UIColor clearColor] CGColor];
_borderImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"popover-bg.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(CAP_INSET,CAP_INSET,CAP_INSET,CAP_INSET)]];
_arrowView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrow.png"]];
[self addSubview:_borderImageView];
[self addSubview:_arrowView];
}
return self;
}
+(UIEdgeInsets)contentViewInsets{
return UIEdgeInsetsMake(CONTENT_INSET, CONTENT_INSET, CONTENT_INSET, CONTENT_INSET);
}
+(CGFloat)arrowHeight{
return ARROW_HEIGHT;
}
+(CGFloat)arrowBase{
return ARROW_BASE;
}
- (CGFloat) arrowOffset {
return _arrowOffset;
}
- (void) setArrowOffset:(CGFloat)arrowOffset {
_arrowOffset = arrowOffset;
}
- (void)setArrowDirection:(UIPopoverArrowDirection)arrowDirection {
_arrowDirection = arrowDirection;
}
- (UIPopoverArrowDirection)arrowDirection {
return _arrowDirection;
}
#end
Calling of CustomPopoverBgView in UIPopoverController
UIButton *btn = (UIButton *)sender;
ViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"dddddd"];
controller.view.backgroundColor = [UIColor redColor];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:controller] ;
popoverController.popoverBackgroundViewClass = [CustomPopoverBgView class];
[popoverController presentPopoverFromRect:btn.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:true];
Hope this will help you.
Create your own custom popover view and add it as a subview on top of your main view instead of the default one Apple provided.
Related
I want to make a reddish translucent UINavigationBar (for iOS9), and I found that the following codes are essential:
navController.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
navController.navigationBar.shadowImage = UIImage()
navController.navigationBar.backgroundColor = UIColor(red: 1.0,green: 0.3,blue: 0.3,alpha: 0.9)
navController.navigationBar.translucent = true
It works fine if I simply created a UINavigationBar (instead of creating a UINavigationController), but it looks like this as I created a UINavigationController.
enter image description here
I found the culprit to be the line navController.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
, but if I remove it, the bar looks like this:
enter image description here
So how can I solve this problem? (I'm creating the UINavigationController programmatically and sorry for the inconvenience that I cannot imbed images)
Edit:
You need to subclass the UINavigationBar in order to get the translucent background of desired color. Have a look at this answer:
https://stackoverflow.com/a/19043174/2082569
Adding necessary code here too for reference:
#interface UnderlayNavigationBar : UINavigationBar
#end
#interface UnderlayNavigationBar ()
{
UIView* _underlayView;
}
- (UIView*) underlayView;
#end
.
#implementation UnderlayNavigationBar
- (void) didAddSubview:(UIView *)subview
{
[super didAddSubview:subview];
if(subview != _underlayView)
{
UIView* underlayView = self.underlayView;
[underlayView removeFromSuperview];
[self insertSubview:underlayView atIndex:1];
}
}
- (UIView*) underlayView
{
if(_underlayView == nil)
{
const CGFloat statusBarHeight = 20; // Make this dynamic in your own code...
const CGSize selfSize = self.frame.size;
_underlayView = [[UIView alloc] initWithFrame:CGRectMake(0, -statusBarHeight, selfSize.width, selfSize.height + statusBarHeight)];
[_underlayView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[_underlayView setBackgroundColor:[UIColor colorWithRed:1.0f green:0.3f blue:0.3f alpha:1.0f]];
[_underlayView setAlpha:0.7f];
[_underlayView setUserInteractionEnabled:NO];
}
return _underlayView;
}
#end
.
UIViewController* rootViewController = ...;
UINavigationController* navigationController = [[UINavigationController alloc] initWithNavigationBarClass:[UnderlayNavigationBar class] toolbarClass:nil];
[navigationController setViewControllers:#[rootViewController]];
I have a GameOver UIView that I call from inside my main UIViewController. It is just a 'popover' window that has the text game over, the score, and some blur effects to blur the main UIViewcontroller.
I try to pass an int to the UIView, but it doesn't accept it unless it is in the - (void)drawRect:(CGRect)rect method.
If I move the score label to drawRect method, the label is updated. But the blur effects go away.
What am I doing wrong?
MainViewController.m
#import "GameOverView.h"
#interface ViewController () {
GameOverView * gov;
}
- (void) showGameOver {
gov = [[GameOverView alloc] initWithFrame:self.view.bounds];
NSLog(#"Passing score of: %i", self.score);
gov.finalScore = self.score;
[self.view addSubview:gov];
}
GameOverView.h
#interface GameOverView : UIView {}
#property (nonatomic) int finalScore;
#end
GameOverView.M
#implementation GameOverView
- (id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//self.backgroundColor = [UIColor redColor];
NSLog(#"Score:%i", self.finalScore );
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = super.bounds;
[super addSubview:visualEffectView];
UILabel * lblGameOver = [[UILabel alloc] initWithFrame:CGRectMake(0,0, frame.size.width, 200)];
lblGameOver.center = CGPointMake(frame.size.width/2, 100);
lblGameOver.text = [NSString stringWithFormat: #"GAME OVER %i", self.finalScore];
[self addSubview:lblGameOver];
UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, 200)];
button.center = CGPointMake(frame.size.width/2, 200);
[button setTitle:#"Start New Game" forState:UIControlStateNormal];
[button addTarget:self action:#selector(removeSelfFromSuperview) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
return self;
}
- (void) removeSelfFromSuperview{
[self removeFromSuperview];
}
You are using the finalScore property in the init method of the GameOverView class, but you are only setting its value after initializing it.
Change your initialization method to
- (id) initWithFrame:(CGRect)frame finalScore:(int)fs{
// use 'fs' instead of 'self.finalScore'
}
It should work.
I wonder how there isn't any problem with the view background color. You are initializing the view and adding it as subview like this:
gov = [[GameOverView alloc] initWithFrame:self.view.bounds];
gov.finalScore = self.score;
[self.view addSubview:gov];
This will give the view background color as black which is default color. So you don't find much difference if you use blur effect.
you need to give the color for the view during the initialization :
gov = [[GameOverView alloc] initWithFrame:self.view.bounds];
[gov setBackgroundColor:[UIColor yourColor]];
[self.view addSubview:gov];
If you are planning to keep the code in initWithFrame, you don't need to worry about setting the background color. If you keep the code in drawRect, then you must set the background color,else it will be black color.
When coming to setting the score label, it doesn't matter whether you put it in drawRect or initWithFrame method. Make sure you use drawRect method only if you really have to draw on the view,so that you can call it later by using setNeedsDisplay
I am trying to change self.navigationController.toolbar position to top instead of a bottom.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIToolbarDelegate, UIBarPositioningDelegate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
// View did load
- (void)viewDidLoad
{
// Superclass view did load method call
[super viewDidLoad];
// UIToolbarDelegate
self.navigationController.toolbar.delegate = self;
}
- (void)viewDidLayoutSubviews
{
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.frame = CGRectMake(self.navigationController.toolbar.frame.origin.x, 64.0f, self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height);
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(50.0f, 10.0f, 220.0f, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
}
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
The position changes at first, but later gets back to the bottom. Please, help me!
First make sure that toolbar delegate method positionForBar: is get called. If not, then your toolbar delegate is not properly set and you've have to define the UIToolbarDelegate protocol inside your header class.
#interface ExampleViewController : UIViewController <UIToolbarDelegate>
...
#end
Then set the delegate and also change the frames for toolbar. However, for the orientation you might have to reconsider the frames of toolbar.
#implementation ExampleViewController
- (void)viewDidLoad {
[super viewDidLoad];
// set the toolbar delegate
self.navigationController.toolbar.delegate = self;
self.navigationController.toolbarHidden = NO;
// create a toolbar child items
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.with, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
// set the frames
CGRect toolbarFrame = self.navigationController.toolbar.frame;
toolbarFrame.origin.y = self.navigationController.frame.size.height;
self.navigationController.toolbar.frame = toolbarFrame;
}
// pragma mark - UIToolbarDelegate
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
In your viewDidLoad method, add:
self.navigationController.toolbar.delegate = self;
I have a UINavigationController to which I need to add a second UINavigationBar. Neither of those bars is translucent. Problem is, view controllers that I put inside this navigation controller are partially covered by my second navigation bar. Where do I adjust the frames of those view controllers' views so that I don't get a "blinking" effect of them changing frames while being visible?
EDIT:
This is in viewDidLoad:
UINavigationBar *secondaryNavBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 50)];
secondaryNavBar.translucent = NO;
if ([secondaryNavBar respondsToSelector:#selector(setBarTintColor:)]) { //it has to work on iOS 6 as well
secondaryNavBar.barTintColor = [UIColor darkGrayColor];
secondaryNavBar.tintColor = [UIColor whiteColor];
}
else {
secondaryNavBar.tintColor = [UIColor darkGrayColor];
}
[self.view addSubview:secondaryNavBar];
self.secondaryNavBar = secondaryNavBar;
Here's a working solution. Certainly not the best, and I did not make it to support iOS 6, you'll have to work on it and test it.
CustomNavigationController.m :
#implementation CustomNavigationController {
UINavigationBar *bottomNavBar;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self showNavBar];
}
- (void)showNavBar {
UINavigationBar *secondaryNavBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 50)];
secondaryNavBar.translucent = NO;
if ([secondaryNavBar respondsToSelector:#selector(setBarTintColor:)]) { //it has to work on iOS 6 as well
secondaryNavBar.barTintColor = [UIColor darkGrayColor];
secondaryNavBar.tintColor = [UIColor whiteColor];
}
else {
secondaryNavBar.tintColor = [UIColor darkGrayColor];
}
[self.view addSubview:secondaryNavBar];
bottomNavBar = secondaryNavBar;
[self layoutNavBar];
}
- (void)layoutNavBar {
// Get the currently displayed view
UIView *contentView = self.topViewController.view;
// Get its frame and height
CGRect contentFrame = contentView.frame;
float height = contentFrame.size.height;
// Adapt height and y origin with the new nav bar
contentFrame.size.height = height - bottomNavBar.frame.size.height;
contentFrame.origin.y = bottomNavBar.frame.origin.y + bottomNavBar.frame.size.height;
// Set the view's frame
contentView.frame = contentFrame;
}
#end
ViewController.m :
#implementation ViewController
-(void)viewDidAppear:(BOOL)animated {
CustomNavigationController *navigation = (CustomNavigationController*)self.navigationController;
[navigation layoutNavBar];
}
#end
Note that you have to call layoutNavBar on viewDidAppear, or the view's frame will be reset by your app. This is not a perfectly clean solution, but a pretty good fix.
I have a view (InfoVC) that is rotating even if I set shouldAutoRotate to false.
This is the code that is opening the view (inside a Modal)
- (IBAction)presentInfoVC:(id)sender{
InfoVC *infoVC = [[InfoVC alloc] init];
UINavigationController *infoNVC = [[UINavigationController alloc] initWithRootViewController:infoVC];
UIImage *img =[UIImage imageNamed:#"image.png"];
UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
infoNVC.navigationBar.tintColor = [UIColor lightGrayColor];
[infoNVC.navigationBar.topItem setTitleView:imgView];
[imgView release];
[self presentModalViewController:infoNVC animated:YES];
[infoVC release];
}
and the code that was supposed to avoid this view to rotate (inside InfoVC.m):
- (BOOL)shouldAutorotate
{
return FALSE;
}
What is wrong?
Regards!
Instead of creating a subclass of UINavigationController, you could use a category to perform the same task (if it's required for all instances of UINavigationController). It's a lot more lightweight than the subclassing method, and doesn't require you to swap class types for pre-existing UINavigationControllers.
To do so is as follows:
UINavigationController+NoRotate.h
#interface UINavigationController(NoRotate)
- (BOOL)shouldAutorotate;
#end
UINavigationController_NoRotate.m
#import "UINavigationController+NoRotate.h"
#implementation UINavigationController (NoRotate)
- (BOOL)shouldAutorotate
{
return NO;
}
#end
From then on, if you need a UINavigationController to no longer rotate, simply import UINavigationController+NoRotate.h where required. As category overrides will affect all instances of the class, if you need this behaviour for only a few cases, then you will need to subclass UINavigationController, and override -(BOOL)shouldAutorotate.
I got the answer. I figured out that I was supposed to implement shoulAutorotate in the UINavigationController, not in UIViewController. I created another class (subclass of UINavigationController), implemented shouldAutorotate like in this view and I used it replacing UINavigationController.
Code:
UINavigationControllerNotRotate.h
#import <UIKit/UIKit.h>
#interface UINavigationControllerNotRotate : UINavigationController
#end
UINavigationControllerNotRotate.m
#import "UINavigationControllerNotRotate.h"
#interface UINavigationControllerNotRotate ()
#end
#implementation UINavigationControllerNotRotate
- (BOOL)shouldAutorotate
{
return FALSE;
}
#end
New code:
- (IBAction)presentInfoVC:(id)sender{
InfoVC *infoVC = [[InfoVC alloc] init];
UINavigationControllerNotRotate *infoNVC = [[UINavigationControllerNotRotate alloc] initWithRootViewController:infoVC];
UIImage *img =[UIImage imageNamed:#"logo_vejasp_topbar.png"];
UIImageView *imgView = [[UIImageView alloc] initWithImage:img];
infoNVC.navigationBar.tintColor = [UIColor lightGrayColor];
[infoNVC.navigationBar.topItem setTitleView:imgView];
[imgView release];
[self presentModalViewController:infoNVC animated:YES];
[infoVC release];
}
This worked fine for me. Thanks for everybody who tried to help!