I made a custom button using drawRect: and put it in my headerview for my tableview. I want the custom button to be hidden when editing mode is selected. i know i can do that by using the method:
-(void)setEditing:(BOOL)editing animated:(BOOL)animated
but for some reason, my button isn't actually dissapearing when I either 1) set it to nil, 2) or use the button.hidden property. Here is my code:
TableViewController.h:
#interface ToDoTableViewController : UITableViewController <Properties2ViewControllerDelegate, UITableViewDelegate>{
addButtonView *button;
}
#property (strong, nonatomic) NSMutableArray *taskArray;
#property (strong, nonatomic) NSMutableArray *completedArray;
-(IBAction)addCell:(id)sender;
-(void)buttonPressed:(id)sender;
#end
TableViewController.m
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView *headerView;
UIView *seperatorView;
CGRect testFrame = CGRectMake(280.0, 5.0, 30.0, 30.0);
button = [[addButtonView alloc]initWithFrame:testFrame];
NSString *sectionTitle = #"Incomplete Tasks";
NSString *section2Title = #"Completed Tasks";
UILabel *label = [[UILabel alloc]init];
label.textColor = [UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f];
label.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:25];
label.backgroundColor = [UIColor clearColor];
label.frame = CGRectMake(10.0, 0.0, 320.0, 40.0);
headerView = [[UIView alloc]initWithFrame:label.frame];
[button addTarget:self action:#selector(addCell:) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
CGRect sepFrame = CGRectMake(0, headerView.frame.size.height-2, 320, 1);
seperatorView = [[UIView alloc] initWithFrame:sepFrame];
seperatorView.backgroundColor = [UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f];
[headerView addSubview:seperatorView];
switch (section) {
case 0:
label.text = sectionTitle;
[headerView addSubview:label];
[headerView addSubview:button];
break;
case 1:
label.text = section2Title;
[headerView addSubview:label];
// if (completedArray == nil)
// headerView.hidden = YES;
break;
}
return headerView;
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
if([self isEditing]){
button.hidden = YES;
}else {
button.hidden = NO;
}
}
---EDIT----
-(void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
if([self isEditing]){
button.hidden = YES;
[[self tableView] reloadData]; //shouldn't this make the button dissapear?
}else {
button.hidden = NO;
}
}
Whenever the table view is reloaded your code will recreate the entire header, including creating a new button. So you may have set the old button to hidden and then it gets destroyed and replaced by a new, visible, button.
When returning the header, either create it once and always return the same instance, then changing the hidden property should work. Or, check if the table isEditing each time the header is created and decide what to do as a result.
Let's go with the more efficient header reuse option:
Create a property to hold the header view(s) - an array.
In viewDidLoad create the header views (using your current code, but moved to a different method).
Add the header views to the property (ensure you initialise the array first)
Change viewForHeaderInSection to just return the header from the array (based on section)
In setEditing: iterate through the array and hide/show each button
(You could store the buttons in another array to make that easy)
Related
I have made a simple subclass of UIView which has a few subviews but its breaking for a reason I can't see.
In my storyboard view controller I have added a UIView and made it the shape I want it, and added my custom class to it. The contents of my subclass is below:
#implementation PersonDetailCell
#synthesize button, requiredMarker, textField;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)layoutSubviews
{
[self setBackgroundColor:[UIColor colorWithRed:87.0f/255.0f green:153.0f/255.0f blue:191.0f/255.0f alpha:1.0f]];
textField = [[DetailTextField alloc] initWithFrame:CGRectMake(10, 0, self.frame.size.width -20, self.frame.size.height)];
[textField setFont:[UIFont fontWithName:#"Helvetica" size:14.0f]];
[textField setTextColor:[UIColor whiteColor]];
[textField setHidden:YES];
[self addSubview:textField];
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setHidden:YES];
[self addSubview:button];
requiredMarker = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 4, 22)];
[requiredMarker setBackgroundColor:[UIColor redColor]];
[requiredMarker setHidden:YES];
[self addSubview:requiredMarker];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
Then in my view controller code I have imported my subclass and hooked up an IBOutlet of it to my view in my storyboard. In my viewDidLoad of my view controller I also try setting background colour of this view but nothing happens.
All of my code runs without crashing, but my issues:
I can't set the background colour from my view controller, (or any other properties for that matter).
When I run the app, the height is more than that I set in my storyboard (width is fine), but I change the height of the view nowhere.
Any ideas? Am i using the wrong approach somehow?
Thanks.
If it is a table cell, then the class should be extending UITableViewCell. Buttons and textfields can be added on the storyboard - then you can use struts and springs (Size Inspector pane) to ensure the view resizes properly. I don't think layoutSubviews should be used for adding new UI elements (maybe for resizing if you need to do it manually).
Here is some working code:
#interface ChildView()
#property (strong, nonatomic) UITextField *textField;
#property (strong, nonatomic) UIButton *button;
#property (strong, nonatomic) UIImageView *requiredMarker;
#end
#implementation ChildView
#synthesize textField= _textField;
#synthesize button = _button;
#synthesize requiredMarker = _requiredMarker;
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self setBackgroundColor:[UIColor colorWithRed:87.0f/255.0f green:153.0f/255.0f blue:191.0f/255.0f alpha:1.0f]];
self.textField = [[UITextField alloc] init];
[self.textField setFont:[UIFont fontWithName:#"Helvetica" size:14.0f]];
[self.textField setTextColor:[UIColor whiteColor]];
self.textField.text = #"Test text";
[self addSubview:self.textField];
self.button = [[UIButton alloc] init];
self.button.backgroundColor = [UIColor greenColor];
[self addSubview:self.button];
self.requiredMarker = [[UIImageView alloc] init];
[self.requiredMarker setBackgroundColor:[UIColor redColor]];
[self addSubview:self.requiredMarker];
}
return self;
}
-(void)layoutSubviews
{
CGSize hostSize = self.frame.size;
float length = 22;
self.textField.frame = CGRectMake(10, length, hostSize.width, hostSize.height-length);
self.button.frame = CGRectMake(0, 0, hostSize.width, length);
self.requiredMarker.frame = CGRectMake(0, 0, 4, length);
}
#end
I haven't been able to figure out how to redisplay my changed text in my headerView in my UITableViewController. I do a "removeFromSuperview", and it does get removed, but then it doesn't redisplay the new headerView after I re-add it to my subView. Here is my code:
- (UIView *)headerView
{
if (headerView){
[headerView removeFromSuperview];
[headerView release];
}
UIButton *headerLabel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
if (displayOnly == NO)
[headerLabel setTitle:#"Click here to switch to display only mode." forState:UIControlStateNormal];
else
[headerLabel setTitle:#"Click here to switch to practice session mode." forState:UIControlStateNormal];
float w = [[UIScreen mainScreen] bounds].size.width;
CGRect headerLabelFrame = CGRectMake(8.0, 8.0, w - 16.0, 30.0);
[headerLabel setFrame:headerLabelFrame];
CGRect headerViewFrame = CGRectMake(0, 0, w, 48);
[headerLabel addTarget:self action:#selector(switch) forControlEvents:UIControlEventTouchUpInside];
headerView = [[UIView alloc] initWithFrame:headerViewFrame];
[headerView addSubview:headerLabel];
return headerView;
}
- (void) switch
{
if (displayOnly == YES)
{
displayOnly = NO;
[self headerView];
}
else
{
displayOnly = YES;
[self headerView];
}
}
Did you tried to call [headerView setNeedsDisplay]; after setting new title to label instead of recreating the view every time?
And may be you even don't need to do it at all. If you store UIButton and UIView, if I'm right it will redraw itself automatically when you put new title to it. Something like so:
in your .h file
UIButton* headerLabel;
UIView* headerView;
and in your .m file
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return [self headerView];
}
- (UIView *)headerView{
if(headerView){
return headerView;
}
if(!headerLabel){
headerLabel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
}
if (displayOnly == NO)
[headerLabel setTitle:#"Click here to switch to display only mode." forState:UIControlStateNormal];
else
[headerLabel setTitle:#"Click here to switch to practice session mode." forState:UIControlStateNormal];
float w = [[UIScreen mainScreen] bounds].size.width;
CGRect headerLabelFrame = CGRectMake(8.0, 8.0, w - 16.0, 30.0);
[headerLabel setFrame:headerLabelFrame];
CGRect headerViewFrame = CGRectMake(0, 0, w, 48);
[headerLabel addTarget:self action:#selector(switch) forControlEvents:UIControlEventTouchUpInside];
headerView = [[UIView alloc] initWithFrame:headerViewFrame];
[headerView addSubview:headerLabel];
return headerView;
}
- (void) switch{
if (displayOnly == YES){
displayOnly = NO;
[headerLabel setTitle:#"Click here to switch to display only mode." forState:UIControlStateNormal];
} else{
displayOnly = YES;
[headerLabel setTitle:#"Click here to switch to practice session mode." forState:UIControlStateNormal];
}
//may be there's need to make additional call
[headerView setNeedsDisplay];
}
This way you hold the same instance of UIView and UIButton only updating it's title and possibly manually calling to redraw by making [headerView setNeedsDisplay]; that call.
Did you try debugging your app? Where you are adding headerView in table? you need to change the code like this
- (void) switch
{
if (displayOnly == YES)
{
displayOnly = NO;
self.tableView.tableHeaderView = [self headerView];
}
else
{
displayOnly = YES;
self.tableView.tableHeaderView = [self headerView];
}
}
In this code:
if (headerView){
[headerView removeFromSuperview];
[headerView release];
}
you removing headerView from superview, but after creating new headerView not adding it to superview.
I think you need to call table reload data then it will work.
In my project i'm using a UITextField which is embedded into a plain white UIButton with rounded corners in order to create a "beautiful" text field. This code is used several times in different views so I decided to create a custom UIView for this purpose. The code for this custom UIView:
BSCustomTextField.h
#import <Foundation/Foundation.h>
#interface BSCustomTextField : UIView {
UIButton* btnTextFieldContainer;
UITextField* textField;
NSString* text;
}
#property (retain, nonatomic) UIButton* btnTextFieldContainer;
#property (retain, nonatomic) UITextField* textField;
#property (retain, nonatomic) NSString* text;
-(id)initWithPosition:(CGPoint)position;
#end
BSCustomTextField.m
#import "BSCustomTextField.h"
#import <QuartzCore/QuartzCore.h>
#implementation BSCustomTextField
#synthesize btnTextFieldContainer, textField, text;
-(id)initWithPosition:(CGPoint)position{
if (self == [super init]) {
btnTextFieldContainer = [[UIButton alloc] initWithFrame:CGRectMake(position.x, position.y, 260, 50)];
btnTextFieldContainer.backgroundColor = [UIColor whiteColor];
[[btnTextFieldContainer layer] setCornerRadius:3.];
[[btnTextFieldContainer layer] setMasksToBounds:YES];
[[btnTextFieldContainer layer] setBorderWidth:0.];
textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 240, 30)];
textField.backgroundColor = [UIColor whiteColor];
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.returnKeyType = UIReturnKeySend;
textField.keyboardType = UIKeyboardTypeEmailAddress;
textField.font = [UIFont fontWithName:#"Helvetica-Bold" size:20.];
[btnTextFieldContainer addSubview:textField];
[self addSubview:btnTextFieldContainer];
}
return self;
}
-(void)dealloc{
[btnTextFieldContainer release];
[textField release];
[super dealloc];
}
#end
So, when using this view in the viewDidLoad of the container view (see code below) the view is properly rendered on the desired position and looks exactly as specified but it does not react on touch events and thus does not become first responder when touched.
Code:
searchTextField = [[BSCustomTextField alloc] initWithPosition:CGPointMake(30, 150)];
searchTextField.textField.placeholder = NSLocalizedString(#"lsUserName", #"");
[[(BSPlainHeaderWithBackButtonView*)self.view contentView] addSubview:searchTextField];
Calling [searchTextField.textField becomeFirstResponder] programmatically works properly and makes the keyboard to appear.
But, the interesting part is, if I embed the code of BSCustomTextField inline in my container just like this:
UIButton* btnTextFieldContainer = [[UIButton alloc] initWithFrame:CGRectMake(30, 150, 260, 50)];
btnTextFieldContainer.backgroundColor = [UIColor whiteColor];
[[btnTextFieldContainer layer] setCornerRadius:3.];
[[btnTextFieldContainer layer] setMasksToBounds:YES];
[[btnTextFieldContainer layer] setBorderWidth:0.];
searchTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 240, 30)];
searchTextField.backgroundColor = [UIColor whiteColor];
searchTextField.clearButtonMode = UITextFieldViewModeAlways;
searchTextField.returnKeyType = UIReturnKeySend;
searchTextField.keyboardType = UIKeyboardTypeEmailAddress;
searchTextField.font = [UIFont fontWithName:#"Helvetica-Bold" size:20.];
searchTextField.placeholder = NSLocalizedString(#"lsUserName", #"");
[btnTextFieldContainer addSubview:searchTextField];
[[(BSPlainHeaderWithBackButtonView*)self.view contentView] addSubview:btnTextFieldContainer];
[btnTextFieldContainer release];
everything works as expected and the textfield reacts on touches. The type of the searchTextField is properly set in the header file for each case. The only difference is that in the first case I have an additional wrapping UIView on the UIButton and the UITextFiled. I have no idea what to do to make the text field to become first responder on touch.
Thanks a lot in advance,
Roman
Ok, I've got the solution. raaz's point to the UIResponder class tipped me off to the idea that there must be something wrong in the responder chain, thus I did a little research and found this topic: Allowing interaction with a UIView under another UIView in which exact the same problem is discussed.
Here is the new working code for BSCustomTextField.m
#import "BSCustomTextField.h"
#import <QuartzCore/QuartzCore.h>
#implementation BSCustomTextField
#synthesize btnTextFieldContainer, textField, text;
-(id)initWithPosition:(CGPoint)position{
if (self == [super init]) {
btnTextFieldContainer = [[UIButton alloc] initWithFrame:CGRectMake(position.x, position.y, 260, 50)];
btnTextFieldContainer.backgroundColor = [UIColor whiteColor];
[[btnTextFieldContainer layer] setCornerRadius:3.];
[[btnTextFieldContainer layer] setMasksToBounds:YES];
[[btnTextFieldContainer layer] setBorderWidth:0.];
textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 240, 30)];
textField.backgroundColor = [UIColor whiteColor];
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.returnKeyType = UIReturnKeySend;
textField.keyboardType = UIKeyboardTypeEmailAddress;
textField.font = [UIFont fontWithName:#"Helvetica-Bold" size:20.];
[btnTextFieldContainer addSubview:textField];
[self addSubview:btnTextFieldContainer];
}
return self;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// UIView will be "transparent" for touch events if we return NO
return YES;
}
-(void)dealloc{
[btnTextFieldContainer release];
[textField release];
[super dealloc];
}
#end
Since the clickable area fills out the entire BSCustomTextField view we can simply return YES in pointInside:withEvent:
Thank you all for pointing me into the right direction.
Refer UIResponder class
This class has instance method becomeFirstResponder: & isFirstResponder:
Also do not forget to set textfield editing property to YES
Oh, you're completely wrong with doing this way. You should add stretchable image into UIImageView and put it below UITextField.
UIImage *backgroundImage = [[UIImage imageNamed:#"fieldBackground.png"] stretchableImageWithLeftCapWidth:12.0 topCapHeight:0.0];
Or you can try to disable userInteraction in UIButton.
Okay, a short breif of my app before i explain the problem.
My app has two views for it's custom TableViewCell, one frontview, and one backview(which is revealed once you swipe your finger across the cell, much like the twitter-app).
Anywho, i wanted to have some buttons on the backview. I did this in the cellForRowAtIndexPath-method
The first you'll see here is how i assign labels to the cells. The secondary thing you'll see is the button. It's working fine.
UILabel *nextArtist = [UILabel alloc];
nextArtist.text = #"Rihanna";
nextArtist.tag = 4;
[cell setNextArtist:nextArtist];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(6 ,31, 110, 20);
[button setImage:[UIImage imageNamed:#"radionorge.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(touched:) forControlEvents:UIControlEventTouchUpInside];
[cell.backView addSubview:button];
But, it's in the next method the problem occours.
-(void)touched:(id)sender {
// Here i want to get the UILabels for each cell. Such as nextArtist.
if ([sender isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)sender;
UIView *contentView = button.superview;
UIView *viewWithTag4 = [contentView viewWithTag:4];
if ([viewWithTag1 isKindOfClass:[UILabel class]]) {
UILabel *titleLabel = (UILabel *)viewWithTag4;
NSLog(#"Label: ",titleLabel.text);
}
}
}
So, i realised that i cannot just go to the superview of the button and find my labels there, because their in another subview. I have scanned all my views, but still cannot find the label.
I am very new at this, and the subclassing of the TableView-cell is something i implemented from someone who posted their code.
But, my assumption is that there are noe UILabels in my view, because i am not adding them as views, only drawing them, with the drawTextInRect-function.
[nextArtist drawTextInRect:CGRectMake(boundsX+200 ,46, 110, 15)];
I have tried to adding them as subviews, but with no luck. Could anyone help me?
// Some more code you may need to solve the puzzle(this is where the cell-views are made)
#implementation RadioTableCellView
- (void)drawRect:(CGRect)rect {
if (!self.hidden){
[(RadioTableCell *)[self superview] drawContentView:rect];
}
else
{
[super drawRect:rect];
}
}
#end
#implementation RadioTableCellBackView
- (void)drawRect:(CGRect)rect {
if (!self.hidden){
[(RadioTableCell *)[self superview] drawBackView:rect];
}
else
{
[super drawRect:rect];
}
}
#end
#interface RadioTableCell (Private)
- (CAAnimationGroup *)bounceAnimationWithHideDuration:(CGFloat)hideDuration initialXOrigin:(CGFloat)originalX;
#end
#implementation RadioTableCell
#synthesize contentView;
#synthesize backView;
#synthesize contentViewMoving;
#synthesize selected;
#synthesize shouldSupportSwiping;
#synthesize shouldBounce;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
[self setBackgroundColor:[UIColor clearColor]];
RadioTableCellView * aView = [[RadioTableCellView alloc] initWithFrame:CGRectZero];
[aView setClipsToBounds:YES];
[aView setOpaque:YES];
[aView setBackgroundColor:[UIColor clearColor]];
[self setContentView:aView];
[aView release];
RadioTableCellBackView * anotherView = [[RadioTableCellBackView alloc] initWithFrame:CGRectZero];
[anotherView setOpaque:YES];
[anotherView setClipsToBounds:YES];
[anotherView setHidden:YES];
[anotherView setBackgroundColor:[UIColor clearColor]];
[self setBackView:anotherView];
[anotherView release];
// Backview must be added first!
// DO NOT USE sendSubviewToBack:
[self addSubview:backView];
[self addSubview:contentView];
[self setContentViewMoving:NO];
[self setSelected:NO];
[self setShouldSupportSwiping:YES];
[self setShouldBounce:YES];
[self hideBackView];
}
return self;
}
Please help me, or at least point me in a direction or two!
//////////////////////////
Updated with some new code:
This is inside my RadioCustomCell, a UIView-subclass. It's here the UILabels are drawn
#import "RadioCustomCell.h"
#implementation RadioCustomCell
#synthesize nowTitle,nowArtist,nextTitle,nextArtist,ChannelImage;
// Setting the variables
- (void)setNowTitle:(UILabel *)aLabel {
if (aLabel != nowTitle){
[nowTitle release];
nowTitle = [aLabel retain];
[self setNeedsDisplay];
}
}
- (void)setNowArtist:(UILabel *)aLabel {
if (aLabel != nowArtist){
[nowArtist release];
nowArtist = [aLabel retain];
[self setNeedsDisplay];
}
}
- (void)setNextTitle:(UILabel *)aLabel {
if (aLabel != nextTitle){
[nextTitle release];
nextTitle = [aLabel retain];
[self setNeedsDisplay];
}
}
- (void)setNextArtist:(UILabel *)aLabel {
if (aLabel != nextArtist){
[nextArtist release];
nextArtist = [aLabel retain];
[self setNeedsDisplay];
}
}
- (void)setChannelImage:(UIImage *)aImage {
if (aImage != ChannelImage){
[ChannelImage release];
ChannelImage = [aImage retain];
[self setNeedsDisplay];
}
}
- (void)drawContentView:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//UIColor * backgroundColour = [UIColor whiteColor];
UIColor *backgroundColour = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"CellBackground.png"]];
[backgroundColour set];
CGContextFillRect(context, rect);
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
[ChannelImage drawInRect:CGRectMake(boundsX+120 ,25, 75, 35)];
nowTitle.enabled = YES;
nowTitle.textAlignment = UITextAlignmentCenter;
nowTitle.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size: 14.0];
nowTitle.textColor = [UIColor blackColor];
nowTitle.backgroundColor = [UIColor clearColor];
//[nowTitle drawTextInRect:CGRectMake(boundsX+6 ,31, 110, 20)];
// Trying to add a subview instead of drawing the text
nowTitle.frame = CGRectMake(boundsX+6 ,31, 110, 20);
[self addSubview:nowTitle];
// I have also tried adding it to super, no effect.
nowArtist.enabled = YES;
nowArtist.textAlignment = UITextAlignmentCenter;
nowArtist.font = [UIFont fontWithName:#"HelveticaNeue" size: 10.0];
nowArtist.textColor = [UIColor blackColor];
nowArtist.backgroundColor = [UIColor clearColor];
[nowArtist drawTextInRect:CGRectMake(boundsX+6 ,46, 110, 15)];
nextTitle.enabled = NO;
nextTitle.textAlignment = UITextAlignmentCenter;
nextTitle.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size: 12.0];
[nextTitle drawTextInRect:CGRectMake(boundsX+200 ,31, 110, 20)];
nextArtist.enabled = NO;
nextArtist.textAlignment = UITextAlignmentCenter;
nextArtist.font = [UIFont fontWithName:#"HelveticaNeue" size: 9.0];
[nextArtist drawTextInRect:CGRectMake(boundsX+200 ,46, 110, 15)];
}
You just forgot to init your UILabel in your very first line of code. :)
At the first look, I can be sure that if you draw the text (and the text is not the label), then there is no UILabel at all in your cell. You can ignore that way.
So, if you don't have the UILabel, how you can get the text. Because your contentView is indeed a RadioTableCellView, then it is not hard. In your class, just public a property called nextArtist. When your button is tapped, look up for the contentView (by calling some superview), cast it to RadioTableCellView then get the nextArtist out
Without writing a bunch of code, here's my best guess.
You're going to need to assign tags to aView and anotherView in your initWithStyle: method. I'm going to assume you have a couple constants: BACK_VIEW_TAG and FRONT_VIEW_TAG.
In your touched: method, walk up the view hierarchy until you find your UITableViewCell.
UIView *currentView = button.superView;
while (![currentView isKindOfClass:UITableViewCell] && currentView != nil) {
currentView = currentView.parent;
}
Get the front view and back view (or which ever you want) from the table cell's contentView using the tags.
if (currentView != nil) {
UITableViewCell *cellView = (UITableViewCell *)currentView)
UIView *cellContentView = cellView.contentView;
UIView *backView = [cellContentView viewWithTag:BACK_VIEW_TAG];
UIView *frontView = [cellContentView viewWithTag:FRONT_VIEW_TAG];
// Get other views from frontView and backView using viewWithTag:.
}
Note that you should be adding views to your UITableViewCell subclass's contentView, not to the UITableViewCell directly. See Programmatically Adding Subviews to a Cell’s Content View for details.
I created a custom UITableViewCell class with a UIButton, a UIImage, and two UILabels. The button and the image are overlayed on top of each other, and only one is displayed at a time. The expected behavior is you touch on the button, the button disappears, and it displays the image. The UITableViewCells are set to be reused. Here's my code:
Constructor:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
unheartButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
unheartButton.backgroundColor = [UIColor clearColor];
unheartButton.frame = CGRectMake(10, 13, 20, 18);
[unheartButton addTarget:self action:#selector(onButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[unheartButton setBackgroundImage:[UIImage imageNamed:#"redheart.png"] forState:UIControlStateNormal];
imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(12, 13, 16, 16);
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int ndx = 1; ndx < 13; ndx++) {
[array addObject:[UIImage imageNamed:[NSString stringWithFormat:#"icon-loading-%d (dragged).tiff", ndx]]];
}
imageView.animationImages = array;
imageView.animationDuration = 1;
[array release];
[self.contentView addSubview:imageView];
[self.contentView addSubview:unheartButton];
return self;
}
}
- (void) setModel:(MyModel *)myModel {
model = myModel;
if (model.hideImage) {
imageView.hidden = YES;
unheartButton.hidden = NO;
else {
imageView.hidden = NO;
unheartButton.hidden = YES;
}
}
Button click:
- (IBAction) onButtonClick: (id) sender {
model.hideImage = NO;
unheartButton.hidden = YES;
imageView.hidden = NO;
[imageView startAnimating];
[self setNeedsDisplay];
[self.contentView setNeedsDisplay];
[self.unheartButton setNeedsDisplay];
[self.imageView setNeedsDisplay];
}
I'm calling setNeedsDisplay on everything, but nothing seems to happen. If I scroll off the screen and back up, the button is hidden and now the loading icon is shown, but this only happens after a scroll. I'm not sure what I need to do to get the cell to repaint.
The UITableView does some fancy caching to support scrolling and the like; I've had similar issues with refreshing a specific cell when I use custom views.
You can use reloadRowsAtIndexPaths:withRowAnimation: to make the table reload just that row. See this post for more information: Why won't my UITableViewCell deselect and update its text?