Is UICollectionView.backgroundView broken - ios

I'm writing something relatively simple, or so I thought.
Firstly, the code, for which I'm trying to place an image on the background of the UICollectionView if there are no results returned from my server. The image is 200 by 200:
UIView *myView = [[UIView alloc] initWithFrame:self.view.bounds];
CGRect myViewSpace = self.view.bounds;
CGFloat myX = (myViewSpace.size.width /2.0) - 100;
CGFloat myY = (myViewSpace.size.height /2.0) - 100;
UIImageView *imView = [[UIImageView alloc] initWithFrame:CGRectMake(myX, myY, 200, 200)];
imView.image = [UIImage imageNamed:#"imNotHome"];
[myView addSubview:imView];
myCollectionView.backgroundView = myView;
Once there are results, I want to be able to remove it.
I thought it'd be as simple as placing the following, before I reloaded the UICollectionView:
[myCollectionView.backgroundView removeFromSuperview];
However, it appears to be doing nothing.
Am I missing something?
Thanks in advance!

It should be done this way instead:
myCollectionView.backgroundView = nil;
Explanation: You should unset the UICollectionView's background in the same way as you set it. You didn't set it by manipulating the view hierarchy, but by setting the background property. You did call addSubview in the previous line, but that was to add a subview to your background view, not to add the background view itself.
Edit:
There is a very good article about this UICollectionView bug here:
http://blog.spacemanlabs.com/2013/11/uicollectionviews-backgroundview-property-is-horribly-broken/
The solution the author gives is to reset the background to an empty opaque view:
UIView *blankView = [UIView new];
blankView.backgroundColor = [UIColor whiteColor];
[myCollectionView.backgroundView removeFromSuperview];
myCollectionView.backgroundView = blankView;
Also, the author recommends not using the backgroundView property at all but doing it yourself:
Frankly, I think the best solution is to just ignore the backgroundView property all together. Instead, make the collection view’s background clear, and implement your own backgroundView; just throw a view behind the collection view.

Related

Making transparent Circles in iOs

I want to create a black UIView with transparent circles.
I think about create one view (with black color and transparence 50%), and add multiple circles inside of it, but I don't know how to set the transparence for each. I know how to create a circle View (an example: how to draw a custom uiview that is just a circle iphone-app).
I want to do is something like iShowcase library but with multiple dots:
Any clue? thanks.
SOLVED
I took a look to the code of iShowcase library and I solved my probblem. now, I am working in a library based in iShowcase library.
I will post here when I finish it.
Please have a look of below link hope this will helpful for you.
Link : Here is Answer to set shadow in your view.
Use alpha for your circleView. As in your link example,then add as subviews in yourmainview:
UIView *circleView = [[UIView alloc] initWithFrame:CGRectMake(10,20,100,100)];
circleView.alpha = 0.5;
circleView.layer.cornerRadius = 50;
circleView.backgroundColor = [UIColor whiteColor];
[yourmainview addSubview: circleView];
Btw in your picture I think white circles have 100% alpha. You can use individual alpha for each circleView, or use a randomizer :)
As for updated example why don't you add more buttons and showcase in your h file, synthesize them and use multiple instances .... showcase setupShowcaseForTarget:btn_custom_1 title:#"title" details:#"other"]; ? I think you should modify main classes, becouse what you want are different containerView for multiple views [circles].
Using modifyed iShowcase.m [- (void) calculateRegion], and different views as containers, I was able to make something like: http://tinypic.com/view.php?pic=2iwao6&s=8#.VLPTRqYsRE8 So the answer is: use custom views for multiple showcase [ex [showcase2 setContainerView:self.view2];], then custom frame for each showcase [ showcase2.frame = CGRectMake(0,0,100,100);] I don;t habe time to fine tuning the example, but yes, you can achieve desired result...
I finally solved my question inspired by iShowCase library I did this simple class and Upload to github.
https://github.com/tato469/FVEasyShowCase
Simplest what you can do is to have your main view (black 50% transparant) and add shapes to the mask layer of that.
So basically:
//Set up your main view.
UIView* mainView = [UIView new];
mainView.backgroundColor = [UIColor blackColor];
mainView.alpha = 0.5;
UIView* circle1 = [YourCircleClassHere new];
UIView* circle2 = [YourCircleClassHere new];
UIView* circle3 = [YourCircleClassHere new];
UIView* container = [UIView new];
[UIView addSubview:circle1];
[UIView addSubview:circle2];
[UIView addSubview:circle3];
//Make a new layer to put images in to mask out
CALayer* maskLayer = [CALAyer layer];
//Assign the mask view to the contents layer.
maskLayer.contents = (id)container;
//This will set the mask layer to the top left corner.
maskLayer.frame = CGRectMake(0,0,container.frame.size.width,container.frame.size.height);
//Lastly you assign the layer to the mask layer of the main view.
mainView.layer.mask = maskLayer;
//Applies basically the same as clipToBounds, but a bit reversed..
mainView.layer.mask = true/false;
On a sidenote:
I achieved this with images "contents = (id) [UIImage CGImage]", but I'm sure it should work with UIViews as well.
Also mind some mistakes, since I just wrote this from my mind, also I didn't test this out.. So keep me updated if it works/!works ^_^

iOS - UIView Always on Front without BringSubviewToFront

Can I have some UIView which will always appear on top in iOS?
There are lots of addSubview in my project but I need to have one small view which will always appear. SO is there any other option than
[self.view bringSubViewToFront:myView];
Thanks
One more option (especially if you want to overlap several screens, with logo for example) - separate UIWindow. Use windowLevel to set the level of new window.
UILabel *devLabel = [UILabel new];
devLabel.text = #" DEV ";
devLabel.font = [UIFont systemFontOfSize:10];
devLabel.textColor = [UIColor grayColor];
[devLabel sizeToFit];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
static UIWindow *notificationWindow;
notificationWindow = [[UIWindow alloc] initWithFrame:
CGRectMake(screenSize.width - devLabel.width, screenSize.height - devLabel.height,
devLabel.width, devLabel.height)];
notificationWindow.backgroundColor = [UIColor clearColor];
notificationWindow.userInteractionEnabled = NO;
notificationWindow.windowLevel = UIWindowLevelStatusBar;
notificationWindow.rootViewController = [UIViewController new];
[notificationWindow.rootViewController.view addSubview:devLabel];
notificationWindow.hidden = NO;
Another option is set layer.zPosition of your UIView.
You need to add
#import <QuartzCore/QuartzCore.h>
Framework to your .m file.
And set such like
myCustomView.layer.zPosition = 101;// set maximum value as per your requirement.
For more information about layer.zPosition read this documentation.
Discussion
The default value of this property is 0. Changing the value of this property changes the the front-to-back ordering of layers onscreen. This can affect the visibility of layers whose frame rectangles overlap.
The other option is to add other subviews below this always-on-top subview. For example:
[self.view insertSubview:subview belowSubview:_topSubview];
There's no solution with Interface Builder if you search for this kind. It should be done programmatically. If you don't want to use bringSubviewToFront: everytime, just insert other subviews below this one.
Many times your view did not appear in viewDidLoad or, if your view comes from parentViewController (for example in many transitions like modal segue..) your can see parentViewController only in viewDidAppear so:
Try to put bringSubviewToFront in :
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.view bringSubViewToFront:myView];
// or if your view is attached in parentViewController
[self.parentViewController.view bringSubViewToFront:myView];
}
Good luck!

Moving a cell using CGRectOffset - what am I doing wrong?

I stumbled upon this fantastic library for implementing table view cell sliding, but there's a few minor differences between what it offers and what I'm looking to have, so I'm continuing with my implementation.
The way the developer moved the table view cells was creative, I thought, in that he used CGRectOffset() to add almost padding to the sides of the cell as it moved to look like it was moving.
I want to do something similar for mine, as it seems like the easiest way to accomplish this. However, when I do the following, nothing happens to the cell:
(Just an example):
CGFloat offset = 11;
self.contentView.frame = CGRectOffset(self.contentView.bounds, offset, 0);
I set a breakpoint there, so it's indeed being called when I pan across the cell (it's in the gesture recognizer method). Yet after it gets called, the cell looks identical in position.
And I have this at the beginning, similar to how he set up the view:
- (void)awakeFromNib {
[super awakeFromNib];
self.contentView.backgroundColor = [UIColor whiteColor];
UIView *backgroundView = [[UIView alloc] initWithFrame:self.contentView.frame];
backgroundView.backgroundColor = [UIColor whiteColor];
self.backgroundView = backgroundView;
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pannedCell:)];
panGestureRecognizer.delegate = self;
[self addGestureRecognizer:panGestureRecognizer];
}
So I'm not sure exactly why it's not working. Does anyone have any ideas?

UIView: layoutSubviews vs initWithFrame

When subclassing UIView, I usually place all my initialisation and layout code in its init method. But I'm told that the layout code should be done by overriding layoutSuviews. There's a post on SO that explains when each method gets called, but I'd like to know how to use them in practice.
I currently put all my code in the init method, like this:
MyLongView.m
- (id)initWithHorizontalPlates:(int)theNumberOfPlates
{
self = [super initWithFrame:CGRectMake(0, 0, 768, 1024)];
if (self) {
// Initialization code
_numberOfPlates = theNumberOfPlates;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
[scrollView setContentSize:CGSizeMake(self.bounds.size.width* _numberOfPlates, self.bounds.size.height)];
[self addSubview:scrollView];
for(int i = 0; i < _numberOfPlates; i++){
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:#"a1greatnorth_normal_%d.jpg", i+1]];
UIImageView *plateImage = [[UIImageView alloc] initWithImage:img];
[scrollView addSubview:plateImage];
plateImage.center = CGPointMake((plateImage.bounds.size.width/2) + plateImage.bounds.size.width*i, plateImage.bounds.size.height/2);
}
}
return self;
}
It's the usual tasks: setting up the view's frame, initialising an ivar, setting up a scrollview, initialising UIImages, placing them in UIImageViews, laying them out.
My question is: which of these should be done in init, and which of these should be done in layoutSubviews?
Your init should create all the objects, with the required data. Any frame you pass to them in init should ideally be their starting positions.
Then, within layoutSubviews:, you change the frames of all your elements to place them where they should go. No alloc'ing or init'ing should take place in layoutSubviews:, only the changing of their positions, sizes etc...
In case you're autoresizing works perfectly with just autoresizingFlags, or autolayout, you may just use init to setup the whole view.
But in general your should do layouting in layoutSubviews, since this will be called on every change of the views frame and in other situation, where layout is needed again. Sometimes you just don't know the final frame of a view within init, so you need to be flexible as mentioned, or use layoutSubviews, since you do the layout there after the final size has been set.
As mentioned by WDUK, all initialization code / object creation should be in your init method or anywhere, but not in layoutSubviews.

Shadow in separate view from UIImage for dynamic adjustments

I would like to obtain this effect (http://stackoverflow.com/questions/7023271/how-to-adjust-drop-shadow-dynamically-during-an-uiimageview-rotation) but from a more complex image than just a red square ! If the link ever gets broken, it's a about how to adjust drop shadow dynamically during an UIImageView rotation.
So I tried implementing something but I just can't get the shadow in a separate layer... Here is my code, very simple, but doesn't work:
// here is my code
- (void)viewDidLoad {
[super viewDidLoad];
testView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"handNoShadow.png"]];
testViewShadow = [[UIView alloc] initWithFrame:testView.frame];
testViewShadow.layer.shadowPath = [[testView layer] shadowPath];
testViewShadow.layer.shadowOpacity = 1.0;
testViewShadow.layer.shadowOffset = CGSizeMake(10, 10);
testViewShadow.layer.shadowRadius = 5.0;
[self.view addSubview:testViewShadow];
[self.view addSubview:testView];
}
PS: i did #import
I do get an image but no shadow... =(
Any lead, help, code, link... is welcome !
Thanks
possible cause:
your testViewShadow.clipToBounds property is set to YES (should be NO)
your testViewShadow do the drawing of the shadow correctly but another UIView is on top and mask it. Check your Z order. Either the order in Storyboard/Nib file (or the order you added the subviews programmatically). Last in the list (or last one added) is on top. For my app I had to put the UIView that need a shadow last so that no other view mask it.

Resources