How to provide an own contentView for using -drawRect? - iphone

I want to use -drawRect: in an UITableViewCell subclass but it is covered by contentView. So the best option seems to be that I make a UIView subclass with my -drawRect: code and use that as contentView. But how could I feed my UITableViewCell subclass with that contentView?
UITableViewCell creates that on its own when the contentView property is accessed. Would I simply override the getter method and then provide my own view there?

Make a subclass of UIView and implement your drawing code in this objects drawRect method.
Add this subclass to the contentView of the cell upon initialisation.
[cell.contentView addSubview:customView];
No need to modify the cell's drawRect method.

Related

How to set the height of subviews of UItableViewCell when cell is created programaticalliy

I have custom cell created with nib. In the table view I am using the method -(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath to set the height of cell
Everything works fine.
But the problem is that I also want to change the size of UIlabel which is added as subview in nib of cell.
How do I do that?
Which metod to override in customcell class ?
The method you are looking for is:
-(void)layoutSubviews
{
[super layoutSubview];
//Do your magic
}
layoutSubviews is call after the cell is created and whenever the device orientation changes, to allow you to resize and/or move the subviews (plus make any other minor adjustments) to compensate for differences between the orientations, but in this case you can also use it to redraw your subviews.
As you have UILabel in your custom cell class, make a function in that class that take frame you want to set as parameter. Set frame of label in that function. You need to call this function from your cellForRowAtIndexPath method before returning the cell.
If you are reusing your custom cell you should call method only when the (cell == nil)
Also if you can add some code in your question that would be helpful and you can get more precise answer.
You need to treat your custom cell in the same way you would treat a normal view or view controller class with a xib. i.e. You need to create IBOutlets for the controls in you custom cell and during creation of the cell you can access the controls quite easily.
myCell.myCustomUILabel.text = #"blah"
There are some gotchas when using custom cells in a xib and onnecting up the IBOutlets. This SO answer (of mine) explains how to create and link up IBOutlets of a custom cell.

inherit from a subclass of UIView

I've added a functionality to UIView by extending drawRect.
This works great for a simple UIView, but the problem is that I want it to work also for UILabel, UIButton, UIImageView and every other component that inherits from UIView.
I was wondering what is the best way to achieve this. Can I make a subclass of UILabel (for example) that inherits from MyView instead of UIView?
You can make a category of UIView and override drawRect function, so all subclasses of UIView, that call to [super drawRect:...] will use this category function, though you should be extremely cautious while doing this, since you override something very basic there. I did it at time with UINavigationBar when I would need to add a background picture there. But take into consideration that not all subclasses of UIView call [super drawRect:...].

LayoutSubviews for Custom UITableViewCell and UIView

I have a custom UITableViewCell. It has a UIView which is added to the "contentView" of the UITableViewCell. For any update, I'm redrawing that UIView by calling its "setNeedsDisplay" and implementing drawing inside "drawRect" method of the UIView.
The UITableViewCell overrides "willTransitionToState" and according to the bit mask value, asks the UIView to redraw.
Because I'm asking the UIView to redraw itself again, every time I do a "swipe to delete", I see the cell "flicker" a moment; even the text that didn't move position due to the Delete button suffers from a flicker since everything is being redrawn.
I'm aware that a possible solution is not to call "setNeedsDisplay" of the UIView from the "willTransitionToState" but instead call "setNeedsLayout" and have the UIView implement "layoutSubviews".
This is where I'm stuck at: how can I re-layout my UIView since everything inside my UIView is "drawn" (I use "drawInRect" and "drawAtPoint" methods for strings and images). There is also a string on the right side that I wanna hide when the "Delete" button appears (like in the Messages app in iPhone).
How can I do this by doing re-layout instead of re-draw?
Thank you!!!
I think there's an issue with your approach. Rather than draw everything, it's better to set up your subviews in an init method, or in the NIB.
In the willTransitionToState method, update whatever subviews according to the state transition.
In layoutSubviews, update each subview's origin and size as required.
Here's some detail from the willTransitionToState documentation. Although, I'm sure you'd have seen this already:
Subclasses of UITableViewCell can implement this method to animate additional changes to a cell when it is changing state. UITableViewCell calls this method whenever a cell transitions between states, such as from a normal state (the default) to editing mode. The custom cell can set up and position any new views that appear with the new state. The cell then receives a layoutSubviews message (UIView) in which it can position these new views in their final locations for the new state. Subclasses must always call super when overriding this method.

How to intercept UIScrollView contentOffset changes from UITableView subclass?

Actually, a UITableView is a UIScrollView (inherits from that). Now, I made a UITableView subclass and added this line of code to it:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"contentOffset: %#", NSStringFromCGPoint(self.contentOffset));
}
For some reason this is never called when I scroll the table view. But since UITableView has a delegate property on it's own, I assume that it must implement UIScrollViewDelegate protocol and is the delegate for the scroll view itself. Isn't it?
How could I intercept scroll position changes? I want to read them only. Probably I couldn't set them with contentOffset, right?
Probably I couldn't set them with
contentOffset, right?
As UITableView inherits from UIScrollView you can get and set its contentOffset property.
Note also that UITableViewDelegate protocol is defined the following way:
#protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>
That is it conforms to UIScrollViewDelegate protocol as well so your tableView's delegate(not UITableView itself) can implement any UIScrollViewDelegate methods and they should get called fine.
Just implement setContentOffset: and call super after you read the values you want. A UITableView is a UIScrollView so you can scroll it by calling setContentOffset: as well.

touchesBegan for UITable's Cell

How can I use touchesbegan in a table's cell without having to subclass a whole cell. Something like addTarget..... which is available for a UIButton?
(in vb.net this would be like AddHandler I think)
You must subclass UITableViewCell in order to have access to individual touches on a tableview cell.
You cant do it, you will have to subclass UITableView cell just like the post before me said, then you can add some view in the cells content view there which can delegate the touches to the tableviewcontroller or wherever they need to go...
#Jaco Relkin, you can implement the messages on the UITableViewDelegateProtocol, for example: the message tableView:didSelectRowAtIndexPath: documented here:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:didSelectRowAtIndexPath: