I want to have a UISegmentedControl with a number of selectable options in it, but also include an Info button, which is not selectable. The UISegmentedControl class reference talks about using a momentary disclosure button, hinting that its possible, but there is nothing else there or in the header file that explains how to do such a thing.
So how can I do this?
After much experimentation, I found that keeping a shadow variable on the selected index let me do this. In the following code, the info button is 1, the other buttons are selectable. In viewDidLoad set the initial value (or ask the control for its selected index). Then use the following code for the action method:
- (IBAction)segmentAction:(UISegmentedControl *)sender
{
NSUInteger idx = [sender selectedSegmentIndex];
switch(idx) {
case 1: // momentary button
sender.selectedSegmentIndex = selectedIndex;
break;
default:
selectedIndex = idx;
// other stuff
break;
}
...
Essentially all you need to do is reset the selected index. Tested with iOS7 only.
Related
I am using https://github.com/CEWendel/SWTableViewCell library to my project.
Certain situation I need to disable the particular button action of swipe cell.
I cannot find any property in their class file. If anyone crossed this, give me answer.
Here I have attaced my swipe options image:
For ex
: I want to disable the share button action.
Let's assume your share button is in the leftButtonsArray. In the method:
- (void)swipeableTableViewCell:(SWTableViewCell *)cell scrollingToState:(SWCellState)state
{
//case:left buttons opened
UIButton *shareButton = leftButtonsArray[theIndexOfTheShareButton];
shareButton.enabled = NO;
}
#karthikeyan You can hide the button for a particular row in tableview by the following code:
- (void)updateRightUtilityButtons:(NSArray *)rightUtilityButtons WithButtonWidth:(CGFloat) width {
_rightUtilityButtons = rightUtilityButtons;
[self.rightUtilityButtonsView updateUtilityButtons:rightUtilityButtons WithButtonWidth:width];
[self.rightUtilityButtonsView layoutIfNeeded];
[self layoutIfNeeded];
}
Add/update this methods to SWTableViewCell.m class, where rightUtilityButtons is an array of buttons you need to display for the particular row.
In case if you want to disable just user interaction you can achieve while adding button into array, just disable user interaction for that button by shareButton.userInteration = NO and then add to array and then pass the array to the method defined above. By this you can be sure that button is disabled.
But please provide the sample code that you have worked so that can update your code directly.
In case if you still didn't get revert back I'll give you the working code directly here.
I want to create a tableView or tabs that expands when user selects them. This is very commonly used in webpages using jquery.
you can check http://jqueryui.com/accordion/ It does exactly what i want to do in my ipad app. with horizontal tabs too http://jqueryui.com/tabs/
Can anyone tell me how to achieve this in my iPad app ? Or any pointers would be appreciated.
TIA
Sam
1.Use UITableView for first type of tab.
a) Use Header and Cell View in your desired format.
b) Hide and unhide cell view with some animation.
2.Use UISegementedControl for second type of tab.
a) Use function addTarget :
[self.mySegmentedControl addTarget:self action:#selector(segmentChanged) forControlEvents:UIControlEventValueChanged];
b) Implement segmentChanged :
- (void) segmentChanged:(UISegmentedControl *)paramSender{
//check if its the same control that triggered the change event
if ([paramSender isEqual:self.mySegmentedControl]){
//get index position for the selected control
NSInteger selectedIndex = [paramSender selectedSegmentIndex];
if (selectedIndex == 1 ) { // do required } and so on....
}
}
The best possible way is using the headerview to show the Master row and the tableview cells for showing the Details row.Write a touch event for the headerview and set it with the showing and hiding the cells ,with neat row animation.You need to keep the status of the opened and closed state of cell with an array of bools repesenting the no of masterview.
I want to add total 5 button at bottom of screen but only four will be visible at first time loading of nib.
and if user press first button it will be disappear with animation and second button will come at place of first . and now in screen one more button (button 5 ) at last.
to make it more clear i am adding image.
screen 1. when nib loaded first time.
screen 2. when button 1 pressed.
screen 3. when button 2 pressed.
AS U HAVENT POSTED ANY CODE THAT U'VE TRIED.
So Here is some idea I can suggest to u.
If u want to disappear the button when pressed then, instead of removing it from the view u can keep it there but only make it invisible , may be by setting properties of "visual appearance of view"(look for UIView class reference) eg. alpha value,hidden property.
Once u invisible it, then make it visible after some delay eg.1/2 second.
Once button is visible then CHANGE the label text.
In case ur, u'll need to set UILabel text of all four button; by incrementing label-text int value by 1.
How about something like this? It's not perfect so you'll have to play with it but it should get you started in the right direction...
in your .h
IBOutlet UIButton *firstButton, *secondButton, *thirdButton, *fourthButton
NSArray *buttonsArray;
in your .m
-(void)viewDidLoad{
// VDL stuff
buttonsArray = [NSArray arrayWithObjects:#"One", #"Two", #"Three", #"Four", #"Five", #"Six", nil];
[firstButton setTitle:[buttonsArray objectAtIndex:0]];
[firstButton setTag:0];
// initial setup of the other three buttons works the same way
}
-(IBAction)updateButtons:(id)sender{
UIButton *btn = (UIButton*)sender;
int index = btn.tag;
for(int i = 0; i <4; i++){
if([buttonsArray count] > index+i){
switch(i){
case 0:;
[firstButton setTitle:[buttonsArray objectAtIndex:i+index]];
[firstButton setTag:i+index];
break;
case 1:; //secondButton
break;
case 2:; //thirdButton
break;
case 3:; //fourthButton
break;
}
}else{
break;
}
}
}
Then all you need to do is connect the four on-screen buttons to the action and in the else you'll need some logic (pretty much the same as the switch-case above) to hide ones once you get towards the end of the array if that's what you want to do.
I have a typical requirement wherein I need to keep a button in highlighted state after pressing it. I need to perform a task which should work only when a button is in highlighted state. Actually I am setting a button state to highlighted programatically.
[sender setHighlighted:YES];
And once the button is in highlighted state i need to perform another action.
- (IBAction)changeState: (UIButton*)sender
{
if (sender.highlighted == YES)
{
[self performSomeAtion:sender];
}
}
But, to my horror, whenever I press any button, the above condition is becoming true and the action is being performed repeatedly. Is there any way in which i can keep a UIButton's state to be highlighted after pressing it?
EDIT - Actually I need to perform 3 different actions for 3 different states of the button. I am already making use of selected state and normal state. Now, I need to make use of the highlighted state.
[sender setSelected:YES];
or you can simulate this effect with two image for your UIButton (notselectedimage.png and selectedimage.png), then keep track button state with a BOOL variable like BOOL buttonCurrentStatus;. Then in .h file:
BOOL buttonCurrentStatus;
and in .m file
// connect this method with Touchupinside function
- (IBAction)changeState:(UIButton*)sender
{
/* if we have multiple buttons, then we can
differentiate them by tag value of button.*/
// But note that you have to set the tag value before use this method.
if([sender tag] == yourButtontag){
if (buttonCurrentStatus == NO)
{
buttonCurrentStatus = YES;
[butt setImage: [UIImage imageNamed:#"selectedImage.png"] forState:UIControlStateNormal];
//[self performSomeAction:sender];
}
else
{
buttonCurrentStatus = NO;
[butt setImage:[UIImage imageNamed:#"notSelectedImage.png"] forState:UIControlStateNormal];
//[self performSomeAction:sender];
}
}
}
- (void)mybutton:(id)sender
{
UIButton *button = (UIButton *)sender;
button.selected = ![button isSelected]; // Important line
if (button.selected)
{
NSLog(#"Selected");
NSLog(#"%i",button.tag);
}
else
{
NSLog(#"Un Selected");
NSLog(#"%i",button.tag);
}
}
The highlighted state is used to highlight the button while it is being touched. A touch down event in the button highlights it. You should use the "selected" state instead.
If what you want to do is perform an action after the button is pressed, don't attach your method to the state change event, attach your method to the TouchUpInside event.
I just find a way, so I share it, just in case...
I kept my UIButton and set one image for each state (so you could go up to a 4 states button).
I set the UserInteractionEnabled to NO -> This button won't receive any touch.
The purpose of this first button is to show a state
I create a second custom UIButton with the same frame than the first one. For this one, none image will be set for the state (it's a fully transparent button). The purpose of this button is to catch the touch event. So I added a target to this button on the TouchUpInside event. And then when the event is fired, I change the state of the first button to Disabled, Highlighted, Selected, or none of these state (= Default state).
Everything is working like a charm!
The way you describe it, you'd be better off subclassing UIView to create your own three-state button.
Actually, you should even implement your own multistate buttonView, and manage the state it's in internally via an array of PNG for the looks and an array of states to know how many times it's been pressed.
Use [sender setSelected: YES];, I think it will be useful to you.
UIButton *btn_tmp=sender;
if(!(btn_tmp.selected))
{
[btn_temp setHighlighted:YES];
}
For iOS 7 only: you should consider setting the image renderMode to UIImageRenderingModeAlwaysTemplate. You can then use the tintColor to represent various states.
see How to apply a tintColor to a UIImage?
and
see Tint a UIView with all its subviews
The solution is tricky but it's possible.
The problem is that you tried to change the highlighted status in the button action method, which I suppose makes a clean up or check process at the end of the action and switch the highlighted status. When you try to debug it you get the highlighted = 1 but it will change at the end.
Strange but your "3 statuses button" is sometimes useful, when you'd like to keep a button in "highlighted" mode like the "selected" mode to get different action depending on the 3 statuses.
The only problem that you couldn't analyze this or switch it to highlighted mode in the button action method as this will switch to highlighted mode immediately as the user push it AND switch it back at the end.
The solution is using a dispatch.
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[theButton setHighlighted:YES];
});
This will do the trick and you could use the 3 statuses.
According to apple, UIButton has a property of imageView:
Although this property is read-only, its own properties are read/write. Use these properties to configure the appearance and behavior of the button’s view
This means that you can set in the IB (in the storyboard) a picture for this button and set the highlighted picture:
Open the Attribute inspector.
Under Button section, choose an image.
In the same section, change the State Config to Highlighted. Notice the image you chose under default is now gone and now you can set a new picture for the Highlighted.
Now you have a button with 2 state config and all you have to do during runtime to change the button.highlighted = true. Also, check the UIControl under Configuring the Control’s Attributes for more states.
You can also do it programatically as follows:
Swift (and almost the same in Objective-C):
// Setting the highlighted image
self.someButton.imageView?.highlightedImage = UIImage(named: "imageNameFromImageAssest")
// someButton will now some the highlighted image and NOT the image set in the IB
self.someButton.imageView?.highlighted = true
In my project I must control action of 40 buttons, but I don't want to create 40 IBAction, can I use only a IBAction, how?
If you're using interface builder to create the buttons, simply point them at the same IBAction in the relevant class.
You can then differentiate between the buttons within the IBAction method either by reading the text from the button...
- (IBAction)buttonClicked:(id)sender {
NSLog(#"Button pressed: %#", [sender currentTitle]);
}
...or by setting the tag property in Xcode and reading it back via [sender tag]. (If you use this approach, start the tags at 1, as 0 is the default and hence of little use.)
-(IBAction)myButtonAction:(id)sender {
if ([sender tag] == 0) {
// do something here
}
if ([sender tag] == 1) {
// Do something here
}
}
// in Other words
-(IBAction)myButtonAction:(id)sender {
switch ([sender tag]) {
case 0:
// Do something here
break;
case 1:
// Do something here
break;
default:
NSLog(#"Default Message here");
break;
}
Set all the buttons to use that one action. Actions generally have a sender parameter, which you can use to figure out which button is calling the action. One popular way to tell the difference between buttons is to assign a different value to each button's tag property. So you might have 40 buttons with tags ranging from 1 to 40. (0 probably isn't a great choice for a tag since that's what the default value is, and any button for which you forget to set the tag will have 0 as the tag value.)
This technique is most useful when all the buttons do approximately the same thing, like the buttons on a calculator or keyboard. If each of the buttons does something completely different, then you still end up with the equivalent of 40 methods, but you substitute your own switch statement for Objective-C's messaging system. In that case, it's often better just to spend the time to create as many actions as you need an assign them appropriately.
Sure. Just connect all buttons to the same action method in Interface Builder. Use the method's sender argument (possibly in conjunction with the buttons' tag property) to identify which button is sending the event.
Just use one IBAction and assign it to all your buttons.
Just used the above method myself , had a selection of buttons but converted them all and used switch case instead
-(IBAction)buttons:(id)sender
{
switch ([sender tag])
{
case 0 :
}
}
Seems like you are getting all the answers you need, but I wanted to add to everyone else's answers.
Whether you want to use one IBAction or 40 actions is up to what you want the buttons to do. If all the buttons do completely different things, you need all separate IBActions, but if you want all of them to do the same thing, you can use just one. I need more details of those buttons and action, but you probably have title for each button, so you can use that to differentiate each button and create a message or something that's being customized by the particular button pressed. Here is the example. Each time a button is pressed, a label displays a message that say "i.e.title of the button" pressed.
By doing it this way, you don't need to do switch case with all 40 patterns. You can still display or do something that's individualized by the button pressed with just 2-3 lines of code.
- (IBAction)button_Clicked:(UIButton *)sender {
//Get the buttons' titles.
NSString *title =[sender titleForState:UIControlStateNormal];
//Construct a message that includes the *title.
NSString *plainText=[NSString stringWithFormat:#"%# button pressed.", title];
//Assigns the *plainText to the label.
self.Label.text=plainText;
}
#end