How to achieve below effect??
I want that when my UIImage width is smaller then UILabel width then my image should be displayed only once as below.
I already have done some more work with UILabel and UIImage. Refer to my previous question : How to stretch Image to fill the Label Width set in Background in UILabel?.
But now i want some more fun with UILabel... :D
EDIT :
SBLabel *lbl = [[SBLabel alloc] initWithFrame:CGRectMake(0, 50, 320, 28)];
lbl.text = #"Hello World!!!...";
UIImage *img = [UIImage imageNamed:#"cn3.png"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 50, 320, 28)];
imgView.image = img;
[lbl setNonRepeatingBackgroundImage:imgView];
[self.view addSubview:lbl];
[imgView release];
if (image.size.width < label.size.width ||image.size.height < label.size.height )
{
//rect here is frame of image
[img drawInRect:rect];
label.backgroudColor = [UIColor clearColor];
}
It seems like the most straightforward solution would be to have your UIImage sit behind your UILabel and your UILabel has a transparent background color.
Edit
Assuming you're using ARC...
SBLabel.h
#import <UIKit/UIKit.h>
#interface SBLabel : UILabel
#property (nonatomic, strong) UIImageView *nonRepeatingBackgroundImage;
#end
SBLabel.m
#import "SBLabel.h"
#implementation SBLabel
#synthesize nonRepeatingBackgroundImage;
- (void)setNonRepeatingBackgroundImage:(UIImageView *)aNonRepeatingBackgroundImage {
nonRepeatingBackgroundImage = aNonRepeatingBackgroundImage;
[self addSubview:aNonRepeatingBackgroundImage];
[self sendSubviewToBack:aNonRepeatingBackgroundImage];
[self setBackgroundColor:[UIColor clearColor]];
}
#end
You would need to call this setter method after you add the UILabel to the parent view. I have not tested but I believe it should work, might require some tweaks but hopefully it explains how to Subclass UILabel to make a custom enhancement such as this.
A subclass of UILabel could look like this (without ARC)
CustomLabel.h
#import <UIKit/UIKit.h>
#interface CustomLabel : UILabel {
UIImage *mImage;
}
#property (retain) UIImage *image;
#end
CustomLabel.m
#import "CustomLabel.h"
#implementation CustomLabel
- (void)dealloc {
self.image = nil;
[super dealloc];
}
- (void)drawRect:(CGRect)rect {
[mImage drawAtPoint:CGPointMake(0, 0)];
[super drawRect:rect];
}
- (UIImage*)image {
return mImage;
}
- (void)setImage:(UIImage *)image {
self.backgroundColor = [UIColor clearColor];
if(mImage)
[mImage release];
mImage = [image retain];
[self setNeedsDisplay];
}
#end
Usage
yourCustomLabel.image = [UIImage imageNamed:#"test.png"];
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 am trying to change the background color and make an image appear on the screen when a button is pushed. I can get the color to change, but I can't get a trace of the image to appear. I don't know how to place the image on the screen either. I am using iOS 5 and storyboard, but I have not added the UIImageView to the storyboard, as I want it to appear.
My ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)changeButton:(id)sender;
#end
My ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)colorchange
{
self.view.backgroundColor = [UIColor greenColor];
}
-(void)imageShow
{
UIImage *image = [UIImage imageNamed:#"logo-tag-centered.pmg"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[imgView setImage:image];
}
- (IBAction)changeButton:(id)sender
{
[self colorchange];
[self imageShow];
}
#end
Any help would be greatly appreciated! Thanks!
You have to add the image view to your view controller's view.
- (void)showImage
{
UIImage *image = [UIImage imageNamed:#"logo-tag-centered.png"];
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.center = CGPointMake(self.view.bounds.size.width / 2.0f, self.view.bounds.size.height / 2.0f);
[self.view addSubview:imgView];
}
You haven't added the image view anywhere to the main view. You could do this:
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"logo-tag-centered.pmg"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[imgView setImage:image];
[imgView setHidden:YES];
[self.view addSubview:imgView];
}
-(void)imageShow
{
[imgView setHidden:NO];
}
- (IBAction)changeButton:(id)sender
{
[self colorchange];
[self imageShow];
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i have a problem. I have this code a zoom doesn't work.
- (void)viewDidLoad
{
UIImage *image = [UIImage imageNamed:#"zoomimage.jpeg"];
CGRect yFrame = CGRectMake(0.0, 0.0, 320, 432);
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, image.size.width, image.size.height)];
[imageView setImage:image];
scrollView = [[UIScrollView alloc] initWithFrame:yFrame];
[scrollView setScrollEnabled:YES];
[scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setContentSize:CGSizeMake(image.size.width, image.size.height)];
scrollView.minimumZoomScale = 0.4;
scrollView.maximumZoomScale = 4.0;
[scrollView setZoomScale:scrollView.minimumZoomScale];
[self.view addSubview:scrollView];
[self.view bringSubviewToFront:scrollView];
[scrollView addSubview:imageView];
}
First, set the delegate of scrollview to your self.
scrollView.delegate = self;
Now, Add this delegate method of UIScrollView in your class to enable zooming on the image.
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}
Try this:
.h Controller:
#interface MyViewController : UIViewController{
IBOutlet UIScrollView *scrollView;
UIImageView *imageView;
}
#property (nonatomic, retain) UIScrollView *scrollView;
#property (nonatomic, retain) UIImageView *imageView;
.m Controller:
#synthesize scrollView, imageView;
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return imageView;
}
- (void)viewDidLoad
{
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"YourImageName.png"]];
self.imageView = tempImageView;
[tempImageView release];
scrollView.maximumZoomScale = 3.0;
scrollView.minimumZoomScale = 0.6;
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
}
This code worked for me :)
I tried to subclass UIButton to include an activity indicator, but when i use initWithFrame:(since i'm subclassing uibutton i'm not using buttonWithType:) the button doesn't display. Also how would i set the button type in this case?:
my view controller:
ActivityIndicatorButton *button = [[ActivityIndicatorButton alloc] initWithFrame:CGRectMake(10, 10, 300, 44)];
[button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Older Posts..." forState: UIControlStateNormal];
[cell addSubview:button];
[button release];
my activityindicatorbutton class:
#import <Foundation/Foundation.h>
#interface ActivityIndicatorButton : UIButton {
UIActivityIndicatorView *_activityView;
}
-(void)startAnimating;
-(void)stopAnimating;
#end
#implementation ActivityIndicatorButton
- (id)initWithFrame:(CGRect)frame {
if (self=[super initWithFrame:frame]) {
_activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_activityView.frame = CGRectOffset(_activityView.frame, 60.0f, 10.0f);
[self addSubview: _activityView];
}
return self;
}
-(void) dealloc{
[super dealloc];
[_activityView release];
_activityView = nil;
}
-(void)startAnimating {
[_activityView startAnimating];
}
-(void)stopAnimating {
[_activityView stopAnimating];
}
#end
Favour composition over inheritance.
Create a UIView which contains the components you need and add them to your view.
I ran into a similar situation, and agree with Jeff that you don't really need to subclass UIButton. I solved this by subclassing UIControl, and then overriding layoutSubviews to do all of the configuration of the views I wanted on my "button". It's a much more simple implementation that subclassing UIButton since there does seem to be some hidden mojo going on under the hood. My implementation looked like this:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.opaque = YES;
self.imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
[self addSubview:self.imageView];
self.textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self addSubview:self.textLabel];
}
return self;
}
And layoutSubviews looked like this:
- (void)layoutSubviews {
[super layoutSubviews];
// Get the size of the button
CGRect bounds = self.bounds;
// Configure the subviews of the "button"
...
}
I have created a custom class, preferring composition over inheritance and it works perfect. My custom class has a button and it knows it's MCContact object. Also it draws a proper button and calculates frames automatically using MCContact object, that is passed.
Header file sample:
#import <UIKit/UIKit.h>
#protocol MCContactViewDelegate;
#interface MCContactView : UIView
{
}
#property (nonatomic, strong) MCContact *mcContact;
#property (nonatomic, weak) id <MCContactViewDelegate> delegate;
- (id)initWithContact:(MCContact*)mcContact delegate:(id <MCContactViewDelegate>)delegate;
#end
#protocol MCContactViewDelegate <NSObject>
- (void)contactViewButtonClicked:(MCContactView*)contactView;
#end
Implementation file:
#import "MCContactView.h"
#interface MCContactView()
{
UIButton *_button;
}
#end
#implementation MCContactView
- (id)initWithContact:(MCContact*)mcContact delegate:(id <MCContactViewDelegate>)delegate
{
self = [super initWithFrame:CGRectZero];
if (self) {
GetTheme();
_mcContact = mcContact;
_delegate = delegate;
_button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *normalBackgroundImage = [[UIImage imageNamed:#"tokenNormal.png"] stretchableImageWithLeftCapWidth:12.5 topCapHeight:12.5];
[_button setBackgroundImage:normalBackgroundImage forState:UIControlStateNormal];
UIImage *highlightedBackgroundImage = [[UIImage imageNamed:#"tokenHighlighted.png"] stretchableImageWithLeftCapWidth:12.5 topCapHeight:12.5];
[_button setBackgroundImage:highlightedBackgroundImage forState:UIControlStateHighlighted];
_button.titleLabel.font = [theme contactButtonFont];
[_button setTitleColor:[theme contactButtonTextColor] forState:UIControlStateNormal];
[_button setTitleEdgeInsets:UIEdgeInsetsMake(4, 6, 4, 6)];
NSString *tokenString = ([allTrim(mcContact.name) length]>0) ? mcContact.name : mcContact.eMail;
[_button setTitle:tokenString forState:UIControlStateNormal];
[_button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
CGSize size = [tokenString sizeWithFont:[theme contactButtonFont]];
size.width += 20;
if (size.width > 200) {
size.width = 200;
}
size.height = normalBackgroundImage.size.height;
[_button setFrame:CGRectMake(0, 0, size.width, size.height)];
self.frame = _button.frame;
[self addSubview:_button];
}
return self;
}
- (void)buttonClicked:(id)sender
{
[self.delegate contactViewButtonClicked:self];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
You have a pretty obvious problem that concerns your dealloc method: [super dealloc]; must be called AT THE END of your implementation, or else the line after that will try to access a memory space (the ivar space) that has been already deallocated, so it's going to crash.
For the other problem, I'm not sure it's a good idea to put an activity monitor as the subview of a button in general...
You don’t really want to subclass UIButton. It’s a class cluster, so individual instances will be something like UIRoundRectButton or some other private Apple class. What are you trying to do that requires a subclass?
Given the multitasking of iOS I thought it wouldn't be a pain to pause and resume my app, by pressing the home button or due to a phone call, but for a particular view controller it crashes.
The navigation bar is working fine i.e. when I tap "Back" it's ok, but if I try to tap controls of the displayed UI View Controller then I get EXC_BAD_ACCESS.. =/
Please find the code of my problematic View Controller below. I'm not very sure about it myself, because I used loadView to build its View. However apart from this interruption problem it works fine.
StoreViewController.h
#import <UIKit/UIKit.h>
#protocol StoreViewDelegate <NSObject>
#optional
- (void)DirectionsClicked:(double)lat:(double)lon;
#end
#interface StoreViewController : UIViewController
{
double latitude;
double longitude;
NSString *description;
NSString *imageURL;
short rating;
NSString *storeType;
NSString *offerType;
UIImageView *imageView;
UILabel *descriptionLabel;
id<StoreViewDelegate> storeViewDel;
}
#property (nonatomic) double latitude;
#property (nonatomic) double longitude;
#property (nonatomic) short rating;
#property (nonatomic,retain) NSString *description;
#property (nonatomic,retain) NSString *imageURL;
#property (nonatomic,retain) NSString *storeType;
#property (nonatomic,retain) NSString *offerType;
#property (assign) id<StoreViewDelegate> storeViewDel;
#end
StoreViewController.m
#import "StoreViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface StoreViewController()
-(CGSize) calcLabelSize:(NSString *)string withFont:(UIFont *)font maxSize:(CGSize)maxSize;
#end
#implementation StoreViewController
#synthesize storeViewDel, longitude, latitude, description, imageURL, rating, offerType, storeType;
- (void)mapsButtonClicked:(id)sender
{
}
- (void)loadView
{
UIView *storeView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
// Colours
UIColor *lightBlue = [[UIColor alloc] initWithRed:(189.0f / 255.0f)
green:(230.0f / 255.0f)
blue:(252.0f / 255.0f) alpha:1.0f];
UIColor *darkBlue = [[UIColor alloc] initWithRed:(28.0f/255.0f)
green:(157.0f/255.0f)
blue:(215.0f/255.0f)
alpha:1.0f];
// Layout
int width = self.navigationController.view.frame.size.width;
int height = self.navigationController.view.frame.size.height;
float firstRowHeight = 100.0f;
int margin = width / 20;
int imgWidth = (width - 3 * margin) / 2;
// Set ImageView
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(margin, margin, imgWidth, imgWidth)];
CALayer *imgLayer = [imageView layer];
[imgLayer setMasksToBounds:YES];
[imgLayer setCornerRadius:10.0f];
[imgLayer setBorderWidth:4.0f];
[imgLayer setBorderColor:[lightBlue CGColor]];
// Load default image
NSData *imageData = [NSData dataWithContentsOfFile:#"thumb-null.png"];
UIImage *image = [UIImage imageWithData:imageData];
[imageView setImage:image];
[storeView addSubview:imageView];
// Set Rating
UIImageView *ratingView = [[UIImageView alloc] initWithFrame:CGRectMake(3 * width / 4 - 59.0f,
margin,
118.0f,
36.0f)];
UIImage *ratingImage = [UIImage imageNamed:#"bb-rating-0.png"];
[ratingView setImage:ratingImage];
[ratingImage release];
[storeView addSubview:ratingView];
// Set Get Directions button
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(3 * width / 4 - 71.5f,
36.0f + 2*margin,
143.0f, 63.0f)];
[btn addTarget:self action:#selector(mapsButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
UIImage *mapsImgUp = [UIImage imageNamed:#"bb-maps-up.png"];
[btn setImage:mapsImgUp forState:UIControlStateNormal];
[mapsImgUp release];
UIImage *mapsImgDown = [UIImage imageNamed:#"bb-maps-down.png"];
[btn setImage:mapsImgDown forState:UIControlStateHighlighted];
[mapsImgDown release];
[storeView addSubview:btn];
[btn release];
// Set Description Text
UIScrollView *descriptionView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f,
imgWidth + 2 * margin,
width,
height - firstRowHeight)];
descriptionView.backgroundColor = lightBlue;
CGSize s = [self calcLabelSize:description withFont:[UIFont systemFontOfSize:18.0f] maxSize:CGSizeMake(width, 9999.0f)];
descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(margin, margin, width - 2 * margin, s.height)];
descriptionLabel.lineBreakMode = UILineBreakModeWordWrap;
descriptionLabel.numberOfLines = 0;
descriptionLabel.font = [UIFont systemFontOfSize:18.0f];
descriptionLabel.textColor = darkBlue;
descriptionLabel.text = description;
descriptionLabel.backgroundColor = lightBlue;
[descriptionView addSubview:descriptionLabel];
[storeView addSubview:descriptionView];
[descriptionLabel release];
[lightBlue release];
[darkBlue release];
self.view = storeView;
[storeView release];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
[imageView release];
[descriptionLabel release];
[super dealloc];
}
#end
Any suggestions ?
Thank you,
F.
Perhaps look at your crash report, get an idea of where it's crashing, and help us help you by posting the relevant code if it is not clear to you what is causing the crash. We may be able to help you further, but we need you to do some pre-requisite work first, like trying to solve it yourself with the appropriate information at hand. Now that you know what to look for, please, go forth and unicorn!
The problem was that I released some UIImages that were never allocated. Erasing the following lines solved my issue:
[ratingImage release];
[mapsImgUp release];
[mapsImgDown release];
F.