How to position view relative to parent? - cocoa-touch

I have a UIViewController with an MKMapView in it. In viewDidLoad of this controller, I add the MKMapView:
[self.view addSubview:mapView];
I want to display this map in a tableview cell. In the tableview controller's cellForRowAtIndexPath:, I do this:
[cell addSubview:mapView.view];
where cell is a UITableViewCell. I've set the mapview frame to
mapView.frame = CGRectMake(0, 0, 200, 100);
The mapview appears to the bottom left of the cell. Meaning, it is partially in the cell and also out of it. The map overlaps much of the cell but I want it to fill the cell and be bounded by it. How can that be done?
There isn't an associated xib for these controllers.
--- EDIT ------
The tableview is styled as grouped. It looks as though I just need to do some trial and error offsetting to get the map matched up correctly.

did you try setting the clipbounds property on the mapview?

Related

How to center a cell with the content offset in a UICollectionView with scrollToItemAtIndexPath

I am implementing a UICollectionView which shows only a single line of cells. It is like an image cover flow. This means I have subclassed UICollectionViewFlowLayout. My implementation works fine when I use my finger for scrolling, meaning that the following delegate method is called and I center the cell;
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
However when the view loads I want the view to automatically scroll to a cell. For this automatic scroll I use the following;
[self.CollectionView scrollToItemAtIndexPath:_selectedIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
The problem is that targetContentOffsetForProposedContentOffset is not called and thus when the automatic scroll is complete the cell is off the centre.
So how can I programmatically scroll my collection view so that it will also centre on the cell being scrolled to?
Solved this issue myself.
According to the book "iOS UICollectionView The Complete Guide" (Listing 6.7) scrollToItemAtIndexPath: cannot be used in this cover flow type layout as it will not centre the cell.
I have posted below the way it is suggested in the book. Based on the indexPath you want to have you need to calculate the offset of the collection view yourself, and then use the targetContentOffsetForProposedContentOffset: to automatically centre it for you.
CGPoint proposedOffset = CGPointMake(0, 0);
proposedOffset.x = _selectedIndexPath.item * (flow.itemSize.width + flow.minimumLineSpacing);
CGPoint contentOffset = [flow targetContentOffsetForProposedContentOffset:proposedOffset withScrollingVelocity:CGPointMake(0, 0)];
[self.statCollectionView setContentOffset:contentOffset animated:YES];

Accessory View Is Showing Up Half Off of the Cell

I cant figure out how to get my accessory view to fit into my cell. Also, When I add a subview it adds it to the right of the first subview added. I want the sub views to be added from right to left.
I have this for my accessory view
UIView *myAccessoryView = [[UIView alloc] initWithFrame:cell.accessoryView.frame];
And anytime I add a sub view I just write this
[myAccessoryView addSubview:greenCircle];
And as soon as it adds another subview it is placed to the right of the previous sub view which is even further off my cell. How do I reverse the way it adds subview? How can I format the accessory view to stay on the cell?
You are trying to init myAccessoryView with the frame of accessoryView that doesn't yet exist. It will be created after cell creation (and adding to tableView) if you specify cell.accessoryType property, or if you create and set accessoryView yourself like:
[cell setAccessoryView:myAccessoryView];
So if You do this:
UIView *myAccessoryView = [[UIView alloc] initWithFrame:cell.accessoryView.frame];
[cell setAccessoryView:myAccessoryView];
You will have accessoryView with zero size and coordinates. After the cell is set to tableView, accessoryView will get standart origin point in the right side of the cell. But it still have zero size. And all subviews You add to accessoryView will be set to that origin point.
Method "addSubview" cant change subviews frame, it just places one view to another view.
Have no ideas why new subviews are placed to the rigtht of the previous.
To put your subviews to the right place, You have to set their frames manually. For example:
UIView *greenCircle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[myAccessoryView addSubview:greenCircle];
Hope that helps.

UITableViewCell's backgroundView overlapping contentView

I am trying to set the backgroundView parameter of a UITableViewCell, but the backgroundView is overlapping the bounds of the cell. I have tried setting masksToBounds to YES, but that doesn't seem to make a difference. Please can you tell me where I am going wrong?
Here is an image showing my problem:
Here is my code:
UIImageView *iv = [[[UIImageView alloc] initWithFrame:cell.frame] autorelease];
[iv setImage:[UIImage imageNamed:#"paper"]];
[iv.layer setMasksToBounds:YES];
[cell.layer setMasksToBounds:YES];
[cell.contentView.layer setMasksToBounds:YES];
[cell setBackgroundView:iv];
Using masksToBounds doesn't work because the bounds of the cell are a rectangle.
Even if the corners of the cell are rounded, they're still part of the cell (but they contain transparent pixels). When a cell is displayed in a grouped table view, its background view (and its selected background view) is drawn in regard of its position in its section (middle, top, bottom, single).
So, if you want to provide a custom background view, you need to compute the position of the cell in its section and provide the adequate background :
either by using 4 different images
or by using the mask property of the background image's layer
or by subclassing UIView and implementing drawRect: so the graphic context is clipped before the image is drawn.
Are you setting every cell that background view, if so why don't you just set it to the table view background.

How do you determine the size/frame of a custom UINavigationItem.titleView?

After creating a custom view and assigning it to the navigationItem.titleView property it is displayed like this
with the custom view filling the space between the two buttons. Therefore, the custom view is not centered on the navigation bar. How do I determine the frame of the view in the .titleView property? I want to center some text in the navigation bar, say under the time stamp.
If you really want to get titleView's frame (in your top-level view's coordinate space), you can do this:
[self.navBar layoutIfNeeded];
CGRect titleViewFrameInTopLevelViewSpace = [self.navigationItem.titleView
convertRect:self.navigationItem.titleView.bounds
toView:self.view];
You need to do layoutIfNeeded if you have just assigned titleView, because by default the navigation bar won't lay out its subviews until the next pass through the run loop.
That said, the titleView will be centered automatically, if it fits. I think you are setting the frame (or bounds) of your custom view too large. I tested this two ways:
I set up the titleView directly in the XIB. I simply dragged a View from the Object library onto the center of the navigation bar:
It sized the view to 128x33 automatically. The resize handles let me adjust the size. It stays centered until it overlaps the Categorize button. Then it shifts left.
I set the titleView property in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
customView.backgroundColor = [UIColor greenColor];
self.navItem.titleView = customView;
}
The result looks like this:
You could get the width of the leftBarButtonItem and the rightBarButtonItem after you've set them, and then use that to determine how to centre within the view you supply to titleView. That might do what you want?

Adding a button (UIButton) to a custom tableview cell drawn with drawRect:

I am currently working a on project where I have lots of custom table view cells. Part of the requirements is that the cells be able to expand if their default size can not hold all of the content. If they need to be able to expand I have to add a UIButton to the cell and when it is tapped redraw it in a bigger view where all the data fits. Currently in draw rect I essentially do this:
if([self needsExpansion]) {
[self addExpansionButton];
}
-(void)addExpansionButton {
self.accessoryButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.accessoryButton setShowsTouchWhenHighlighted:YES];
UIImage *buttonImage = [UIImage imageNamed:#"blue_arrow_collaps_icon.png"];
[self.accessoryButton setFrame:CGRectMake(280, 82, buttonImage.size.width, buttonImage.size.height)];
[self.accessoryButton setImage:buttonImage forState:UIControlStateNormal];
[self.accessoryButton addTarget:self action:#selector(toggleExpanded) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.accessoryButton];
}
This works fine, except for when I click anywhere else in the cell the button flickers and disappears. Anyone know how to propertly do this?
From the UITableViewCell Class Reference:
You have two ways of extending the
standard UITableViewCell object beyond
the given styles. To create cells with
multiple, variously formatted and
sized strings and images for content,
you can get the cell's content view
(through its contentView property) and
add subviews to it.
Instead of adding the accessory button as a subview of the UITableViewCell, you should add it as a subview of the contentView:
[[self contentView] addSubview:self.accessoryButton];
Have you worked out the following problem in your design approach?: Let's say one of your cells (let's call it A) determines it needs expansion, so you add a button to it. What happens when the user scrolls through the UITableView? For performance reasons, your UITableView delegate should be using dequeueReusableCellWithIdentifier in tableView:cellForRowAtIndexPath:. So you'll be reusing A to display a different row of the table. Do you really want A to have an accessory button? Probably not, since it's now representing a different object.
You're probably better off doing the cell customization at the UITextViewDelegate. In tableView:cellForRowAtIndexPath:, you can determine if the object being displayed at the row specified needs a button, and if it does add it as a subview to the contentView.
Then again, if your table size is always relatively small (say < 50), you can use this approach Jeremy Hunt Schoenherr suggests.