I have a fairly vanilla UITableView in my app used to display an image and text in the default/standard way. The first time a UITableViewCell is requested I return it with a placeholder image and start an asynchronous download of the real image. When the download is complete I replace the placeholder image.
If a download fails, the placeholder image remains. Clicking on such a row acts normally. If the download is successful, clicking on a row with the intended image leads to the UIImageView expanding to the height of the row (and the width increases at scale). The UIImageView never returns to normal size. Crude attempts to set the frame of the UIImageView do not alleviate the issue of mysterious resizing.
// from my - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; method
// after boilerplate cell dequeuing code
cell.textLabel.text = [selectedNoun title];
// add placeholder image
UIImage *placeholderImage = [UIImage imageNamed:#"placeholder.png"];
cell.imageView.image = placeholderImage;
[cell.imageView setContentMode:UIViewContentModeScaleAspectFit];
//...
// If the image has been downloaded I set it
cell.imageView.image = iconDownloader.image;
This is driving me nuts. It actually only happens in one of two tables in my app, but after comparing them line or line I can't see any difference. Hoping that someone has come across this before.
Thanks!
EDIT: I don't have a good explanation for my solution other than to say that images over a certain size appear to lead to this behavior and the use of actual thumbnails (even images somewhat bigger than the UIImageView's frame) do not exhibit this behavior.
If you have custom UITableViewCell then make sure that your UIImageView is not named with "imageView"
The only things that come to mind that effect the size & appearance of a view within its superview are:
Are you changing the frame/bounds/center properties anywhere? Where/how is the frame set initially?
imageView.autoResizingMask should be set to UIViewAutoResizingNone
imageView.clipsToBounds should be set to YES
EDIT: more suggestions
I'm shooting in the dark b/c your posted code looks fine and if you've set imageView.clipsToBounds that should constrain the drawn image to the imageView frame. Here are a couple more things to try:
Implement tableView:willDisplayCell:forRowAtIndexPath: and set the imageView properties there. If imageView.frame is the problem, this likely won't fix it.
Add your own UIImageView to the cell configured how you want it and don't use the built in imageView property. If the behavior of the default cell is causing the problem this should work.
EDIT: large image problems
I don't know exactly how big the "really big images" are that you are currently using but they are likely the issue. From the UIImage docs (emphasis is mine):
You should avoid creating UIImage objects that are greater than 1024 x
1024 in size. Besides the large amount of memory such an image would
consume, you may run into problems when using the image as a texture
in OpenGL ES or when drawing the image to a view or layer. This size
restriction does not apply if you are performing code-based
manipulations, such as resizing an image larger than 1024 x 1024
pixels by drawing it to a bitmap-backed graphics context. In fact, you
may need to resize an image in this manner (or break it into several
smaller images) in order to draw it to one of your views.
This answer helped me. But I had to make sure to call [cell layoutSubviews] in the method that actually does the setting, like this:
cell.imageView.image = image;
[cell layoutSubviews];
Hope this can be of use to you!
My issue was slightly different, I had a custom UITableViewCell with own UIImageView and when cell disappeared and reappeared, the image would be incorrect size. My problem was that I was setting cell.imageView in one place and cell.thumbnail (custom image) in another, so I changed all references to cell.thumbnail.
Hopefully it helps someone in the future with similar issue.
In these situations I use this Image loader framework. It includes a method to set a placeholder image of your choosing, while downloading images in the background, and as an added benefit it caches images guaranteeing the same image won't ever have to be downloaded twice. Its a great piece of work that I've found very useful for tableview image loading.
SDWebImage:
https://github.com/rs/SDWebImage
I had the same problem, and I didn't figure out the reason for that. Anyway, it's something related to the placeholder image: if you load an image of the same size that the placeholder, no resize will be performed, but if the sizes don't match, the loaded image will be resized to the placeholder dimensions, and resized again when clicked.
So, if you want to avoid the problem, use a placeholder that matches the row height.
follow these steps:
Select the ImageView on your custom cell
go to Show to Identity Inspector
Scroll all the way to the end and uncheck the "User Interaction Enabled" checkbox.
This is pretty unlikely, but you should try to look into what happens to the frames of the UITableViewCell's subviews when its isSelected property switches from NO to YES (I.e. what happens when you tap a cell). I doubt that will help much, but it's worth looking into (if you can find anything...that's all under the hood of UITableViewCell I would imagine).
You should also look into the imageview's clipsToBounds property. Maybe that has something to do with it?
doing something like
CGRect bounds = [self bounds];
[self setImage:image];
[self setBounds:bounds];
when setting image fixes the problem for me
If you reload the tableview when it finish loading, the image get the size that it was suppose to have
[self.tableview reloadData];
I fix the problem with:
cell.selectionStyle = .none
In my case, I faced this issue in iOS 12 however iOS 13 works fine.
I changed UIImageView to UIButton and set background image as like below which fixes my issue.
cell.imageButton.setBackgroundImage(UIImage(named: "name_of_the_image", for: UIControl.State.normal)
I know this is way too late to post but someone might find it helpful.
Related
I've added an image to a UITableview using the following code. What I can't figure out is how to have that background image scroll with the table (not an image in each cell, but a large image behind the UITable). I need the background image to be scrollable and in synch with the UITable scrolling.
I've searched and all the examples I've seen simply add a static image.
here's the code:
[self.view setBackgroundColor:
[UIColor colorWithPatternImage:
[UIImage imageWithContentsOfFile:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
#"background.png"]]]];
thanks for any help.
I had this same problem and didn't find any solutions. I rolled my own which I explain in more detail than can be easily given here. It's explained at UITableView that scrolls the background with dynamic content
The basic idea is the following:
create a second table view behind your table view that has dynamic cell heights (or heights that aren't a multiple of a background pattern image's height)
turn its .userInteractionEnabled property to NO (so it doesn't receive touch events)
have it listen to the 'front' table view's contentOffset property via KVO so that the background table view sets its contentOffset to the same value.
have this background table view be its own delegate (you have to make a subclass so to implement KVO listening handlers anyway), and it populates empty cells' contentView.backgroundColor = [UIColor colorWithPatternImage: ...]
make sure your 'front' table view cells have transparent backgrounds. i.e. backgroundView set to an imageView without an image and opaque set to NO, and backgroundColor set to clearColor.
worked for me quite fine, and didn't seem in any way slower. The tables were still quite snappy on an iPod 4G
Because few days ago I saw that -
http://www.appuicomponents.com/component/sbtv
I am guessing the answer is not trivial. But maybe you would like to try that ?
Any way, if you are using a pattern image, isn't that possible to add the pattern to the cells them selfs ?
I have a UIImageView that I dynamically load with an Image using
myTableViewCell.myImageView.image = [UIImage imageNamed:myImageFileName];
myImageView is a UIImageView added to a myTableViewCell.nib and declared as IBOutlet. In IB I set the properties to set the content mode to "ScaleToFill".
The images are larger than the UIImageView and I want to auto-scale them down to the size of the view.
Strangely and whatever I try, this doesn't seem to work (XCode version is 3.2.3).
One Oberservation is that the myTableViewCell.myImageView seems to take it's size from the top cell in the tableview, since the cells below are displayed in equal size to the first cell, even though the image sizes are different.
Note that I use the same myTableViewCell in another tableView with different Icons and there it works. I can't spot the difference between the 2 except the jpg files have different dimensions and aspect ratios ...
Is it possible that the TableView-class has something to do with it?
Are the image properties that prevent the image from resizing?
I found th reason for this. In IB the 'Autosizing' parameters were set to strech the image according to the display size.
Changing these parameters to keep the image at constant size resolve the problem.
In my view I have a picture.. The picture has a 3:2 scale and is huge, resolution wise.
I'm having a lot of trouble initializing a UIImage with the image to the original size and then zooming out of the UIImageView so that the entire image is visible within the scrollview.
The program stays only in the portrait orientation.
And no, please don't say to just use UIWebView. UIWebView doesn't let me set the content size during view load...instead, it just zooms out of the image by some arbitrary scale and I couldn't figure out a way to adjust the scale value (I don't think it's possible).
Thanks for any responses! I really appreciate them :D
Here's an example of placing an image that responds to pinch-to-zoom. Basically, you place the UIImageView in a UIScrollView and change some settings.
UIImageView *myImage;
UIScrollView *myScroll;
-(void)viewDidLoad{
myImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,360,450)];
[myImage setImage:[UIImage imageNamed:#"coolpic.png"]];
myImage.contentMode = UIViewContentModeScaleAspectFit;
[myScroll addSubview:myImage];
[myScroll setContentSize:CGSizeMake(myImage.frame.size.width, myImage.frame.size.height)];
[myScroll setMinimumZoomScale:1.0];
[myScroll setMaximumZoomScale:4.0];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return myImage;
}
Of course, set all your delegates and IB hooks properly.
Edit: I just reread your question. The portion of the example that answers your question is the frame specification of the UIImageView and its contentMode setting.
You almost certainly don't want to load your 'huge, resolution wise' image all at once on load regardless of it's scale. I'd suggest checking out some of Apple's sample code on this stuff (starting with ScrollViewSuite would be good, I'd say).
There was also a recent video released from WWDC where they implement this sort of thing live (they have more of a photo viewing app, but you could pretty easily do what they show with just one image too) so take a look for that too.
Go to the attributes tab of the UIImageView. Select "aspect to fill" or "aspect to fit". If you use "aspect to fill", you might not show the whole image. I just use "aspect to fit", and make the background black.
I have a custom UIImageView class which I use to handle multi-touch events on the UIImageView. When the user touch begins, I want to increase the UIImageView's frame but keep the UIImage size fixed.
I tried changing the UIImageView's frame and then calling the drawInRect: method of UIImage to keep the UIImage's size fixed. But this is not working.
The contentMode for the UIImageView is set as ScaleAspectFit and as soon as I increase the frame size of the UIImageView, the UIImage size also increases (and is not affected by the drawInRect:)
Can someone please tell me how I can achieve this?
Thanks.
Adding more details
What I am trying to do is this
Place a UIImageView on the screen with the size same as the size of the image
When the user selects the image, anywhere he touches, the image edits as if the user is doing multi-touch with the image
If I increase the size of the imageview to detect touches any where, the image size also increases... Hope that makes things clearer!
Thanks
There may well be other ways to do it, but I think the UIImageView is doing what it's intended to do here.
What do you want the area of the view not covered by the image to look like? Be transparent? Have a solid colour?
Why do you want to do this? Is it to capture touch events from a wider area than that under the image itself?
If you have a good reason for needing to do this I would create a new view, probably just a plain UIView (with background set to transparent colour), and add the UIImageView to that. Make the plain view the one you resize.
I haven't specifically tried this, but I think it would work:
imageView.contentMode = UIViewContentModeCenter;
set a UIImageView.image property to a UIImage is unable add the image to the view,however if i set the imageview frame property,it works.can anyone tell me how it's happen?
and what will happen when i apply the UIImage instance method[drawInRect:] redraw the image frame which is larger than the view frame?i have tried but nothing happen,and what is this function doing actual?
Generally, how it works is, you add an Image to a UIImageView and then add the UIImageView to a UIView to display it on the screen. You can do this programmatically, or using Interface Builder. Optionally, you can create a CGRect (based on a frame, if you like), use this as the bounds for the UIImageView (or you can frame the UIView). There are several ways to do what you want to do.
It's hard to tell without seeing your code. It could be a number of things. You could be inserting the view with the image behind the currentView? You may not be retaining the UIImageView. We can't read minds here necessarily, (sometimes we do). But you'll need to be more helpful if you want a solid answer.
Or just take a look at this:
UIImageView Docs