2

Is it possible to implement custom JSQMessagesInputToolbar for JSQMessagesViewController?

I need to set custom UIToolbar, but inputToolbar property of class JSQMessagesViewController is readonly and initialized from .xib, so I have no idea how to insert overridden implementation of JSQMessagesInputToolbar.

MMiroslav
  • 1,672
  • 20
  • 32

3 Answers3

1

Create a Category and replace the implementation of the method loadToolbarContentView method. This basically replaces the implementation of the original function with the function you define.

So Create a Category with the following .h file :

#import <JSQMessagesViewController/JSQMessagesViewController.h>
@interface JSQMessagesInputToolbar (InputCategory)
@end

And the following .m file

#import "JSQMessagesInputToolbar+InputCategory.h"
@implementation JSQMessagesInputToolbar (InputCategory)

- (JSQMessagesToolbarContentView *)loadToolbarContentView
{
    //this is called once in the loadNib and returns the toolbar

    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"updatedXib" owner:self options:nil];
    return topLevelObjects.firstObject;
    //self.preferredDefaultHeight = 84.0f; this could also be useful
}
@end

You might also want to extended an implementation of JSQMessagesViewController to handle the specific behaviour of the updatedXib UI elements.

M.C.
  • 1,765
  • 3
  • 29
  • 31
1

I am facing the same question,so I explore the JSQMessagesViewController issues;

The issue 358: said that the author is not going to support this any time soon, because other features have higher priority and no one else has requested this. And the author suggest us to fork and customize it.

The other issue is asking the same question and there is a example using Frame to add a second button.

I don't think it's a good example.

I think my demo below is better.

In the viewDidLoad method of JSQMessagesViewController or subclass

UIButton *btn=[UIButton buttonWithType:UIButtonTypeContactAdd];
JSQMessagesToolbarContentView *contentView= self.inputToolbar.contentView;
[contentView.leftBarButtonContainerView addSubview:btn];//add the new button

contentView.leftBarButtonItemWidth=66; //make containerView wider to hold more buttons
//remove unused leftBarButtonItem constraint
for (NSLayoutConstraint *constraint in contentView.leftBarButtonItem.superview.constraints) {
    if(constraint.secondItem ==contentView.leftBarButtonItem &&constraint.firstAttribute ==NSLayoutAttributeLeading){
        constraint.active=NO;
    }
}
// update two button constraint
[contentView.leftBarButtonItem mas_makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(@30);
}];

[btn mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(btn.superview.mas_top);
    make.bottom.equalTo(btn.superview.mas_bottom);
    make.left.equalTo(btn.mas_left);
    make.width.equalTo(@30);
}];

Result like this: InputToolBarContent

Bryan
  • 14,756
  • 10
  • 70
  • 125
Shawn Wang
  • 2,314
  • 1
  • 16
  • 19
0

Swift 3 version of Shawn Wang's answer

        let button = UIButton(type: .infoDark)
        if let contentView = self.inputToolbar.contentView {

            contentView.leftBarButtonContainerView.addSubview(button)
            contentView.leftBarButtonItemWidth = 66

            for constraint in contentView.leftBarButtonItem.superview!.constraints {

                if (constraint.secondItem  as? UIButton) == contentView.leftBarButtonItem && constraint.firstAttribute == .leading {
                    constraint.isActive = false
                }
            }

            contentView.leftBarButtonItem.snp.makeConstraints({ (make) in
                make.width.equalTo(30)
            })

            button.snp.makeConstraints({ (make) in
                make.top.equalTo(button.superview!.snp.top)
                make.bottom.equalTo(button.superview!.snp.bottom);
                make.left.equalTo(3);
                make.width.equalTo(30);
            })
        }

I have used SnapKit for autoLayout

Anand
  • 5,323
  • 5
  • 44
  • 58