I'm building an messaging app, I use JSQMessageViewController to render messages and it's awesome.
Now I have a little problem trying to customize the send button:
Basically I want to replace left and right BarButtonItem to customized button with images.
After some hours of reading and searching, I got this far now:
button without text
button with text
As shown in the pictures, the voice button which is replacing the original send button is disabled if there is no text in the textField, this behavior is not what I want. How do I disable this behavior and make the button available all the time?
And this is how I customize the send button:
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
[rightButton setBackgroundImage:[UIImage imageNamed:#"AudioButton#2x.png"] forState:UIControlStateNormal];
self.inputToolbar.contentView.rightBarButtonItem = rightButton;
if you want button available all the time,
Find This method in "JSQMessagesInputToolbar.h" And Comment These lines in OLD Code
- (void)toggleSendButtonEnabled
{
BOOL hasText = [self.contentView.textView hasText];
// if (self.sendButtonOnRight) {
// self.contentView.rightBarButtonItem.enabled = hasText;
// }
// else {
// self.contentView.leftBarButtonItem.enabled = hasText;
// }
}
in New JSQ Code
- (void)updateSendButtonEnabledState
{
if (!self.enablesSendButtonAutomatically) {
return;
}
BOOL enabled = [self.contentView.textView hasText];
// switch (self.sendButtonLocation) {
// case JSQMessagesInputSendButtonLocationRight:
// self.contentView.rightBarButtonItem.enabled = enabled;
// break;
// case JSQMessagesInputSendButtonLocationLeft:
// self.contentView.leftBarButtonItem.enabled = enabled;
// break;
// default:
// break;
// }
}
this will work if you are replacing your custom button in rightBarButtonItem
add this in viewDidAppear
[self.inputToolbar.contentView.rightBarButtonItem setEnabled:YES];
and override textview delegate
-(void)textViewDidChange:(UITextView *)textView;
Related
I have some code that creates barbuttonitem Edit and if you click it and begin editing, changes the button to Done.
When I first create the button I set its action to Edit. However, once the user is editing, I want to change the action of the renamed button to Save.
I thought I had save firing but somewhere along the line it stopped working possibly when I added a method in the middle to enable and disable the button.
Can anyone suggest the proper way to change the action of a bar button item?
Here is my code:
//code to create button which sets action to gotoEdit method
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStylePlain target:self action:#selector(gotoEdit)];
self.navigationItem.rightBarButtonItem = editButton;
}
-(void) gotoEdit {
self.navigationItem.rightBarButtonItem.title = #"Done";
_editButton.target = self;
_editButton.action = #selector(save);//changes action to save method
//some other code to make a textview editable, change its background color and so forth.
}
-(void) save {
NSLog(#"save method firing");
}
//I added the following methods at about the same time the save method stopped firing but not sure if they are related. (Probably not but including them anyway.)
//detect change on screen
- (void)textViewDidChange:(UITextView *)textView{
self.didChange=YES;
[self updateSaveButton];
}
-(void) updateSaveButton
{
self.editButton.enabled = (_didChange == TRUE);
}
It is better to use a bool instead of adding and removing the button's action.
-(void) gotoEdit {
if(!isEditing){
// Prep for editing
self.navigationItem.rightBarButtonItem.title = #"Done";
isEditing = true;
}else{
// Prep for saving
self.navigationItem.rightBarButtonItem.title = #"Edit";
isEditing = false;
}
}
For future reference you can remove a button's selector like this:
[_editButton removeTarget:self
action:#selector(gotoEdit)
forControlEvents:UIControlEventTouchUpInside];
I have some buttons on my storyboard that I removed all text from and which I later add text to programmatically, so when the application starts the buttons are invisible. However, if a user clicks any one of the buttons, all four of the buttons show (null) in the label section of the button. I thought this might be because the buttons were enabled, so I added this code in the initWithFrame method of the subclass of UIView where the buttons are a property however it didn't change anything.
Furthermore, I don't understand why clicking one of the buttons would show (null) in the label area of all four buttons.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.button1.enabled= NO;
self.button2.enabled= NO;
self.button3.enabled= NO;
self.button4.enabled= NO;
}
return self;
}
I then considered that maybe this initWithFrame method isn't getting run when I thought it was. I tried in the subview of UIView and didn't change result
-(id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
self.answerChoice1.enabled= NO;
self.answerChoice2.enabled= NO;
self.answerChoice3.enabled= NO;
self.answerChoice4.enabled= NO;
}
return self;
}
Can you explain why all four buttons are showing (null) if I click on any one of them?
it depends i think on the selector the button is calling, and also whether you are able to distinguish your buttons.
you can use button.tag property to distinguish between your buttons as below:
// declare and allocate
UIButton* button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// set frame
button1.frame = frameButton1;
// add to view
[self.view addSubview: button1];
// properties from docs
// button1.enabled or button1.hidden or button1 setTitle.. here
// add selector
[button1 addTarget:self selector:#selector(buttonAction:) ..UIEventTouchUpInside];
// add identifier, integer in this case
button1.tag = 1;
// repeat for other buttons
// in your selector
- (void)buttonAction:(UIButton *)sender
{
// identify button
switch (sender.tag) {
case 0:
// perform action
[self doAction];
break;
//..
}
// perform shared actions
}
i have a Navigation Bar, wich contains a Navigation Item, which contains 2 Bar Buttons, these are created in the Storyboard, and i wanted to change 1 of the buttons at runtime, now this works:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UINavigationItem *thisNavBar = [self myNavigationItem];
thisNavBar.rightBarButtonItem = nil; // this works, it gets removed
UIBarButtonItem *insertBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(insertSkemaItem:)];
thisNavBar.rightBarButtonItem = insertBtn; // this also works, it sets the btn
}
Now, in my other method, which is called by another controller, it does not work
- (void)callChildChange {
...
// remove old btn
UINavigationItem *thisNavBar = [self skemaNavigationItem];
thisNavBar.rightBarButtonItem = nil; // does not work?
}
There is nothing wrong with the method, it runs just fine, but the nav btn item does not get removed ?
skemaNavigationItem is a Navigation item, declared in the .h file which links the navigation item i made via the storyboard.
Your UI items need to be added to your code (by ctrl-dragging) in the header file (.h) so they can be publicly accessed from other classes/view controllers.
Presuming you've done this, hiding a UI item is best done by using
relevantClass.yourViewObject.hidden = YES;
or if you really need to delete it for good,
[relevantClass.yourViewObject.view removeFromSuperView];
Edits
Options for changing target method:
Declare #property (nonatomic, assign) BOOL myButtonWasPressed; and:
- (IBAction) myButtonPressed
{
if (!self.myButtonWasPressed)
{
// This code will run the first time the button is pressed
self.myButton.text = #"New Button Text";
self.myButtonWasPressed = YES;
}
else
{
// This code will run after the first time your button is pressed
// You can even set your BOOL property back, and make it toggleable
}
}
or
- (IBAction) myButtonWasPressedFirstTime
{
// do what you need to when button is pressed then...
self.myButton.text = #"New Button Text";
[self.myButton removeTarget:self action:#selector(myButtonPressedFirstTime) forControlEvents:UIControlEventTouchUpInside];
[self.myButton addTarget:self action:#selector(myButtonPressedAgain) forControlEvents: UIControlEventTouchUpInside];
}
- (IBAction) myButtonWasPressedAgain
{
// this code will run the subsequent times your button is pressed
}
just wondering how to make a button "START" that when pressed triggers a function and the text changes to "STOP". then when pressed again the function will stop and the text changes back to "START"
Ive got the button already that starts the function. and i can handle changing the title, just not sure on what to use to make the 1 button have 2 functions
Add the IBAction method like:
- (IBAction)buttonTapped:(id)sender
{
UIButton *btn = (UIbutton *)sender;
NSString *title=btn.titleLabel.text;
if ([title isEqualToString:#"Start"])
{
//Start
}else
{
//Stop
}
}
Please try this:
- (IBAction) buttonAction:(id)sender
{
if([[(UIButton *)sender currentTitle]isEqualToString:#"START"])
{
[actionButton setTitle:#"STOP" forState:UIControlStateNormal];
//start the action here and change the button text to STOP
}
else if([[(UIButton *)sender currentTitle]isEqualToString:#"STOP"])
{
[actionButton setTitle:#"START" forState:UIControlStateNormal];
//stop the action here and change the button text to START
}
}
you have at least two options here:
Check for the title of your button and depending on the value call an action or the other.
Create two different buttons, each one with his action and show/hide them.
I have made 20 Buttons dynamically, and I got the tag values of all Buttons.
But I need to know how to use that tag values.
I need information on every button pressed with tag values.
So, how do I use those tag values?
You need to set target-action of each button.
[button setTarget:self action:#selector(someMethod:) forControlEvents:UIControlEventTouchUpInside];
Then implement someMethod: like this:
- (void)someMethod:(UIButton *)sender {
if (sender.tag == 1) {
// do action for button with tag 1
} else if (sender.tag == 2) {
// do action for button with tag 2
} // ... and so on
}
Why do you need to use the tag to get the button. You can directly get the buttons reference from its action method.
- (void)onButtonPressed:(UIButton *)button {
// "button" is the button which is pressed
NSLog(#"Pressed Button: %#", button);
// You can still get the tag
int tag = button.tag;
}
I hope you have added the target-action for the button.
[button addTarget:self action:#selector(onButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
You can get reference to that your buttons using that tags. For example, you've added UIButtons to UIView *mainView. To get reference to that buttons you should write following:
UIButton *buttonWithTag1 = (UIButton *)[mainView viewWithTag:1];
Set the tags like this :
for (createButtonIndex=0; createButtonIndex<buttonsCount; createButtonIndex++)
{
buttonCaps.tag=createButtonIndex;
}
And add the method to trap the tags :-
-(void)buttonsAction:(id)sender
{
UIButton *instanceButton = (UIButton*)sender;
switch(instanceButton.tag)
{
case 1(yourTags):
//Code
break;
case 2:
//Code
break;
}
}
Hope this Helps !!
- (IBAction)buttonPressed:(id)sender {
UIButton selectedButton = (UIButton *)sender;
NSLog(#"Selected button tag is %d%", selectedButton.tag);
}
usefully we use btn tag if You Write One Function For (more than one) Buttons .in action if we want to write separate Action For button at that situvation we use btn tag.it can get two ways
I) case sender.tag
//if we have four buttons Add,mul,sub,div having Same selector and add.tag=10
mul.tag=20,sub.tag=30,div.tag=40;
-(IBAction) dosomthing:(id)sender
{
int x=10;
int y=20;
int result;
if(sender.tag==10)
{
result=x+y;
}else if(sender.tag==20)
{
result=x*y;
}else if(sender.tag==30)
{
result=x-y;
}else if(sender.tag==40)
{
result=x/y;
}
NSLog(#"%i",result);
}
2)Case
UIButton *btn=[self.view viewWithTag:10];
then you got object of add button uyou can Hide It With btn.hidden=YES;
UIButton *btn = (UIButton *)[mainView viewWithTag:button.tag];