Custom UITableViewCell Not Highlighting Text - iphone

I setup a custom UITableViewCell and am subclassing it from UITableViewCell.
I am using it in my table and everything works except when I select the cell, it highlights the default blue but the text is gone. Once I diselect the text is back. Does anyone know how to fix it?
This is the custom cell code I am using
#import "TableViewCell.h"
#implementation TableViewCell
#synthesize text;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
}
return self;
}
- (void)setText:(NSString *)string {
text = [string copy];
[self setNeedsDisplay];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
- (void)drawRect:(CGRect)rect {
CGContextRef c = UIGraphicsGetCurrentContext();
CGGradientRef myGradient;
CGColorSpaceRef myColorspace;
size_t num_locations = 2;
CGFloat locations[2] = {0.0, 1.0};
CGFloat components[8] = {0.8f, 0.8f, 0.8f, 1.0f, // Bottom Colour: Red, Green, Blue, Alpha.
0.9f, 0.9f, 0.9f, 1.0}; // Top Colour: Red, Green, Blue, Alpha.
myColorspace = CGColorSpaceCreateDeviceRGB();
myGradient = CGGradientCreateWithColorComponents (myColorspace, components,
locations, num_locations);
CGColorSpaceRelease(myColorspace);
CGPoint startPoint, endPoint;
startPoint.x = 0.0;
startPoint.y = self.frame.size.height;
endPoint.x = 0.0;
endPoint.y = 0.0;
CGContextDrawLinearGradient (c, myGradient, startPoint, endPoint, 0);
const CGFloat topSepColor[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // Cell Seperator Colour - Top
CGGradientRelease(myGradient);
CGContextSetStrokeColor(c, topSepColor);
CGContextMoveToPoint(c, 0.0, 0.0);
CGContextSetLineWidth(c, 1.0);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextAddLineToPoint(c, self.frame.size.width, 0.0);
CGContextStrokePath(c);
const CGFloat bottomSepColor[] = { 0.5f, 0.5f, 0.5f, 1.0f }; // Cell Seperator Colour - Bottom
CGContextSetStrokeColor(c, bottomSepColor);
CGContextMoveToPoint(c, 0.0, self.frame.size.height);
CGContextSetLineWidth(c, 1.0);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextAddLineToPoint(c, self.frame.size.width, self.frame.size.height);
CGContextStrokePath(c);
[[UIColor blackColor] set];
[text drawInRect:CGRectMake(10, self.frame.size.height / 3.5, self.frame.size.width - 20, self.frame.size.height - 10) withFont:[UIFont boldSystemFontOfSize:15] lineBreakMode:UILineBreakModeWordWrap];
}
- (void)dealloc {
[super dealloc];
[text release];
}
#end

Apple advises againts overriding UITableViewCell's -drawRect. If you really want to do custom drawing, do it in UIView subclass and then add the instance of that class as UITableViewCell's content view. Also Apple encourages using UIImageView as cell's background view instead of custom-drawn UIView subclasses (where possible, of course). That applies not only to cell's background view. As far as I see it, it's possible to use UIImageView in your case since drawing code in -drawRect is not parametrized in any way, that is, doesn't have external dependencies.
May be you should take a look at that: http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
But if you don't want to take another approach, there's a highlightedTextColor property of UILabel

See: UITableViewCell: How to prevent blue selection background w/o borking isSelected property?

Check your settings for UITableViewCellStyle, and UITableViewCellSelectionStyle. They're explained in the UITableViewCell Class Reference. The default selection style has a blue background which may be "masking" your text while in that state.

Related

How to change color of the UIAlertView dialog in iOS?

I have an application where I am showing an alert message using UIAlertView. By default the color of the dialog box is blue. Can anyone tell me, how to change the color of that? Can it be changed?
Use Like This
[CustomAlert setBackgroundColor:[UIColor blueColor]
withStrokeColor:[UIColor greenColor]];
.h and .m File's Content
CustomAlert.h
#import <UIKit/UIKit.h>
#interface CustomAlert : UIAlertView
{
}
+ (void) setBackgroundColor:(UIColor *) background
withStrokeColor:(UIColor *) stroke;
#end
CustomAlert.m
#import "CustomAlert.h"
#interface CustomAlert (Private)
- (void) drawRoundedRect:(CGRect) rect inContext:(CGContextRef)
context withRadius:(CGFloat) radius;
#end
static UIColor *fillColor = nil;
static UIColor *borderColor = nil;
#implementation CustomAlert
+ (void) setBackgroundColor:(UIColor *) background
withStrokeColor:(UIColor *) stroke
{
if(fillColor != nil)
{
[fillColor release];
[borderColor release];
}
fillColor = [background retain];
borderColor = [stroke retain];
}
- (id)initWithFrame:(CGRect)frame
{
if((self = [super initWithFrame:frame]))
{
if(fillColor == nil)
{
fillColor = [[UIColor blackColor] retain];
borderColor = [[UIColor colorWithHue:0.625
saturation:0.0 brightness:0.8 alpha:0.8]
retain];
}
}
return self;
}
- (void)layoutSubviews
{
for (UIView *sub in [self subviews])
{
if([sub class] == [UIImageView class] && sub.tag == 0)
{
// The alert background UIImageView tag is 0,
// if you are adding your own UIImageView's
// make sure your tags != 0 or this fix
// will remove your UIImageView's as well!
[sub removeFromSuperview];
break;
}
}
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetAllowsAntialiasing(context, true);
CGContextSetLineWidth(context, 0.0);
CGContextSetAlpha(context, 0.8);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [borderColor CGColor]);
CGContextSetFillColorWithColor(context, [fillColor CGColor]);
// Draw background
CGFloat backOffset = 2;
CGRect backRect = CGRectMake(rect.origin.x + backOffset,
rect.origin.y + backOffset,
rect.size.width - backOffset*2,
rect.size.height - backOffset*2);
[self drawRoundedRect:backRect inContext:context withRadius:8];
CGContextDrawPath(context, kCGPathFillStroke);
// Clip Context
CGRect clipRect = CGRectMake(backRect.origin.x + backOffset-1,
backRect.origin.y + backOffset-1,
backRect.size.width - (backOffset-1)*2,
backRect.size.height - (backOffset-1)*2);
[self drawRoundedRect:clipRect inContext:context withRadius:8];
CGContextClip (context);
//Draw highlight
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35, 1.0, 1.0, 1.0, 0.06 };
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace,
components, locations, num_locations);
CGRect ovalRect = CGRectMake(-130, -115, (rect.size.width*2),
rect.size.width/2);
CGPoint start = CGPointMake(rect.origin.x, rect.origin.y);
CGPoint end = CGPointMake(rect.origin.x, rect.size.height/5);
CGContextSetAlpha(context, 1.0);
CGContextAddEllipseInRect(context, ovalRect);
CGContextClip (context);
CGContextDrawLinearGradient(context, glossGradient, start, end, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
- (void) drawRoundedRect:(CGRect) rrect inContext:(CGContextRef) context
withRadius:(CGFloat) radius
{
CGContextBeginPath (context);
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect),
maxx = CGRectGetMaxX(rrect);
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect),
maxy = CGRectGetMaxY(rrect);
CGContextMoveToPoint(context, minx, midy);
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
CGContextClosePath(context);
}
- (void)dealloc
{
[super dealloc];
}
#end
From the UIAlertView Class Reference:
The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.
You have to implement your UIAlertView. You can't change the default blue color.
use a uiview to show alert instead of using UIAlertView then change the color of that view accordingly

UIView's drawRect is not getting called

I am trying to display horizontal and/or vertical lines in a grid. So I created a UIView subclass GridLines that draws lines in drawRect:. I then create two of these (one vertical, one not), and add them as subviews to my primary view (Canvas) also UIView derived. The other custom subviews I add to Canvas are displayed, removed, etc. properly, but the GridLines objects are not, and their drawRect:s never get called. When I had this line-drawing code in [Canvas drawRect:] (which is now disabled), it displayed the grid properly.
Looking through similar questions, it seems most people with this issue are calling drawRect in a non-UIView derived class, but mine is a UIView.
Am I missing something here?
GridLines.h:
#import <UIKit/UIKit.h>
#interface GridLines : UIView
{
BOOL mVertical;
}
- (id) initWithFrame: (CGRect) _frame vertical: (BOOL) _vertical;
#end
GridLines.m:
#import "GridLines.h"
#implementation GridLines
- (id) initWithFrame: (CGRect) _frame vertical: (BOOL) _vertical
{
if ((self = [super initWithFrame: _frame]))
{
mVertical = _vertical;
}
return self;
}
- (void) drawRect: (CGRect) _rect
{
NSLog(#"[GridLines drawRect]");
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor clearColor] set];
UIRectFill([self bounds]);
if (mVertical)
{
for (int i = 50; i < self.frame.size.width; i += 50)
{
CGContextBeginPath(context);
CGContextMoveToPoint(context, (CGFloat)i, 0.0);
CGContextAddLineToPoint(context, (CGFloat)i, self.frame.size.height);
[[UIColor grayColor] setStroke];
CGContextSetLineWidth(context, 1.0);
CGContextDrawPath(context, kCGPathFillStroke);
}
}
else
{
for (int j = 50; j < self.frame.size.height; j += 50)
{
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0.0, (CGFloat)j);
CGContextAddLineToPoint(context, self.frame.size.width, (CGFloat)j);
[[UIColor grayColor] setStroke];
CGContextSetLineWidth(context, 1.0);
CGContextDrawPath(context, kCGPathFillStroke);
}
}
}
#end
In another UIView derived class:
- (void) createGrids
{
mHorizontalLines = [[GridLines alloc] initWithFrame: self.frame vertical: NO];
mVerticalLines = [[GridLines alloc] initWithFrame: self.frame vertical: YES];
[self addSubview: mHorizontalLines];
[self addSubview: mVerticalLines];
}
You may have a frame v bounds problem.
mHorizontalLines = [[GridLines alloc] initWithFrame: self.frame vertical: NO];
mVerticalLines = [[GridLines alloc] initWithFrame: self.frame vertical: YES];
frame is kept in superview's co-ordinate space, if self.frame is offset more that it is wide, when you set these new views to that frame, they'll be clipped to rect of self.
try changing this to self.bounds, which should have origin = {0,0}

UITableView headers - iPhone

In my iPhone app, I'd like to alter the headers on my UITableView. How can I keep the same gradient/alpha/nice looking style of the gray, default headers, except change the color of it?
If you want to apply a gradient then you could create a custom view class and then override drawRect: and use CoreGraphics to draw a gradient
e.g.
- (void) drawRect:(CGRect)rect
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1 };
const CGFloat *startColorComponents = CGColorGetComponents(startColor.CGColor);
const CGFloat *endColorComponents = CGColorGetComponents(endColor.CGColor);
CGFloat components[8] = { startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3], // Start color
endColorComponents[0], endColorComponents[1], endColorComponents[2], endColorComponents[3] }; // End color
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint bottomCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, bottomCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
Then do as per Sachin's suggestion but use your custom view class instead.
you can use this
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectZero];
headerView.backgroundColor = [UIColor lightGrayColor];
return headerView;
}

Quartz 2d trying to redraw a triangle

I'm developing an iPhone app.
I have the following class:
#import "Triangulo.h"
#implementation Triangulo
#synthesize minusValue;
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
CGSize size = rect.size;
CGPoint origin = {10.0f, size.height - 10.0f};
[self drawLineAtOrigin:origin withLength:size.width - 10.0f];
CGPoint origin2 = {10.0f, size.height - 20.0f};
CGSize size2 = {size.width - minusValue, 20.0f};
[self drawTriangleAtOrigin:origin2 withSize: size2 inRect: rect];
}
- (void)drawLineAtOrigin:(CGPoint)origin withLength:(float)length {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextMoveToPoint(context, origin.x, origin.y);
CGContextAddLineToPoint(context, length, origin.y);
CGContextStrokePath(context);
}
- (void)drawTriangleAtOrigin:(CGPoint)origin withSize:(CGSize)size inRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(UIGraphicsGetCurrentContext(), rect);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextMoveToPoint(context, origin.x, origin.y);
CGContextAddLineToPoint(context, size.width, origin.y);
CGContextAddLineToPoint(context, size.width, origin.y - size.height);
CGContextAddLineToPoint(context, origin.x, origin.y);
CGContextFillPath(context);
CGContextStrokePath(context);
}
- (void)dealloc {
[super dealloc];
}
#end
This UIView is part of UIViewController.view. I've add in UIViewController.h as:
IBOutlet Triangulo *triangulo;
...
#property (nonatomic, retain) IBOutlet Triangulo *triangulo;
On UIViewController I have a button to modify Triangulo:
- (IBAction)btnDrawTriangleClicked:(id)sender {
triangulo.minusValue += 10.0f;
CGRect rect = CGRectMake(0, 0, 280, 50);
[triangulo drawRect: rect];
}
But I can't draw anything because UIGraphicsGetCurrentContext is always nil.
Any advice?
Add this code to your Triangulo class:
- (void)setMinusValue:(double)aMinusValue {
minusValue = aMinusValue;
[self setNeedsDisplay];
}
And then the btnDrawTriangleClicked: method to the following:
- (IBAction)btnDrawTriangleClicked:(id)sender {
triangulo.minusValue += 10.0f;
}
Now when you alter the minusValue, Triangulo automatically flags itself as needing redisplay. (See The View Drawing Cycle for more info). As Deepak stated, you never call drawRect: yourself (unless you're within the drawRect: method itself, and you're calling [super drawRect:frame];). The drawRect: method is called automatically by the system, and it always makes sure that a valid CGGraphicsContext is set up beforehand. Since you were calling it directly, that preparation work wasn't being done, so UIGraphicsGetCurrentContext() usually returned NULL.
You should never call drawRect: directly. You should call either setNeedsDisplay or setNeedsDisplayInRect: whenever you want to redraw the view. rect that is passed to drawRect: is not a random value that is passed. It tells you the portion of the view's bounds that need to be redrawn.

How to change the color of first letter of a textfields text

I have a textfield and starting letter of textfield's text is always a dollar sign.Now i need to change the color of dollar symbol so that dollar symbol and remaining text should be in different color. How can i do this?? Any idea
Can't be done standard. Only one style is allowed in a UITextField.
Best idea: get rid of the $ in the UITextField, replace it with whitespace, then place a UILabel on top.
2nd best idea: subclass UITextField.
Edit:
UITextField has a drawTextInRect: method which is probably all you need to override.
Documented here. If you need more help, try googling or searching SO for how to subclass different UI classes, and get a feel for how to override draw methods (e.g. drawRect: for UIView)
Here's the #implementation of my LinethruLabel, a subclass of UILabel. It indicates a "scratched" item with a red linedrawn thru the text. In my case I call [super drawRect:rect]; and UILabel draws the text and background etc., but I'm not sure if whether you'll want to, so take it out if it's not working the way you want. So I guess you'll need to use some of the variations of drawAtPoint:withFont: methods from NSString UIKit category.
#implementation LineThruUILabel
- (void)dealloc {
[super dealloc];
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
drawLine = NO;
}
return self;
}
- (void) setDrawLine:(BOOL) newValue
{
if( drawLine != newValue ){
drawLine = newValue;
[self setNeedsDisplay];
}
}
- (CGSize) calculateLineWidth
{
NSString *newText = self.text;
CGFloat actualFontSize;
CGFloat width = self.frame.size.width;
CGSize size = [newText sizeWithFont: self.font minFontSize:self.minimumFontSize
actualFontSize:&actualFontSize
forWidth:width
lineBreakMode:self.lineBreakMode ];
return size;
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGFloat horizOffset = 0.0;
if( drawLine ){
CGSize lineSize = [self calculateLineWidth];
CGFloat offset = 1.0;
// Drawing code
CGContextRef ctx = UIGraphicsGetCurrentContext();
//CGFloat w = rect.size.width;
CGFloat h = rect.size.height;
// just match the color and size of the horizontal line
CGContextSetRGBStrokeColor(ctx, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(ctx, 2.0);
CGContextMoveToPoint(ctx, horizOffset , h/2 + offset );
CGContextAddLineToPoint(ctx, lineSize.width + horizOffset + 1.0, h/2 + offset);
CGContextStrokePath(ctx);
}
}