Round imageview in collectionviewcell - objective-c

i am working on uicollectionview. i want customize cell so i took separate class file for cell. i took an image in cell from storyboard. my problem is i want rounding image but image shape convert to be diamond. please suggest me the way to convert this diamond image into to circle.
see here
UICollectionView in storyboard
ViewController.h
#interface ViewController : UIViewController
#property(nonatomic, weak)IBOutlet UICollectionView *my_collectionview;
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController
#synthesize my_collectionview;
- (void)viewDidLoad {
[super viewDidLoad];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 9;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionViewCell" forIndexPath:indexPath];
return cell;
}
CollectionViewCell.h
#interface CollectionViewCell : UICollectionViewCell
#property(nonatomic, weak) IBOutlet UIImageView *temp_imgview;
#end
CollectionViewCell.m
-(void)awakeFromNib{
[temp_imgview.layer setCornerRadius:self.temp_imgview.frame.size.width/2];
temp_imgview.layer.borderWidth=0.5;
temp_imgview.layer.masksToBounds = YES;
temp_imgview.clipsToBounds=YES;
}
if i put hard code 100 instead of self.temp_imgview.frame.size.width/2 then it is working. can anybody help me how can i solve this

Depending on your constraints in the storyboard, the awakeFromNib might not be the correct place to all the rounded corners. That is because it might be that the frame of the imageView is not final there.
You could try adding the code for the rounded corners in layoutSubviews. Something like this:
- (void)layoutSubviews {
[super layoutSubviews];
[temp_imgview.layer setCornerRadius:self.temp_imgview.frame.size.width/2];
temp_imgview.layer.borderWidth=0.5;
temp_imgview.layer.masksToBounds = YES;
temp_imgview.clipsToBounds=YES;
}
Also, in your awakeFromNib, you missed the super call.
Let me know if this worked out for you or need more help! Good luck
Update
You could try using the size of the image, instead of the frame. Something like this:
- (void)layoutSubviews {
[super layoutSubviews];
[temp_imgview.layer setCornerRadius:self.temp_imgview.image.size.width/2];
temp_imgview.layer.borderWidth=0.5;
temp_imgview.layer.masksToBounds = YES;
temp_imgview.clipsToBounds=YES;
}
If this does not work either, try logging the frame of your image on iPhone and iPad to see what differs between them

Try adding [self layoutIfNeeded], it worked for me.
- (void)layoutSubviews {
[super layoutSubviews];
[self layoutIfNeeded];
imageView.layer.cornerRadius = CGRectGetWidth(imageView.bounds) / 2;
imageView.layer.borderWidth = 0.1;
imageView.clipsToBounds = YES;
}

Related

How to use NSCollectionViewItem without subclassing it?

I am writing a very simple macOS application that I'd like to show a few images in a collection view. I don't need any special behavior for how they are displayed. The docs for NSCollectionViewItem say:
The default implementation of this class supports the creation of a simple item that displays a single image or string.
That is what I want. However, I can't find any information on how to create a default NSCollectionViewItem.
The documentation for NSCollectionView states:
Every data source object is required to implement the following methods:
collectionView:numberOfItemsInSection:
collectionView:itemForRepresentedObjectAtIndexPath:
The second method above returns an NSCollectionViewItem. From reading examples I gather that the traditional way of creating an NSCollectionViewItem in this case is to call:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:<some identifier>
forIndexPath:indexPath];
The problem is that I don't understand what <some identifier> should be. I don't have a nib that contains an NSCollectionViewItem because I'm not subclassing it or customizing it in any way. I've tried adding the following to my data source:
- (void)awakeFromNib
{
[imageCollectionView registerClass:[NSCollectionViewItem class]
forItemWithIdentifier:#"Image"];
}
where imageCollectionView is the NSCollectionView in question. And then in my - (NSCollectionViewItem *)collectionView:itemForRepresentedObjectAtIndexPath: method, I call:
NSCollectionViewItem* newCollectionViewItem = [imageCollectionView makeItemWithIdentifier:#"Image"
forIndexPath:indexPath];
But this throws an exception and prints this to the console:
2016-12-19 17:51:27.463 MyApp[28177:3926764] -[NSNib _initWithNibNamed:bundle:options:] could not load the nibName: NSCollectionViewItem in bundle (null).
followed by a stack trace.
So how do I go about creating and using an NSCollectionViewItem that isn't subclassed or modified in any way?
Here is a very simple example which uses a Nib for the item's prototype:
#interface ViewController()
#property (weak) IBOutlet NSCollectionView *collectionView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSNib *theNib = [[NSNib alloc] initWithNibNamed:#"Item" bundle:nil];
[self.collectionView registerNib:theNib forItemWithIdentifier:#"item"];
}
#pragma mark NSCollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)inCollectionView {
return 1;
}
- (NSInteger)collectionView:(NSCollectionView *)inCollectionView numberOfItemsInSection:(NSInteger)inSection {
return 10;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)inCollectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)inIndexPath {
NSCollectionViewItem *theItem = [inCollectionView makeItemWithIdentifier:#"item" forIndexPath:inIndexPath];
NSTextField *theLabel = (NSTextField *)theItem.view;
theLabel.stringValue = [NSString stringWithFormat:#"%d.%d", (int)inIndexPath.section, (int)inIndexPath.item];
return theItem;
}
#end
The NIB contains just a NSCollectionViewItem with a text field as view.
Addendum:
I think you should create a NSCollectionViewItem.xib for the registerClass variant. A view controller will search for a NIB with its class name, if you doesn't create its view manually in loadView. Thus, you can't use plain NSCollectionViewItem without a NIB for registering a class, because of makeItemWithIdentifier:forIndexPath: will access the view of the item.
I found a way to set up NSCollectionView without needing to add a .xib file.
The trick was inheriting from NSCollectionViewItem and using that subclass for -[NSCollectionView registerClass:forItemWithIdentifier:].
#import "ViewController.h"
#interface MyViewItem : NSCollectionViewItem
#end
#implementation MyViewItem {
}
- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nil bundle:nil];
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
[button setTitle:#"Button"];
[self setView:button];
return self;
}
#end
#implementation ViewController {
IBOutlet NSCollectionView *_collectionView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[_collectionView registerClass:[MyViewItem class]
forItemWithIdentifier:#"item"];
[_collectionView setDataSource:self];
}
- (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath {
return [_collectionView makeItemWithIdentifier:#"item" forIndexPath:indexPath];
}
#end

How do I get buttons in a cell on a UICollectionView running on tvOS (AppleTV) to take focus?

Here is my very basic code. It shows five cells in a UICollectionView (each cell with a simple button in it). All buttons point to the single IBAction method. This is all setup within the Main.storyboard.
I can't get tvOS to take focus of the buttons though. Any idea why?
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 5;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
return cell;
}
- (IBAction)buttonAction
{
// do stuff
}
#end
By default UICollectionViewCell is a focusable means it will get focus instead of its subview, but you can override this functionality by overriding preferredFocusedView and return which ever view you want to get focus.
- (UIView *)preferredFocusedView
{
return _button;
}
read more about Initial Focus and the Preferred Focus Chain
or you can just
- (BOOL)collectionView:(UICollectionView *)collectionView canFocusItemAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}

Changing from UIView to UIView in another class

Here is a small problem I am having. I am not too good at programmatically changing views, but this is what I have:
//(.h)
#import <UIKit/UIKit.h>
#import "Detail.h"
#interface List : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
}
#property (retain, nonatomic) IBOutlet UITableView *tableView;
#property (retain, nonatomic) Detail *detail;
#end
and
//(.m)
#synthesize detail=_detail;
- (Detail *)detail
{
NSLog(#"Detail UIView construction started.");
if (_detail != nil)
{
return _detail;
}
Detail *aDetailView = [[Detail alloc] init];
_detail = aDetailView;
[self.view addSubview:_detail.view];
//I never really set it to setHidden:YES, but just to make sure I'm setting it NO here.
[_detail.view setHidden:NO];
return _detail;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView transitionFromView:self.view toView:self.detail.view duration:1 options:UIViewAnimationOptionTransitionFlipFromRight completion:nil];
}
As output:
2012-02-07 11:17:51.909 TodoApp[4232:fb03] Detail UIView construction started.
The view seems to do the FlipFromRight animation fine, but the screen is totally black.
As I said, I'm not good at changing views programmatically.
Thanks for any help!
=============
Answering my own question.
It was really stupid. The "Back" button in the Title bar had an unsupported configuration. So the View did not want to load... fixed it now.
- (Detail *)detail
{
NSLog(#"Detail UIView construction started.");
if (_detail != nil)
{
return _detail;
}
Detail *aDetailView = [[Detail alloc] init];
[self.view addSubview:aDetailView.view];
//I never really set it to setHidden:YES, but just to make sure I'm setting it NO here.
[aDetailView.view setHidden:NO];
_detail = aDetailView;
return _detail;
}
make these changes and let me know the result..
you are returning _detail before adding it to superview
so add this line
return _detail;
after this line [self.view addSubview:_detail.view];
like this
[self.view addSubview:_detail.view];
[_detail.view setHidden:NO];
return _detail;
Answering my own question.
It was really stupid. The "Back" button in the Title bar had an unsupported configuration. So the View did not want to load... fixed it now.

Objective C examples sought

I'm trying to add scrollbars to an IKImageView. Basically at the moment, I need some examples of a program that loads an image into a view, and if the window is too small, sets up scrollbars that do the right things...
Why can I not find these examples on the apple dev site?
Added info:
After looking at ImagekitDemo I see that evidently I DO need to embed the IKIMageView in a ScrollView. (and somehow that makes the has___Scroller properties of the IKImageView YES...)
However, now (And this is true in ImageKitDemo as well) The scroll bars are fine as long as only one (or neither) is needed. However, as soon as both are needed, and either dimension of the window is smaller than the image, BOTH scrollbars disappear.
Mouse scrolling still works.
ZoomViewController.h
#interface ZoomViewController : UIViewController <UIScrollViewDelegate>
{
ForecastImage* detailImage; // wrapper class around UIImage (optional - could just be UIImage)
IBOutlet UIImageView* imageView;
IBOutlet DoubleTapScrollView* zoomableScrollView;
}
#property (readwrite, nonatomic, retain) ForecastImage* detailImage;
- (IBAction) dismissZoomViewController;
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView;
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
#end
ZoomViewController.m
#implementation ZoomViewController
#synthesize detailImage;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{
[imageView setImage:[self.detailImage renderedImage]];
[zoomableScrollView setContentSize:[[imageView image] size]];
[zoomableScrollView setMaximumZoomScale:5.0];
[zoomableScrollView setMinimumZoomScale:0.25];
}
- (void) viewDidAppear:(BOOL)animated
{
self.navigationItem.title = [SearchService getDisplayName:[self.detailImage forecastArea]];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc
{
imageView.image = nil;
self.detailImage = nil;
[super dealloc];
}
- (IBAction) dismissZoomViewController
{
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark Pinch-n-Zoom
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
CGSize newSize = CGSizeMake(imageView.image.size.width * scale, imageView.image.size.height * scale);
[scrollView setContentSize:newSize];
}
#end
The best place to start is the Scroll View Programming Guide. Basically, you need to put the IKImageView inside a NSScrollView. If the IKImageView size exceeds the visible rectangle of the NSScrollView, then scrollbars will appears.
The following sample uses IKImageView to perform various zoom and resizing operations.

Why isn't my UIButton responding to touches?

I'm sure I'm overlooking the obvious as I've got countless working buttons...but...for whatever reason this one is not cooperating...
I've added a UIButton (Rounded Rect) to a UIView subclass (DialogView) which is a subview of my view controller's view. This subview is created almost entirely in IB. I've wired up the button to (IBAction)okButtonPressed:(id)sender in IB to Touch Up Inside and created a corresponding method in DialogView. However when I "touch" this button it doesn't trigger the method. userInteractionEnabled is true for the VC's view, DialogView and the UIButton.
Thinking maybe initWithCoder had to do some frame manipulation or something I added the following which successfully logs to console.
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super initWithCoder:decoder]) {
NSLog(#"DialogView initWithCoder called");
}
return self;
}
In further exploration I wired up an IBOutlet to the button and then if I try to change the titleLabel from the view controller I notice that it get's severely truncated. Default text of say "Press Me!" set in IB displays fine when view is first drawn. But if I change the text...
self.DialogView.okButton.titleLabel.text = #"Not Working";
...it gets truncated to "N..."
Dunno if this is related. Probably...
Anyone see what I've screwed up here?
Edit (adding code related to showing UIButton):
From the View Controller:
self.DialogView = [[[NSBundle mainBundle] loadNibNamed:#"DialogView" owner:self options:nil] objectAtIndex:0];;
self.DialogView.myVC = self;
self.DialogView.backgroundColor = [UIColor clearColor];
self.DialogView.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
self.DialogView.nameLabel.text = loan.fullName;
self.DialogView.noteLabel.text = loan.summaryOfLoan;
self.DialogView.amountLabel.text = [currencyFormatter stringFromNumber:loan.originalAmount];
self.DialogView.alpha = 0.0;
[self.view addSubview:DialogView];
The UILabels all displaying as expected. As is the problem UIButton. I can see it I just can't interact with it!?!
DialogView's interface:
#class MyViewController;
#interface DialogView : UIView {
IBOutlet UILabel *nameLabel, *noteLabel, *amountLabel;
IBOutlet UIImageView *arrowView;
IBOutlet UIButton *okButton;
MyViewController *myVC;
}
#property (nonatomic, retain) UILabel *nameLabel, *noteLabel, *amountLabel;
#property (nonatomic, retain) UIImageView *arrowView;
#property (nonatomic, assign) MyViewController *myVC;
#property (nonatomic, retain) UIButton *okButton;
- (IBAction)okButtonPressed:(id)sender;
#end
And DialogView's implementation:
#import "DialogView.h"
#import "MyViewController.h"
#implementation DialogView
#synthesize nameLabel, noteLabel, amountLabel, arrowView, okButton;
#synthesize myVC;
- (void)dealloc {
[nameLabel release];
[noteLabel release];
[amountLabel release];
[arrowView release];
[okButton release];
[super dealloc];
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super initWithCoder:decoder]) {
NSLog(#"DialogView initWithCoder called");
}
return self;
}
- (IBAction)okButtonPressed:(id)sender {
NSLog(#"pressed DialogView OK button");
[self.myVC.navigationController popViewControllerAnimated:YES];
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
#end
I thought that we should use -setTitle:forState: in order to set button's title ?
An other thought, did you check that the button's frame is not CGRectZero ? And by the way, all the frames for the view in the hierarchy ? And check that one superview in the hierarchy is not user interaction disabled ?
And, I think imageView does not respond to touches, do you have one in your code ?
I was just having more or less the same problem and I found that my containing view did not have "User Interaction Enabled".
Hope this helps.
Do you maybe have two buttons on top of one another? Change the IB project window to the detail view and see if your view has more buttons than you are expecting. Maybe you've wired up a button that's not actually getting the press you're expecting.