I am using a UISegmentedControl with some custom images:
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:nil];
[segmentedControl insertSegmentWithImage:[UIImage imageNamed:#"0.png"] atIndex:0 animated:NO];
[segmentedControl insertSegmentWithImage:[UIImage imageNamed:#"1.png"] atIndex:1 animated:NO];
[segmentedControl insertSegmentWithImage:[UIImage imageNamed:#"2.png"] atIndex:2 animated:NO];
segmentedControl.frame = CGRectMake(0, 0, 90, 30);
[self.view addSubview:segmentedControl];
[segmentedControl release];
This part works fine. But, it still uses Apple's styling for the control and just adds my images over it. Is there a way that I don't have to use Apple's styles, and customize the conrol with my own images with no background? I would also like to have my own "selected" state images.
Possible?
Nic,
After playing with this for a while, I decided to simply "roll my own" in a way.
I made some button images in photoshop and got everything looking like a segmented control. Then, I set a different image for the "selected" states of all the buttons. When one button was pressed, I called setSelected:NO to the others. Then, I handled whatever I needed to do.
I'd love to hear other solutions.
In addition to DexterW's answer. I had came to same decision - to mimic UISegmentedControl using UIButtons only.
However its not a simple task to mimic UISegmentControl. I tried to use Selected state of a UIButton but UIButton wont work as expected if set same settings (bg image, font color) for Hightlighted and Selected states. In such case when segment looks selected its still "pressable" visually. So, to avoid it and make buttons set acting more like UISegmentedControl I didn't use a selected state at all. Instead Id decided to change appearance of selected button in code so that normal and highlighted states are the same visually for selected button and different for unselected one.
Assume I have 3 buttons segmentedControl (LeftSgm | MiddleSgm | RightSgm) and for normal state Im using bg picture named "segment_default" and font color white and for selected state its bg picture named "segment_active" and black font. So in onTouchDown:
-(IBAction)onTopMenuTap:(id)sender
{
int newSelectedSegmentIndex;
if (sender == btnLeftSgm)
newSelectedSegmentIndex=0;
else if (sender == btnMiddleSgm)
newSelectedSegmentIndex=1;
else if (sender == btnRightSgm)
newSelectedSegmentIndex=2;
else
return;
NSLog(#"Tapped segment index %d while old one is %d",newSelectedSegmentIndex,selectedSegmentIndex);
if (newSelectedSegmentIndex==selectedSegmentIndex)
return;
[self handleSegmentAppearenace:newSelectedSegmentIndex];
//do whatever its need to be done
...
}
and the called method is
-(void)handleSegmentAppearenace:(int)newSelectedSegmentIndex
{
if (selectedSegmentIndex==0){
[btnLeftSgm setBackgroundImage:[UIImage imageNamed:#"segmented_control_default_left"] forState:UIControlStateNormal];
[btnLeftSgm setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
btnLeftSgm.highlighted = NO;
}
else if (selectedSegmentIndex==1){
[btnMiddleSgm setBackgroundImage:[UIImage imageNamed:#"segmented_control_default_center"] forState:UIControlStateNormal];
[btnMiddleSgm setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
btnMiddleSgm.highlighted = NO;
}
else if (selectedSegmentIndex==2){
[btnRightSgm setBackgroundImage:[UIImage imageNamed:#"segmented_control_default_right"] forState:UIControlStateNormal];
[btnRightSgm setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
btnRightSgm.highlighted = NO;
}
if (newSelectedSegmentIndex==0){
[btnLeftSgm setBackgroundImage:[UIImage imageNamed:#"segmented_control_active_left"] forState:UIControlStateNormal];
[btnLeftSgm setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
btnLeftSgm.highlighted = YES;
}
else if (newSelectedSegmentIndex==1){
[btnMiddleSgm setBackgroundImage:[UIImage imageNamed:#"segmented_control_active_center"] forState:UIControlStateNormal];
[btnMiddleSgm setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
btnMiddleSgm.highlighted = YES;
}
else if (newSelectedSegmentIndex==2){
[btnRightSgm setBackgroundImage:[UIImage imageNamed:#"segmented_control_active_right"] forState:UIControlStateNormal];
[btnRightSgm setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
btnRightSgm.highlighted = YES;
}
}
All three buttons are bound in IB to corresponding properties (btnRightSgm etc). Also for "touch up event" onTopMenuTap is bound.
Cant say its a best idea but it works perfectly for me.
Related
I am using the StoryBoard feature for my iPhone project. In the storyboard, I have a view controller with a table view using prototype cells. Inside the prototype cell, I have a UIButton (rounded rectangle) hooked up to a sub-classed UIButton class. The tableview gets its data from an array, and the data is printed out in cellForRowAtIndexPath.
Inside cellForRowAtIndexPath, I conditionally modify the cell's appearance. This is when I start getting problems. I am able to successfully change the text of the button. However, if I attempt to change the image of the button, using:
[cell.myButton setImage:[UIImage imageNamed:#"mynewimage.png"] forState:UIControlStateNormal];
the image is changed, but the text disappears.
If I attempt to change the text color of the button, using:
[cell.myButton setTitleColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:.77] forState:UIControlStateNormal]
Nothing happens whatsoever. The color remains the same (unless I also try to change the image, in which case it completely disappears).
I am sensing I am doing something fundamentally wrong here -- do you have any suggestions?
use
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
to change image with text left
use
btn.titleLabel.textColor = yourcolor;
to change text color
Define myButton as below and check.This may be the wrong in your code.The code is:
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
This is newly editted part:
[myButton setBackgroundImage:yourimage forState:UIControlStateNormal];
[myButton setTitleColor:yourcolor forState:UIControlStateNormal];
This is the way to set different properties to a Custom Button...You also find that setBackgroudimage and setTitleColor properties here...
UIButtin *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setFrame:CGRectMake(165, 205, 65, 40)];
[myButton setTitleColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:.77] forState:UIControlStateNormal];
[myButton setTitle:#"Hi....." forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[myButton setBackgroundImage:[UIImage imageNamed:#"mynewimage.png"] forState:UIControlStateNormal];
[cell addSubview:myButton];
Thank u..
I guess what you want is to change your button background:
[cell.myButton setBackgroundImage:[UIImage imageNamed:#"mynewimage.png"] forState:UIControlStateNormal];
Your text disappears because you have set the image at button front side as button main image.
[cell.myButton setImage:[UIImage imageNamed:#"mynewimage.png"] forState:UIControlStateNormal];
You need to set the button background image so that your text would be visible as the image will be drawn at the rear side of your UIButton context.
So just replace the above line of code to :
[cell.myButton setBackgroundImage:[UIImage imageNamed:#"mynewimage.png"] forState:UIControlStateNormal];
I created a UIBarButton programmatically with the following code:
UIButton * rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
[rightButton setFrame:CGRectMake(0, 0, 81, 30)];
[rightButton setBackgroundColor:[UIColor clearColor]];
rightButton.layer.borderColor = [UIColor blackColor].CGColor;
rightButton.layer.borderWidth = 0.5f;
rightButton.layer.cornerRadius = 5.0f;
rightButton.titleLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
[rightButton setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal];
[rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
//set text according to sign in status
if (signIn) {
[rightButton setTitle:#"5 votes left" forState:UIControlStateNormal];
} else {
[rightButton setTitle:#"Sign in" forState:UIControlStateNormal];
}
UIBarButtonItem * rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:rightButton];
self.navigationItem.rightBarButtonItem = rightBarButton;
The obtained button has the desired aspect but now what I need is that when the status of the button is highlighted there should be a gradient effect fading to black to let the user know that he has pressed the button, because right now when I pressed the button, nothing happens to the view so the user has no way to know that he has pressed the button.
I want to explore a choice that does NOT involve setting the background images for the desired states because the text of the button can change dynamically according to the app configurations so I need to do this entirely by code.
Although this won't directly answer your question, it may help. I had to create some graphics for a button dynamically and came up with a method using core graphics to create my button image. It gives me the flexibility to change to appearance parametrically in the code.It draws the button image in an abstract graphics context and then converts the result into an image that I can use for my button. YOu might get enough out of my explanation that you can try it yourself for your needs.
Subclass UIButton and add a CALayer or CAGradientLayer to achieve the highlight effect that you want. Set the initial state of the highlight layer to hidden. Override setHighlighted: with something like:
- (void) setHighlighted:(BOOL)highlight {
highlightLayer.hidden = !highlight;
[super setHighlighted:highlight];
}
Whenever I tap "newButton" my app crashes. I am using automatic reference counting.
Edit: Just tried this in a different app and it works but does not work in my own.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *fullView = [[UIView alloc] initWithFrame:CGRectMake(0, -20, 320, 480)];
fullView.backgroundColor = [UIColor blackColor];
[[self view] addSubview:fullView];
UIImage* blackButton =[[UIImage imageNamed:#"UIButtonBlack.png"]stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0];
// Create button
UIButton *newButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 30)];
// Set button content alignment
newButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
newButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
// Set button title
[newButton setTitle:#"Do Something" forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
// Set button title color
[newButton setTitleColor:[UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:1.0] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
// Add the background image
[newButton setBackgroundImage:blackButton forState:UIControlStateNormal];
// Add Events
[newButton addTarget:self action:#selector(showScanner:) forControlEvents:UIControlEventTouchUpInside];
// in case the parent view draws with a custom color or gradient, use a transparent color
[newButton setBackgroundColor:[UIColor clearColor]];
// Set titleShadowColor this way (apparently, titleLabel.shadowcolor does not work)
[newButton setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
// Set button titleLabel properties
newButton.titleLabel.font = [UIFont fontWithName:#"PTSans-Bold" size:13.0];
newButton.titleLabel.shadowOffset = CGSizeMake(1, 1);
[fullView addSubview:newButton];
}
- (void)showScanner:(id)sender
{
NSLog(#"Do something…");
}
I believe UIControlState's cannot be & (or |) together because according to the UIControl Reference Docs:
a control can have more than one state at a time.
Try separating them out like this:
// Set button title
[newButton setTitle:#"Do Something" forState:UIControlStateNormal];
[newButton setTitle:#"Do Something" forState:UIControlStateHighlighted];
[newButton setTitle:#"Do Something" forState:UIControlStateSelected];
// Set button title color
[newButton setTitleColor:[UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:1.0] forState:UIControlStateNormal];
[newButton setTitleColor:[UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:1.0] forState:UIControlStateHighlighted];
[newButton setTitleColor:[UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:1.0] forState:UIControlStateSelected];
// Add the background image
[newButton setBackgroundImage:blackButton forState:UIControlStateNormal];
// Add Events
[newButton addTarget:self action:#selector(showScanner:) forControlEvents:UIControlEventTouchUpInside];
// in case the parent view draws with a custom color or gradient, use a transparent color
[newButton setBackgroundColor:[UIColor clearColor]];
// Set titleShadowColor this way (apparently, titleLabel.shadowcolor does not work)
[newButton setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateNormal];
[newButton setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateHighlighted];
[newButton setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateSelected];
// Set button titleLabel properties
newButton.titleLabel.font = [UIFont fontWithName:#"PTSans-Bold" size:13.0];
newButton.titleLabel.shadowOffset = CGSizeMake(1, 1);
It may be crashing because button should be newButton.
Change this:
[button setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
To this:
[newButton setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
You're not keeping a reference to your view controller. You either need to
use a standard iOS view controller manager like UITabBarController or UINavigationController to display your views
keep a reference (in an instance variable) to this view controller within the class that you opened it from.
Note that if you were to re-write this code with ARC turned off, you'd have a memory leak, instead of a crash.
The problem is that all references to the view controller from the view are weak references, meaning that they don't retain the controller*. So in your loading code ARC releases the view controller after you've made it and accessed its view, and it's gone.
Within your app you should keep track of all the view controllers, and access their views through them. Something like UINavigationController does this for you.
*This is because the view controller is considered to have ownership over the view, and if the view controller retained the view and the view retained the view controller, there'd be a retain loop, and neither of them would ever be released.
My custom UISegmented control has background images [for each state]. How do I add text above the images [for each state, meaning that when index 0 will be selected I will have a specific color and font] ?
Here's how my UISegmented control looks like:
UISegmentedControl *customUISC=[[UISegmentedControl alloc] initWithItems:[[[NSMutableArray alloc] initWithObjects:#"ON",#"OFF",nil] autorelease]];
[customUISC setFrame:CGRectMake(11,14,298,28)];
customUISC.selectedSegmentIndex=0;
customUISC.segmentedControlStyle=UISegmentedControlStyleBar;
[customUISC setImage:[UIImage imageNamed:#"FirstTabActive.png"] forSegmentAtIndex:0];
[customUISC setImage:[UIImage imageNamed:#"SecondTab.png"] forSegmentAtIndex:1];
[customUISC addTarget:self action:#selector(checkOnOffState:) forControlEvents:UIControlEventValueChanged];
and the checkOnOffState method looks like:
-(IBAction)checkOnOffState:(id)sender{
UISegmentedControl *iSeg=(UISegmentedControl *)sender;
if(iSeg.selectedSegmentIndex==0){
[iSeg setImage:[UIImage imageNamed:#"FirstTabActive.png"] forSegmentAtIndex:0];
[iSeg setImage:[UIImage imageNamed:#"SecondTab.png"] forSegmentAtIndex:1];
}
else {
[iSeg setImage:[UIImage imageNamed:#"FirstTab.png"] forSegmentAtIndex:0];
[iSeg setImage:[UIImage imageNamed:#"SecondTabActive.png"] forSegmentAtIndex:1];
}
}
I'm not sure I fully understand what you're after, but could you just make use of UILabels (positioned above the images). You could then change the colours and text quite easily using myLabel.text and myLabel.textColor.
Hope this helps in some way!
I created a UISwitch using this code...
UISwitch *switch = [[UISwitch alloc]initWithFrame:CGRectMake(110, 230, 60, 60)];
[window addSubview:switchView];
[switchView release];
The created button will be....
The default properties are,
It contains "ON" & "OFF" states
The OFF button is white & the ON button is in blue color
I want to create a customized switch, so that the background color & text in the switch should be changed. Is it possible? Please explain in detail.
Thanks in Advance,
Rajkanth
You can not modify UISwitch control unless and until you write your own control,
But best way so far, you can used UISegmentControl and handle event on it to switch the on.png and off.png images.
UISegmentedControl* switchView=[[UISegmentedControl alloc] initWithItems:[[[NSMutableArray alloc] initWithObjects:#"On",#"Off",nil] autorelease]];
[switchView setFrame:CGRectMake(20,365,140,28)];
switchView.selectedSegmentIndex=0;
switchView.segmentedControlStyle=UISegmentedControlStyleBar;
[switchView setImage:[UIImage imageNamed:#"onSelected.png"] forSegmentAtIndex:0];
[switchView setImage:[UIImage imageNamed:#"off.png"] forSegmentAtIndex:1];
[switchView addTarget:self action:#selector(checkOnOffState:) forControlEvents:UIControlEventValueChanged];
self.navigationItem.titleView=switchView;
and write checkOnOffState method code like this-
-(IBAction)checkOnOffState:(id)sender{
UISegmentedControl* tempSeg=(UISegmentedControl *)sender;
if(tempSeg.selectedSegmentIndex==0){
[tempSeg setImage:[UIImage imageNamed:#"onSelected.png"] forSegmentAtIndex:0];
[tempSeg setImage:[UIImage imageNamed:#"off.png"] forSegmentAtIndex:1];
}
else{
[tempSeg setImage:[UIImage imageNamed:#"on.png"] forSegmentAtIndex:0];
[tempSeg setImage:[UIImage imageNamed:#"offSelected.png"] forSegmentAtIndex:1];
}
}
I used this solution: UICustomSwitch: it works customizing a UISlider and setting a max valure of 1.
You can change the images of your switch, the right / left text and use it with a unique color on background (if you don't want to use images).
The only change I did was about the name: UI is reserved for Apple classe, so I changed it for my own.