Subclass UIButton to show visual feedback when tapped - ios

I am trying to implement a solution I found in another thread but I fail. In interface builder I used the custom class ZFRippleButton for the UIButton class and I changed the type to Custom and State Config to Highlighted. This is the code I used:
#interface ZFRippleButton : UIButton
- (id)initWithCoder:(NSCoder *)aDecoder;
#end
#implementation ZFRippleButton
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self makeBorder];
}
return self;
}
- (void)makeBorder {
self.layer.cornerRadius = 10.0;
self.layer.borderColor = [[UIColor blueColor] CGColor];
self.layer.borderWidth = 1.0;
}
#end
My purpose is to get a circle with a custom color when I tap the button. What am I doing wrong?

Related

Subclass tool bar

I added a toolbar on top of the keyboard, it appears every-time the user clicks on a TextView, it also has a number of buttons that change and interact with the TextView, like for example, changing the text font.
What I'm trying to do now is to create a subclass of the Toolbar so that it can be used on other TextViews, but my problem is:
How to use the TextView delegate methods from inside the Toolbar subclass?
Here is my current code(not all code, for not making the post too big):
.h
#import <UIKit/UIKit.h>
#interface CustomUIToolbar : UIToolbar{
UIButton *btn1;
UIButton *btn2;
UIButton *btn3;
}
.m
#implementation CustomUIToolbar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIBarButtonItem *one = ...
UIBarButtonItem *two = ...
UIBarButtonItem *three = ...
self.barStyle = UIBarStyleDefault;
self.layer.borderWidth = 1;
self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
self.items = [NSArray arrayWithObjects:one,placeholder,two,three,four,five,nil];
[self sizeToFit];
}
return self;
}
-(void)actionBtn3:(UIButton *) barBtnItem{
...
}
-(void)actionBtn2:(UIButton *) barBtnItem{
...
}
-(void)actionBtn1:(UIButton *) barBtnItem{
...
}
// And the UITextView Delegate Methods
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
...
return YES;
}
- (void)textViewDidChangeSelection:(UITextView *)textView {
...
}
Your CustomUIToolbar class should conform to UITextViewDelegate protocol:
#interface CustomUIToolbar : UIToolbar <UITextViewDelegate> {
Then you need to assign your CustomUIToolbar subclass as a delegate to textView:
self.textView.delegate = self.customTabbar;
Update:
I think the problem because your toolbar instance is released before the delegate method is called on it. Try to make a property to make sure that variable stays in memory. So instead of:
UIToolbar *tool = [[CustomUIToolbar alloc] init];
Create a property:
#property(nonatomic, strong) CustomUIToolbar *tool;
And initialize it:
self.tool = [[CustomUIToolbar alloc] init];
You can make another class for UIextView and import toolbar class in it and call bar button click method from this class. and use textview of this class where it need.

iOS7 Selected Effect on Button Border

So I am new to iOS and I want some buttons with rounded boarders. I also want those borders to have the same effect as the text within the button when the button is selected.
Since roundRect buttons are no longer an object in iOS (or at least I couldn't find it and everywhere I read said that is was no more) I decided to write a custom class that extends UIButton. This is what I have:
- (void)drawRect:(CGRect)rect{
{
UIColor *blackColor = blackColor;
UIColor *transBlack = [blackColor colorWithAlphaComponent:(0.5)];
[self.layer setCornerRadius:10.0f];
[self.layer setBorderColor:[UIColor blackColor].CGColor];
[self.layer setBorderWidth:1.0];
if(self.isSelected){
[self.layer setBorderColor:(transBlack.CGColor)];
}
I'm not sure if I am using isSelected properly. I had an NSLog under it and it never seems to be executed no matter how many times I press the buttons.
Any help and suggestions of all kinds would be greatly appreciated. Thank you.
UIButton inherit from UIView, So you can use Layer's Methods...
Create new Object that Subclassing UIButton call it whatever you want, then implement the next Code:
In this sample i have UIButton subclass called PressedButton in the .m file:
#implementation PressedButton
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
//When the button is pressed the border color change to red
self.layer.borderColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5].CGColor;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
//When the button is pressed the border color change back to black
self.layer.borderColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5].CGColor;
}
- (void)initialize{
self.layer.cornerRadius = 10.0f;
self.layer.borderColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5].CGColor;
self.layer.borderWidth = 2;
self.layer.masksToBounds = YES;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self initialize];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self initialize];
}
return self;
}
#end
*** I implemented the all init methods to be sure no matter where i set the button (storyboard or via Code its get the same init).
After that just configure your button custom class to your "Pressed Button class" and that's it
If you need more help be free to ask :)

Add category to UITextView and Override it's init function while UITextView is in xib

I can't intercept the init function that's getting called when it's getting created inside of the xib file.
I want to add borderline to it when it gets created so that I won't need to add it manually.
.h:
#import <UIKit/UIKit.h>
#interface UITextView (FITAddBorderline)
- (id) init;
- (id) initWithFrame:(CGRect)frame;
#end
.m:
#import "UITextView+FITAddBorderline.h"
#implementation UITextView (FITAddBorderline)
- (id) init
{
self = [super init];
if (self) {
[self addBorderline];
}
return self;
}
- (id) initWithFrame:(CGRect)frame {
self = [super init];
if (self) {
self.frame = frame;
[self addBorderline];
}
return self;
}
- (void) addBorderline {
//To make the border look very close to a UITextField
[self.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]];
[self.layer setBorderWidth:2.0];
//The rounded corner part, where you specify your view's corner radius:
self.layer.cornerRadius = 5;
self.clipsToBounds = YES;
}
#end
Views that come from NIBs are initialized with initWithCoder:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self addBorderline];
}
return self;
}
As a side note, I would recommend changing what you are doing and use a subclass instead of a category. You can get yourself into some trouble overriding methods in a category. See more info here.
You just need to implement the awakeFromNib method:
-(void)awakeFromNib
{
[super awakeFromNib];
[self addBorderline];
}

drawRect not getting called from setNeedsDisplay

I have recently started learning core graphics to draw on views, but every time I call setNeedsDisplay, the method runs but doesn't trigger drawRect. In my project, I have a view on a view controller. The view contains an if statement in drawRect that checks if a BOOL variable is YES or NO. If YES, it uses the code to draw a red circle. If NO, it draws a blue circle. In the BOOL's setter, it calls setNeedsDisplay. I create an instance of this view class in the ViewController and set the BOOL but the view is not redrawing. Why is the method not getting called? I posted the xcode files and code bits below.
Customview.m:
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
-(void)awakeFromNib{
[self setup];
}
-(void)setup{
_choice1 = YES;
}
-(void)setChoice1:(BOOL)choice1{
_choice1 = choice1;
[self setNeedsDisplay];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
if (_choice1) {
UIBezierPath * redCircle = [UIBezierPath bezierPathWithOvalInRect:rect];
[[UIColor redColor]setFill];
[redCircle fill];
}else if (!_choice1){
UIBezierPath * blueCircle = [UIBezierPath bezierPathWithOvalInRect:rect];
[[UIColor blueColor]setFill];
[blueCircle fill];
}
}
#end
CustomView.h:
#import <UIKit/UIKit.h>
#interface CustomView : UIView
#property (nonatomic) BOOL choice1;
#end
ViewController.m:
#import "ViewController.h"
#import "CustomView.h"
#interface ViewController ()
- (IBAction)Change:(id)sender;
#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.
}
- (IBAction)Change:(id)sender {
CustomView * cv = [[CustomView alloc]init];
[cv setChoice1:NO];
}
#end
Full project: https://www.mediafire.com/?2c8e5uay00wci0c
Thanks
You need to create an outlet for your CustomView in your ViewController. Delete the code that creates the new CustomView instance and use _cv to refer to the customView.
#interface ViewController ()
- (IBAction)Change:(id)sender;
#property (weak,nonatomic) IBOutlet CustomView *cv;
#end
Then, in the storyboard, connect ViewController's cv outlet to the CustomView. Also, you'll need to implement the initFromCoder: method on CustomView.
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self setup];
}
return self;
}

how to attributes for customer UIButon

I have a button that I am trying to add a border to like this:
.h
#interface MyButton : UIButton
.m
#implementation MyButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
}
self.layer.borderWidth=1.0f;
self.layer.cornerRadius = 4;
self.layer.borderColor=[[UIColor blueColor] CGColor];
return self;
}
The border is not set, what am I doing wrong?
UIButton is not meant to be subclassed, I recommend using a category if all you are trying to do is style buttons. Here is an example category to accomplish what you want... note that this has not been run through a compiler, but you get the idea:
UIButton+Styles.h
#import <UIKit/UIKit.h>
#interface UIButton (Styles)
-(void)styleWithBorderColor:(UIColor *)color;
#end
.m
#import "UIButton+Styles.h"
#import <QuartzCore/QuartzCore.h>
#implementation UIButton (CURStyles)
-(void)styleWithBorderColor:(UIColor *)color
{
self.layer.masksToBounds = YES;
self.layer.cornerRadius = 4.0f;
self.layer.borderWidth = 1.0f;
self.layer.borderColor = color.CGColor;
}
#end
Now when you want to style a button simply import the category and call it like so:
[myButton styleWithBorderColor:[UIColor whiteColor]];
EDIT:
Please see comments... these should be prefixed to avoid confusion with framework methods
Add
self.layer.masksToBounds = YES;
Also if you are creating your button via Nib or Storyboard file initWithFrame method will not be called. In such a case do not forget to place your additional code in awakeFromNib method
- (void)awakeFromNib
{
self.layer.masksToBounds = YES;
self.layer.borderWidth=1.0f;
self.layer.cornerRadius = 4;
self.layer.borderColor=[[UIColor blueColor] CGColor];
}
There is nothing wrong with subclassing UIButton at all.. I suggest maybe you need to set
self.backgroundColor = nil; // or [UIColor clearColor]
self.layer.backgroundColor = desiredBackgroundColor.CGColor;
The backgroundcolor in UIView covers the border on the layer, move the background color to the layer instead to put it behind (and clip it to) the border

Resources