I'm running into a problem trying to perform a certain effect on iOS with tableviews...I know this can be done with normal UIViewControllers, but can't seem to pull it off with UITableViewControllers.
The effect is showing a clear background image behind a tableview and and as the user scrolls down the tableview, the background blurs. No problem getting that to happen.
The issue I'm having is that using a UITableViewController, I can only seem to have 1 ImageView behind the TableView and to create the blurring effect, the extension i am using will require 2 image views, one of which is the blurred image and has it's opacity set to 0 at launch.
This is code I know works using a UIViewController:
UIImage *background = [UIImage imageNamed:#"bg_004.png"];
self.backgroundImageView = [[UIImageView alloc] initWithImage:background];
self.backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
[self.view addSubview:self.backgroundImageView];
self.blurredImageView = [[UIImageView alloc] init];
self.blurredImageView.contentMode = UIViewContentModeScaleAspectFill;
self.blurredImageView.alpha = 0;
[self.blurredImageView setImageToBlur:background blurRadius:10 completionBlock:nil];
[self.view addSubview:self.blurredImageView];
This is the code I am trying on the UITableViewController that does not work:
UIImage *background = [UIImage imageNamed:#"bg_004.png"];
self.backgroundImageView = [[UIImageView alloc] initWithImage:background];
self.backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
[self.tableView setBackgroundView:self.backgroundImageView];
// Also tried this, to no success
[self.tableView.backgroundView addSubview:self.blurredBackgroundView];
self.blurredBackgroundView = [[UIImageView alloc] init];
self.blurredBackgroundView.contentMode = UIViewContentModeScaleAspectFill;
self.blurredBackgroundView.alpha = 0;
[self.blurredBackgroundView setImageToBlur:background blurRadius:10 completionBlock:nil];
[self.tableView setBackgroundView:self.blurredBackgroundView];
// Also tried this, to no success
[self.tableView.backgroundView addSubview:self.blurredBackgroundView];
If anyone has some suggestions how how to make this work, i'd love some advice. I really wouldn't like to change my code from a TableViewController to a UIViewController
Set the table view's backgroundView property to point to an instance of UIView, and then add your image views as subviews of the new view. You can't directly add subviews to instances of UIImageView
Related
My main app has to do some work in a webview, so I want to keep the launch image up longer while this work takes place. To do this, I created a controller with a UIImageView and I'm loading the Default image up in it:
self.imageView.image = [UIImage imageNamed:"Default"];
// These all tend to fill the screen, but end up distorting the image
//self.imageView.contentMode = UIViewContentModeScaleAspectFill;
//self.imageView.contentMode = UIViewContentModeScaleAspectFit;
//self.imageView.contentMode = UIViewContentModeScaleToFill;
// This keeps the aspect the same, but doesn't fill the screen
self.imageView.contentMode = UIViewContentModeCenter;
This mostly works, except when the real launch image goes away and is replaced with mine, I have two white bars - one at the top and one at the bottom - where the image doesn't completely fill. I've tried to set the contentMode to the various fill/fit's, and even though this has the desired effect of filling the full screen, it stretches and distorts the image slightly.
So what I'm wondering is - what does the launch image do that I'm not doing? How can I replicate the display exactly so that the user can't tell it's a different image?
Like in your project I use a launch image and then in the first UIViewController called I have an UIImageView inside. The image resolution, must be exactly the same as the screen's definition.
The code in the UIViewController is something like this :
CGRect fullFrame = [[UIScreen mainScreen] bounds];
// Img Background
UIImageView *background;
if (fullFrame.size.height <= 480) {
background = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image-480h.png"]];
}
else if (fullFrame.size.height <= 568) {
background = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image-568h.png"]];
}
else if (fullFrame.size.height <= 668) {
background = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image-668h.png"]];
}
else {
background = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image-736h.png"]];
}
background = CGRectMake(0, 0, frame.size.width, fullFrame.size.height);
myMainView = [[UIView alloc] initWithFrame:frame];
[myMainView addSubview:background];
self.view = myMainView;
I check the different screen size depending on the iPhone 4, 5, 6 and 6 plus.
I am working on a view based app, I have set the background image as follows.
.h file:
UIImageView *BackgroundImage;
.m file:
viewdidLoad method:
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG.png"]];
[[self view] addSubview:BackgroundImage];
[BackgroundImage.superview sendSubviewToBack:BackgroundImage];
and on the rotate method:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG2.png"]];
[[self view] addSubview:BackgroundImage];
[BackgroundImage.superview sendSubviewToBack:BackgroundImage];
[super viewDidLoad];
}
Using this code I am able to set the background, but on rotation the first loaded image is not removed and the second one is loading just behind the first one, so just half of the image is visible, because of the first image is in front of second one.
Is there is a better way to do this?
OR
How can I just remove the first image and then set the second one?
Please help me to resolve this.
Change your didRotate... method to:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[BackgroundImage removeFromSuperview];
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG2.png"]];
[[self view] addSubview:BackgroundImage];
}
Notice the [BackgroundImage removeFromSuperview]; line. What we are doing here is whenever the device rotates, you remove the old image view and add another one.
Also please notice that variable names should start with lower case, so BackgroundImage should be backgroundImage. This is to tell them apart from classes' names.
If you change your code like this should to work
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG.png"]];
[self.view addSubview:BackgroundImage];
[self.view sendSubviewToBack:BackgroundImage];
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[BackgroundImage removeFromSuperview];
BackgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"BG2.png"]];
[self.view addSubview:BackgroundImage];
[self.view sendSubviewToBack:BackgroundImage];
[super viewDidLoad];
}
This is because you are initializing the UIImageview again. Better to use same UIImageView that is backgroundImage with different image.
[Background Image set image:[UIImage imageNamed:#"BG2.png"]];
Just set the new image when rotating:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
BackgroundImage.image = [UIImage imageNamed:#"BG2.png"];
}
Your code kept adding new image views when rotating.
How [do stuff] properly in iOS?
Start your ivar names using an underscore and a lowercase letter: _backgroundImage instead of BackgroundImage.
Insert a subview in the right spot: [self.view insertSubview:_backgroundImage atIndex:0];
I've added a UIImageVIew to my view and if I specify the image to use within IB then it gets displayed correctly, but if I instead try to add the image programatically then it doesn't display.
I cleared out the image to load from IB and added the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage* image = [UIImage imageNamed:#"pic1.png"];
UIImageView *iv = [[UIImageView alloc] initWithImage: image];
iv.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
iv.contentMode = UIViewContentModeCenter;
self.slideshowView = iv;
}
self.slideshowView is an outlet connected to the image view.
I can confirm that image and iv are both non null when it executes.
Instead of creating a new UIImageView, set the outlet's image property. The problem here is that your new UIImageView does not have a frame within your super view and you're repointing the outlet to the new imageview you created.
self.slideshowView.image = [UIImage imageNamed:#"pic1.png"];
I make a app which include a image view within scroll view.
I have 3 classes and each class add images into image view.
When i press button1, it call class1 and it fill Class1images(from image001 to image200).
When i press button2, it call class2 and it fill Class2images(from image201 to image400)
The problem is when i call class1, image view show class1images(from image001 to image200).
After calling class1, i call class2.
When i call class2, my image view can't show class2images(from image201 to image400)
But, class1Images (from image001 to image200) are remaining in app.
I think class1 images are still in memory, so that class2 images can't add to memory.
I want to remove class1images when i call class2.
When i call next class, it will remove old images in memory and replace with new images.
But, my app is develop with storyboard and ARC.
So, i can't release memory manually in ARC mode.
Is there any ways to remove old images in memory?
- (void)viewDidLoad{
[super loadView];
self.view.backgroundColor = [UIColor grayColor];
ScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,self.view.frame.size.height)];
ScrollView.pagingEnabled = YES;
NSInteger numberOfViews = 200;
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * self.view.frame.size.width;
// Create a UIImage to hold Info.png
UIImage *image1 = [UIImage imageNamed:#"Image001.jpg"];
UIImage *image2 = [UIImage imageNamed:#"Image002.jpg"];
:
:
UIImage *image200 = [UIImage imageNamed:#"Image200.jpg"];
NSArray *images = [[NSArray alloc] initWithObjects:image1,image2, . . . ,image200,nil];
ImageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin, 0,self.view.frame.size.width, self.view.frame.size.height)];
[ImageView setImage:[images objectAtIndex:i]];
[ScrollView addSubview:ImageView];}
ScrollView.contentSize = CGSizeMake(self.view.frame.size.width*numberOfViews,self.view.frame.size.height);
[self.view addSubview:ScrollView];}
setting an imageview's animationImages property to a new array will remove the olf array and animate the new one.
to be 110% safe call stopAnimation, set the images, call startAnimation
I think your scrollview is not getting cleaned up. You need to remove previous images from scrollView and after that add images from next class.
try to implement something like this for removing images from scrollview and after this add other images on button click
for(UIView *subView in self.ScrollView.subviews)
{
if([subView isKindOfClass:[UIImageView class]])
[subView removeFromSuperview];
}
Hopefully can help you. Just give it a try.
If I create a UIImageView via Storyboard and add it as a #property into a ViewController.h, I can access that UIImageView from anywhere in the ViewController.m via [self UIImageView] or self.UIImageView.
But If I create the UIImageView programmatically from viewDidLoad as you see below, I seem to lose the ability to access it from outside viewDidLoad.
UIImageView *prevImgView = [[UIImageView alloc] init];
UIImageView *currImgView = [[UIImageView alloc] init];
UIImageView *nextImgView = [[UIImageView alloc] init];
NSArray *imageViews = [NSArray arrayWithObjects:prevImgView, currImgView, nextImgView, nil];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
[self.view addSubview: scrollView];
CGRect cRect = scrollView.bounds;
UIImageView *cView;
for (int i=0; i<imageViews.count; i++) {
cView = [imageViews objectAtIndex:i];
cView.frame = cRect;
[scrollView addSubview:cView];
cRect.origin.x += cRect.size.width;
}
So later on if I want to modify the image that is being displayed in any one of the UIImageView I've created from viewDidLoad, I can't seem to access it. Does anyone know what I'm doing wrong?
You would need to create your UIImageView in your header file and then it would be available throughout the rest of the view. You will need to add it to the view in viewDidLoad though.
Header
UIImageView *image;
Main // ViewDidLoad
image = [UIImageView alloc] .....
[self.view addSubView image];
Main Function .....
[image setImage ....
The answer AgnosticDev is trying to say here is to add an ivar to your view controller's .h file... e.g.:
#implementation YHLViewController : ViewController
{
UIImageView * currImageView;
}
And then in your "viewDidLoad" method, you can allocate and initialize it via:
currImageView = [[UIImageView alloc] init];
and have access to it from anywhere else in your view controller.