UISplitViewController: remove divider line - objective-c

When using UISplitViewController on the iPad there's a black vertical divider line between the root and detail view. Is there any way to remove this line?
Thanks

Excellent answer by #bteapot. I tested this and it works, even gets rid of the line between master/detail nav bars.
You can do this in storyboard by adding the "gutterWidth" key path and the value 0 to the USplitViewController runtime attributes.

Actuly I have some modification to answer of (Dylan)'s answer
in the appDelegate we need to add image in spliteview controller rather then window
self.splitViewController.view.opaque = NO;
imgView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"FullNavBar.png"]];
[imgView setFrame:CGRectMake(0, 0, 1024, 44)];
[[self.splitViewController view] insertSubview:imgView atIndex:0];
[[self.splitViewController view] setBackgroundColor:[UIColor clearColor]];
here self is object of AppDelegate.
now Apply the answer of this thread : iPhoneOS SDK - Remove Corner Rounding from views (iPad problem) answer by (abs)
edit in above post's answer is
-(void) fixRoundedSplitViewCorner {
[self explode:[[UIApplication sharedApplication] keyWindow] level:0];
}
-(void) explode:(id)aView level:(int)level
{
if ([aView isKindOfClass:[UIImageView class]]) {
UIImageView* roundedCornerImage = (UIImageView*)aView;
roundedCornerImage.hidden = YES;
}
if (level < 2) {
for (UIView *subview in [aView subviews]) {
[self explode:subview level:(level + 1)];
}
}
imgView.hidden = FALSE;
}
** make imgView.hidden to FALSE
declare imgView to the AppDelegate.h file**
and dont forget to call this
-(void)didRotateFromInterfaceOrientation:
UIInterfaceOrientation)fromInterfaceOrientation
{
[yourAppDelegate performSelector:#selector(fixRoundedSplitViewCorner)
withObject:NULL afterDelay:0];
}

chintan adatiya answer covers only the corners and the navigation bar, but I found an trick how to cover the line between the Master and the Detail view.
It is not nice but it works like a charm.
First create an image which is 1 px wide and 704 pixels high.
In the didFinishLaunchingWithOptions add the following code:
UIView *coverView = [[UIView alloc] initWithFrame:CGRectMake(320, 44, 1, 704)];
[coverView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"divider_cover.png"]]];
[splitViewController.view addSubview:coverView];
And done.
When you want a background image which is continues create 3 images:
Master: width: 320, height: 704
Detail: width: 703, height: 704
Divider:width: 1, height: 704

First post here, hi everyone.
I discovered how to do it accidentally... when I tried to find why I had LOST the divider line. Here's how to hide it, if you're still interested:
1) In your Detail (right-side) view, make sure you have a subview that spans the whole view.
2) Offset this subview view to (-1, 0).
3) Make sure that the Detail View has its "Clip Subviews" option unchecked.
Voilà, enjoy.

You can mostly get rid of it by setting another image behind it in the main window's views. This is from the app delegate didFinishLaunchingWithOptions
// Add the split view controller's view to the window and display.
splitViewController.view.opaque = NO;
splitViewController.view.backgroundColor = [UIColor clearColor];
[window addSubview:splitViewController.view];
[window insertSubview:bgImageView belowSubview:splitViewController.view];
[window makeKeyAndVisible];
But it still leaves two visual artifacts at the top and the bottom that appear to be custom drawn by the splitviewcontroller.

Interestingly, In the app that I'm working on I want a black background color for both views in the UISplitViewController. I'd like to change the color of the divider line to white (so that you can see it). Making both background colors black is one way to get rid of (make invisible) the dividing line but that's probably not a solution for most people.

Tested on iOS10 (probably will work on iOS9 too).
splitviewController.view.backgroundColor = UIColor.white
it removes divider. Apparently divider is just a gap between master and detail container.

I looked around for a while, and came to the conclusion that theres no way to do this, other than to create your own custom split view.

Try the MGSplitViewController by Matt Gammell
http://mattgemmell.com/2010/07/31/mgsplitviewcontroller-for-ipad

I may be late here, but I DO have a solution that works. It even works for the iOS 8+ splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible; and seamlessly slides in and out when you press the Full Screen toggle button.
Here is the trick :
first Subclass UISplitViewController.m
In the header add the follwing :
#property (strong, nonatomic) UIView *fakeNavBarBGView;
In the viewDidLoad method add the following code :
CGFloat fakeNavBarWidth = 321; // It is important to have it span the width of the master view + 1 because it will not move when the split view slides it's subviews (master and detail)
CGFloat navbarHeight = self.navigationController.navigationBar.frame.size.height + 20;
self.fakeNavBarBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, fakeNavBarWidth, navbarHeight)];
self.fakeNavBarBGView.backgroundColor = [UIColor redColor];
// Add Fake navbar to back of view
[self.view insertSubview:self.fakeNavBarBGView atIndex:0];
// SplitView Controller
UISplitViewController *splitViewController = self;
DetailViewController *detailVC = [navigationController.viewControllers lastObject];
detailVC.fakeNavBarSubView = self.fakeNavBarBGView;
detailVC.SVView = self.view;
In the DetailViewController.h add the following :
#property (strong, nonatomic) UIView *SVView;
#property (strong, nonatomic) UIView *fakeNavBarSubView;
Now here is the final trick : in the DetailViewController.m, add the following in the viewDidLoad method (called every time you click the Master table) :
[self.SVView sendSubviewToBack:self.fakeNavBarSubView];
[self.SVView bringSubviewToFront:self.view];
Run it and watch the magic ;-)

Private API (can cause App Store rejection):
[splitViewController setValue:#0.0 forKey:#"gutterWidth"];

I did this accidentally by setting the backgroundColor property of the first viewController's view - possibly to clearColor, I don't remember now.

UIManager.put("SplitPaneDivider.draggingColor", new Color(255, 255, 255, 0));

Related

Adding subviews in NSWindow while resizing the windows, the UI gets jumbled

I have a window and a subview is added, this subview is the container of another view(accessed and added using NSViewController).
I have disabled autolayout and doing resizing from springs. The subviews gets resize correctly on window resize.
If I add / remove subviews keeping the window size same it works fine. But if I add subview and maximize it and then remove and then add, it gets jumbled.
Some time it happens straight forward as :
Open the main window (it opens in small size). Maximize it, then add the subview, the subview is added to its original size as drawn in xib. Expected behavior is the subview should get expand and cover the main window.
I am not able to find the solution. Please help me to fix this. The sample code and sample project is attached here.
//In AppDelegate
- (IBAction)buttonClicked:(id)sender {
if (!self.myVC) {
self.myVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
}
[self.containerView addSubview:self.myVC.view];
}
- (IBAction)clearClicked:(id)sender {
for (NSView *view in self.containerView.subviews) {
[view removeFromSuperview];
}
}
I got the answer,
Before adding the view to container view, I get the container's rect and set the frame for child view.
- (IBAction)buttonClicked:(id)sender {
if (!self.myVC) {
self.myVC = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
}
NSRect rect = NSMakeRect(0, 0, self.containerView.frame.size.width, self.containerView.frame.size.height);
[self.myVC.view setFrame:rect];
[self.containerView addSubview:self.myVC.view];
}

Custom UIProgressView in iOS7 not possible?

I know this was already asked about a hundred times here, but I couldn´t find a suitable answer in the other questions.
My problem is the height of my UIProgressView. While everything worked as expected in iOS6, now in iOS7 nothing goes right.
I tried the following:
1.Setting the custom layout in the drawRect-Method:
Works like a charm in iOS6, but in iOS7 the progress is set to 100% from the beginning or the bar is very thin.
2.Setting the layout with the progressImage and trackImage property of the UIProgressView appearance
Also not working under iOS7. Here the bar progress is set to 100% from the beginning, too. Some people write that it should be possible this way, but I can not confirm that for iOS7.
3.Using initWithProgressStyle for initialization and then setting the frame of the progress view
Not working for me under iOS6 and iOS7. In iOS7 the bars are just very slim.
For me right now it is pretty frustrating because the bars are either at 100% or they are mega-slim. Can anyone give me a suggestion to reach the old layout of my progress views. I think it has to be possible because if I look at my Spotify app on the iPhone (iOS7 installed), the progress view looks like before.
Thank you very much!
Well, the problem is seams that iOS6 UIProgressView and iOS7 UIProgressView have different internal subviews structure. iOS6 progress view is a single view without child view (or some minor view), iOS7 progress view have few additional subview for drawing progress bar and background.
If you remove all subview of UIProgressView on iOS7 than you drawRect: method will work the same as before on iOS6, but you will be totally responsible about drawing your progress view content including progress bar and background.
- (id) initWithCoder: (NSCoder*)aDecoder
{
if(self=[super initWithCoder: aDecoder])
{
// Also you can setup height of your progress here
// self.frame = CGRectMake(0,0,100,yourHeight);
NSArray *subViews = self.subviews;
for(UIView *view in subViews)
{
[view removeFromSuperview];
}
}
return self;
}
I made kind of a workaround for this problem. I hope somebody can give a nice answer for a normal UIProgressView though.
I wrote a UIView subclass with round corners and a view inside of it which changes its size depending on the given progress. I only use colors for the background, but images would be possible too. Here´s the code:
#import "CustomProgressView.h"
#import <QuartzCore/QuartzCore.h>
#interface CustomProgressView ()
#property (nonatomic, retain) UIView *progressView;
#end
#implementation CustomProgressView
#synthesize progressColor,trackColor,progressView,progress;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.layer.cornerRadius = 5;
// clipsToBounds is important to stop the progressView from covering the original view and its round corners
self.clipsToBounds = YES;
self.progressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, frame.size.height)];
[self addSubview:self.progressView];
}
return self;
}
-(void)setProgressColor:(UIColor *)theProgressColor {
self.progressView.backgroundColor = theProgressColor;
progressColor = theProgressColor;
}
-(void)setTrackColor:(UIColor *)theTrackColor {
self.backgroundColor = theTrackColor;
trackColor = theTrackColor;
}
-(void)setProgress:(float)theProgress {
progress = theProgress;
CGRect theFrame = self.progressView.frame;
theFrame.size.width = self.frame.size.width * theProgress;
self.progressView.frame = theFrame;
}
#end
I had a custom UIProgressView with it's own drawRect being updated from a background process.
In iOS6 all was working while in iOS7 the progressbar just did not update.
I have added layoutSublayersOfLayer right after the setProgress like this
[self.loadingProgress setProgress:pv.floatValue];
[self.loadingProgress layoutSublayersOfLayer:self.loadingProgress.layer];
and it worked like a charm.
I hope this helps someone.
Avoid a headache and use this excellent library:
YLProgressBar
Copy YLProgressBar.h and YLProgressBar.m from the YLProgressBar folder.
#import "YLProgressBar.h" in the file(s) you want to use the progress bar
Add your progress bar either by code or by xib
progressBar.type = YLProgressBarTypeRounded;
progressBar.progressTintColor = [UIColor greenColor];
progressBar.stripesOrientation = YLProgressBarStripesOrientationVertical;
progressBar.stripesDirection = YLProgressBarStripesDirectionLeft;
You have a nice, fully functional progress bar that supports width, height, modifications.

UIButton inside UIView doesn't respond to touch events

I've put a UIButton inside a custom UIView and the button is not receiving any touch events (it doesn't get into the highlighted state, so my problem is not about being unable to wire up a touch inside up handler). I've tried both putting it into the XIB in Interface Builder, and also tried programatically adding the UIButton into the UIView seperately, both ended with no luck. All my views are inside a UIScrollView, so I first though UIScrollView may be blocking them, so I've also added a button programatically exactly the same way I add my custom view into UIScrollView, and the button worked, elimination the possibility of UIScrollView could be the cause. My View's hiearchy is like this:
The button is over the image view, and the front layer isn't occupying my button completely, so there's no reason for me not be physically interacting with the button. At my custom view's code side, I'm creating my view as such:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIView *sub = [[[NSBundle mainBundle] loadNibNamed:#"ProfileView" owner:self options:nil] objectAtIndex:0];
[self addSubview:sub];
[sub setUserInteractionEnabled:YES];
[self setUserInteractionEnabled:YES];
CALayer *layer = sub.layer;
layer.masksToBounds = YES;
layer.borderWidth = 5.0;
layer.borderColor = [UIColor whiteColor].CGColor;
layer.cornerRadius = 30.0;
/*layer.shadowOffset = CGSizeZero;
layer.shadowRadius = 20.0;
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowOpacity = 0.8;
*/
}
return self;
}
I've tried all combinations of setUserInteractionsEnabled, and had no luck. (Yes, also set them to checked in Interface Builder too). I've also read in another question with a similar problem that I should try overriding 'canBecomeFirstResponder' to return 'YES' and I've also done that too. But the problem persists, I can't click the button. I've not given any special properties, settings to the button, it's just a regular one. My other objects in the view (labels below, image view behind the button etc.) are working properly without problems. What could be possibly wrong here?
Thanks,
Can.
UPDATE: Here is a quick reproduction of the problem: https://dl.dropbox.com/u/79632924/Test.zip
Try to run and click the button.
Looking at the test project, I believe your problem in the way you create TestView, you do not specify the frame for it, so basically the parent view is 0 size, and the subviews you see from XIB extending out of the parent view and thus do not get anything in responder chain.
You should either specify the frame when creating TestView, or adjust the frame after loading XIB file.
I have had this problem as well. The cause for me was that the UIButton superview frame was of height 0, so I believe that even though a touch was happening, it was not being passed down to the button.
After making sure that the button's superview took a larger rectangle as a frame the button actions worked.
The root cause for this problem on my side was a faulty auto layout implementation (I forgot to set the height constraint for the button's superview).
I've found the solution. I was initializing my custom view as:
MyView *view = [[MyView alloc] init];
I've initialized it instead with a frame of my view's size, and it started responding to events:
CGRect rect = CGRectMake(0,0,width,height);
MyView *view = [[MyView alloc] initWithFrame:rect];
Storyboard Solution
Just for anyone wanting a solution to this when using storyboards and constraints.
Add a constraint between the superview (containing the button) and the UIButton with an equal heights constraint.
In my case, I had selected embed UIButton in a UIView with no inset on the storyboard. Adding the additional height constraint between the UIButton and the superview allowed the UIButton to respond to touches.
You can confirm the issue by starting the View Debugger and visually confirm that the superview of the UIButton is not selectable.
(Xcode 11, *- Should also work in earlier versions)

UIScrollView does not work with EXC_BAD_ACCESS

I have a scrollview that is subview of view, and has the subviews. The problem is this: the scrollView came with the black background (as I have set transparent) and also does not work. The scrollView is connected with an IBOutlet. I redid the XIB 2 times, what needs fixing? When I add the scrollView as subview of view:
[self.view addSubview:self.scrollView];
I get this error during runtime:
0x132b61: calll 0x132b66; CA::Layer::ensure_transaction_recursively(CA::Transaction*) + 14
EXC_BAD_ACCESS(code=2 address=0xbf7ffffc)
If I do not add it as a subview in the code, the view controller opens and the scrollview is black and does not scroll.
You are probably doing somewhere, something like:
[myScrollView addSubview:myAnotherView];
[myAnotherView addSubview:myScrollView];
which kicks an unwanted recursion. Check your code.
Check if you init with your scrollView with frame:
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 280, 360)];
Remember also to set contentSize bigger than frame, for example:
self.scrollView.contentSize = CGSizeMake(2*280, 360);
Also add delegate in your interface:
<UIScrollViewDelegate>
And delegate it:
self.scrollView.delegate = self;
In my situation I had a UIView that was receiving the same error. In my case I had forgotten to create an IBOutlet for my view. Once I did this, the error went away.

How to display a UIWindow based dimmed background like UIAlertView?

Here's my problem: I tried to display a UIWindow with a subview that displays a radial gradient. I wanted to put the window on the UIWindowLevelAlert. I had this all figured out before and it was working, but now I'm trying to reproduce it wasting hours...
This is the code I've got (the background is not a gradient because I wanted to keep it simple, then add a view that really is like the one of an UIAlertView):
- (IBAction)buttonPressed {
UIWindow *backgroundWindow = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
backgroundWindow.windowLevel = UIWindowLevelAlert;
UIView *backgroundView = [[UIView alloc]initWithFrame:[UIScreen mainScreen].bounds];
backgroundView.backgroundColor = [UIColor blackColor];
backgroundView.alpha = 0.5;
[backgroundWindow makeKeyAndVisible];
[backgroundWindow addSubview:backgroundView];
backgroundWindow.hidden = NO;
}
When a UIWindow is dealloc'd, it will be removed from the screen. Since you don't keep a reference to your UIWindow, I believe it is getting released and dealloc'd, and therefore it won't show.
The solution is to keep a reference to the window somewhere. Can you store it as a property in the class you're working in?