UIScrollView doesn't scroll - even with valid content size and scroll enabled - uiscrollview

In my viewDidAppear method (in which i call to the super method) I have the following code:
UIScrollView *navbar = [[UIScrollView alloc] init];
[navbar setScrollEnabled:YES];
[navbar setBackgroundColor:[UIColor redColor]];
[navbar setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:navbar];
NSDictionary *viewsDictionary2 = NSDictionaryOfVariableBindings(navbar);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[navbar]|"
options:0
metrics:nil
views:viewsDictionary2]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[navbar]|"
options:0
metrics:nil
views:viewsDictionary2]];
NSArray *categories = #[#"nav1", #"nav2", #"nav3", #"nav4", #"nav5", #"nav6", #"nav7", #"nav8", #"nav9", #"nav10", #"nav11", #"nav12", #"nav13"];
NSMutableArray *tempCategoryImages = [NSMutableArray array];
for (NSInteger i = 0; i < categories.count; i++)
{
[tempCategoryImages insertObject:[UIImage imageNamed:categories[i]] atIndex:i];
}
NSArray *categoryImages = [tempCategoryImages copy];
// Add subviews.
//
CGFloat xPadding = 25.0f;
UIView *previousImageView = NULL;
for (NSInteger i = 0; i < categoryImages.count; i++)
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:categoryImages[i]];
[imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[navbar addSubview:imageView];
if (i == 0) {
//
// First category.
//
[navbar addConstraint:[NSLayoutConstraint constraintWithItem:imageView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:imageView.superview
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0]];
} else {
//
// End categories.
//
[navbar addConstraint:[NSLayoutConstraint constraintWithItem:imageView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:previousImageView
attribute:NSLayoutAttributeRight
multiplier:1
constant:xPadding]];
}
[navbar addConstraint:[NSLayoutConstraint constraintWithItem:imageView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:imageView.superview
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0]];
previousImageView = imageView;
}
// Set content size.
//
CGSize scrollContentSize = CGSizeZero;
for (NSInteger i = 0; i < categories.count; i++)
{
UIImage *tempImage = [UIImage imageNamed:categories[i]];
// Width.
//
scrollContentSize.width += tempImage.size.width;
// Height.
//
if (tempImage.size.height > scrollContentSize.height) {
scrollContentSize.height = tempImage.size.height;
}
}
navbar.contentSize = scrollContentSize;
Which when i log the scrollviews properties, it has the subviews, a large enough content size and scrolling enabled.
Even when I add the UIScrollView to IB and link it to the same code it then works? (I comment out the NSAutoLayout code.
This leads me to believe that for the UIScrollView to work, I cannot use Auto layout.
Am I missing something?
Thanks
EDIT
The code also doesn't work programatically, when I try initWithFrame:frame with setTranslatesAutoresizingMaskIntoConstraints:YES

Check the attributes inspector for your scrollview in IB. Make sure that bounce vertically is checked.
Fixed this problem for me.

Related

Change tint of SFSymbol in UITableView Cell Accessory tvOS

I am adding an accessory view to a cell with:
UIImageSymbolConfiguration* configuration = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightRegular];
UIImageView* accessoryView = [[[UIImageView alloc] initWithImage:[UIImage systemImageNamed:#"globe" withConfiguration:configuration]] autorelease];
[accessoryView setImage:[imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
[accessoryView setTintColor:[UIColor labelColor]];
[cell setAccessoryView: accessoryView];
This works, but how can I configure it so that when the cell is highlighted, the globe icon changes from the labelColor tint to black (so it matches the text color)?
I have also tried making a highlighted image but it does not have any effect:
UIImageSymbolConfiguration* configuration = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightRegular];
UIImageView* accessoryView = [[[UIImageView alloc] initWithImage:[UIImage systemImageNamed:#"globe" withConfiguration:configuration]] autorelease];
UIImage* normalImage = [accessoryView.image imageWithTintColor:[UIColor labelColor]];
UIImage* highlightImage = [accessoryView.image imageWithTintColor:[UIColor blackColor]];
[accessoryView setImage:normalImage];
[accessoryView setHighlightedImage:highlightImage];
[cell setAccessoryView:accessoryView];
Furthermore, the highlighted image never seems to be used at all:
UIImage* image = [[UIImage systemImageNamed:#"checkmark" withConfiguration:configuration] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImage* highlightedImage = [[UIImage systemImageNamed:#"globe" withConfiguration:configuration] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImageView* accessoryView = [[[UIImageView alloc] initWithImage:image highlightedImage:highlightedImage] autorelease];
[cell setAccessoryView:accessoryView];
In the above code, the highlighted image is never shown.
This seems to work:
-(void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
NSIndexPath* nextPath = [context nextFocusedIndexPath];
if (nextPath)
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:nextPath];
UIImageView* accessoryView = (UIImageView *)[cell accessoryView];
[accessoryView setTintColor:[UIColor blackColor]];
}
NSIndexPath* prevPath = [context previouslyFocusedIndexPath];
if (prevPath)
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:prevPath];
UIImageView* accessoryView = (UIImageView *)[cell accessoryView];
[accessoryView setTintColor:[UIColor labelColor]];
}
}

Auto Layout on OS X - make NSTextField fill superview

I can't get Auto Layout to work on OS X. What I'm trying to do is pretty simple, namely I have an NSTextField that is supposed to fill the entire space of its superview. Here's the minimal working example code I'm using:
#import AppKit;
int main() {
#autoreleasepool {
NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 300, 300)
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered
defer:NO];
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
textField.stringValue = #"Lorem ipsum dolor sit atmet.";
[window.contentView addSubview:textField];
textField.translatesAutoresizingMaskIntoConstraints = NO;
window.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[textField setContentHuggingPriority:1
forOrientation:NSLayoutConstraintOrientationHorizontal];
[textField setContentHuggingPriority:1
forOrientation:NSLayoutConstraintOrientationVertical];
[window.contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[textField]-|"
options:0
metrics:nil
views:#{#"textField": textField}]];
[window.contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[textField]-|"
options:0
metrics:nil
views:#{#"textField": textField}]];
window.contentView.wantsLayer = YES;
window.contentView.layer.borderWidth = 5;
[window makeKeyAndOrderFront:nil];
[[NSApplication sharedApplication] run];
[textField release];
[window release];
}
return EXIT_SUCCESS;
}
When I run this, the text field doesn't appear. When you resize the window, you can clearly see the border of the content view resizing properly. What am I doing wrong?
I believe you shouldn't alter NSWindow's contentView behavior, e.g. setting its translatesAutoresizingMaskIntoConstraints property.
Removing the following line works for me:
window.contentView.translatesAutoresizingMaskIntoConstraints = NO;

UIImageView filling entire UICollectionView cell

I have a UICollectionView displaying a horizontal layout of images. Under each image, I'm displaying a label. In the storyboard, I've extended the height of the cell so that the label will be displayed underneath the cell. I've also set the height of the UIImageView in storyboard to be 20pts less than the cell. However, no matter what I do, the images take up the entire cell and the label is displayed on top of the image. Should I be setting the size of the imageview elsewhere? I found this thread which I thought would help since it's basically, identical, but the solution did not help me.
Here is my code...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell"; // string value identifier for cell reuse
ImageViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
cell.layer.borderWidth = 1.0;
cell.layer.borderColor = [UIColor grayColor].CGColor;
NSString *myPatternString = [self.imageNames objectAtIndex:indexPath.row];
cell.imageView.image = [self.imagesArray objectAtIndex:indexPath.row];
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.clipsToBounds = YES;
CGSize labelSize = CGSizeMake(CellWidth, 20);
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(cell.bounds.size.width/2, cell.bounds.size.height-labelSize.height, cell.bounds.size.width, labelSize.height)];
testLabel.text = myPatternString;
[cell.contentView addSubview:testLabel];
return cell;
}
Don't know if this will work for you, but I do this will a subclass of UIView which contains two subviews -- a UIImageView for the image and a UILabel for the label. Here is the essence of that subclass below (don't be bothered by the rounding of bottoms; in some areas I need the bottoms to be rounded, in others I don't). I just add this subview to the contentView of the cell. Don't know if it helps you but here it is. BTW, imageView is a class variable here but you might define it as a property.
- (id)initWithFrame:(CGRect)frame withImage:(UIImage *)img withLabel:(NSString *)lbl roundBottoms:(BOOL)roundBottoms;
{
self = [super initWithFrame:frame];
if (self)
{
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height-25.0f)];
if (roundBottoms)
{
imageView.layer.cornerRadius = 12;
imageView.layer.masksToBounds = YES;
}
else
{
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: imageView.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){12.0, 12.}].CGPath;
imageView.layer.mask = maskLayer;
}
[imageView setImage:img];
imageView.contentMode = UIViewContentModeScaleAspectFill; // default
[self addSubview:imageView];
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 25.0f, frame.size.width, 25.0f)];
label.text = lbl;
labelText = lbl;
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor blackColor];
label.adjustsFontSizeToFitWidth = YES;
label.minimumScaleFactor = 0.50f;
label.backgroundColor = [UIColor clearColor];
self.tag = imageItem; // 101
[self addSubview:label];
}
return self;
}
I have another version of it I use where I calculate the height of the label based on the overall frame height that is passed in. In this one, the cell sizes are static so the label heights can be as well.

UIScrollView Autolayout prevent from scrolling vertically

I'm wondering how to crop image inside UIscrollView with autolayout
I'm trying to make UIscrollView scroll only horizontally. if image is higher than view height it should be cropped. I've tried a lot properties but can't make all images inside uiscrollview same height as view to avoid scrolling vertically.
Do i miss something?
#import "WelcomeController.h"
#interface WelcomeController ()
#property (strong, nonatomic) UIScrollView *scrollView;
#property (nonatomic,strong) NSArray *contentList;
#end
#implementation WelcomeController
#synthesize contentList =_contentList;
- (void)updateUI
{
UIScrollView* sv = self.scrollView;
id previousLab = nil;
for (UIView *lab in _contentList) {
lab.translatesAutoresizingMaskIntoConstraints = NO;
lab.backgroundColor = [UIColor blackColor];
lab.contentMode = UIViewContentModeScaleAspectFit;
[sv addSubview:lab];
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[lab]|"
options:0 metrics:nil
views:#{#"lab":lab}]];
if (!previousLab) { // first one, pin to top
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[lab]"
options:0 metrics:nil
views:#{#"lab":lab}]];
} else { // all others, pin to previous
[sv addConstraints:
[NSLayoutConstraint
constraintsWithVisualFormat:#"H:[prev][lab]"
options:0 metrics:nil
views:#{#"lab":lab, #"prev":previousLab}]];
}
previousLab = lab;
}
// last one, pin to bottom and right, this dictates content size height
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[lab]|"
options:0 metrics:nil
views:#{#"lab":previousLab}]];
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[lab]|"
options:0 metrics:nil
views:#{#"lab":previousLab}]];
}
-(void)setContentList:(NSArray *)contentList
{
_contentList = contentList;
[self updateUI];
}
- (void)setupScrollView
{
UIScrollView* sv = [UIScrollView new];
sv.backgroundColor = [UIColor redColor];
sv.translatesAutoresizingMaskIntoConstraints = NO;
sv.pagingEnabled = YES;
sv.showsHorizontalScrollIndicator =NO;
sv.showsVerticalScrollIndicator = NO;
sv.bounces =NO;
[self.view addSubview:sv];
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[sv]|"
options:0 metrics:nil
views:#{#"sv":sv}]];
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[sv]|"
options:0 metrics:nil
views:#{#"sv":sv}]];
self.scrollView = sv;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupScrollView];
//for testing
UIImageView *image1=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"welcome1.jpg"]];
UIImageView *image2=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"welcome2.jpg"]];
UIImageView *image3=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"welcome3.jpg"]];
self.contentList = [NSArray arrayWithObjects:image1,image2,image3,nil];
}
#end
Have you tried setting the height of the scroll view explicitly?
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[_sv(123)]" options:0 metrics:nil views:views]];
You would need to replace the height above (123) with the height you need, obviously, as well as views.
Autolayout automatically manages the UIScrollView's contentSize (the scrollable area). So if you stick a subview in there with an intrinsic size that is larger than the height, it will increase the contentSize. I can think of two things:
Stick images in a plain UIView with the same height as the scrollview.
Subclass the UIImageView and override the intrinsicContentSize method to return a fixed height for all images. This seems like a poor solution, though.
I think you should be able to set the image view's frames to a fixed height (via constraints). Then add constraints to have the image views top and bottom fixed with x constant from the scrollview.
This will let the scrollview know its exact content size to use. As long as its frame, then, (determined by whatever constraints you give it in relation to its superview) is >= the image view's fixed heights, it won't scroll vertically.

how to show images as a gridview like format in uiscrollview in ios?

its just a week that am into ios devlopement and am facing some problem that i cant show the images in scrolview with gridview format...i dont know how to set the frame size to show images in proper gridview format..
here is my code
that add 5 images in scrollview
for(int i=1;i<6;i++)
{
UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(x+0, 0, 320, 460)];
[image setImage:[UIImage imageNamed:[NSString stringWithFormat:#"e1%d.png",i]]];
[scr addSubview:image];
x+=320;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.delegate = self;
image.userInteractionEnabled = YES;
[image addGestureRecognizer:tapGesture];
}
scr.pagingEnabled=YES;
scr.contentSize = CGSizeMake(320*5, 300);
[self.view addSubview:scr];
but all 5 images shows in one horizontal line but i want to show in every line 2 images.
here is the solution, i've implemented it in my app. Here is my code sv_port is my scrollView. Download SDWebImageDownloader class files and import it in your project. Add
relevant framework in your project. like imageIO.framework, QuartzCore
if your images are not fetching from url, then u dont need to use asyncImage view., so dont need to download SDWebImageDownloader.
Now, in your .m add
#import "UIImageView+WebCache.h"
#import "SDImageCache.h"
#import "SDWebImageCompat.h"
//function for adding image in your scrollview
-(void)populateImages
{
int x=6,y=6;
for(UIView * view in sv_port.subviews)
{
if([view isKindOfClass:[UIImageView class]])
{
[view removeFromSuperview]; view = nil;
}
if([view isKindOfClass:[UIButton class]])
{
[view removeFromSuperview]; view = nil;
}
}
for(int p=0;p<[Manufacturer count];p++)
{
UIButton *btnImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
btnImageButton.frame = CGRectMake(x,y,70,70);
[btnImageButton setTag:p];
[btnImageButton addTarget:self action:#selector(nextview:) forControlEvents:UIControlEventTouchUpInside];
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.frame=CGRectMake(btnImageButton.frame.origin.x+25,btnImageButton.frame.origin.y+25, 20, 20);
spinny.backgroundColor=[UIColor clearColor];
[spinny startAnimating];
[sv_port setScrollEnabled:YES];
[sv_port addSubview:spinny];
UIImageView *asyncImageView = [[[UIImageView alloc] initWithFrame:btnImageButton.frame] autorelease];
asyncImageView.backgroundColor=[UIColor clearColor];
CALayer *layer;
layer = asyncImageView.layer;
layer.borderWidth = 0.5;
layer.cornerRadius = 5;
layer.masksToBounds = YES;
[asyncImageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", yourUrl] ] placeholderImage:[UIImage imageNamed:nil] options:0 andResize:CGSizeMake(btnImageButton.frame.size.width,btnImageButton.frame.size.height) withContentMode:UIViewContentModeScaleAspectFit];
asyncImageView.contentMode = UIViewContentModeScaleAspectFit;
[sv_port addSubview:btnImageButton];
[sv_port addSubview:asyncImageView];
int imgCntPort=0;
imgCntPort=(sv_port.frame.size.width/(asyncImageView.frame.size.width));
//NSLog(#"imgport %d",imgCntPort);
if((p+1)%imgCntPort==0)
{
x=5;
y=y+80;
}
else
{
x=x+80;
}
}
sv_port.contentSize = CGSizeMake(0, y);
glob_x =0; glob_y =y;
}
By this code you will get 4 images in a row., By the change co-Ordiante of x and y you can maintain number of images per row to display.
Hope this helps. Thanks

Resources