Skip to content

Commit

Permalink
Added tap on the tags and other improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
andreamazz committed Jan 31, 2014
1 parent d83eb71 commit 37715d2
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 35 deletions.
12 changes: 12 additions & 0 deletions AMTagListView.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Pod::Spec.new do |s|
s.name = "AMTagListView"
s.version = "0.2"
s.summary = "UIScrollView subclass that allows to add a list of highly customizable tags."
s.homepage = "https://github.com/andreamazz/AMTagListView"
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { "Andrea Mazzini" => "[email protected]" }
s.source = { :git => "https://github.com/andreamazz/AMTagListView.git", :tag => '0.2' }
s.platform = :ios, '5.0'
s.source_files = 'AMTagListView', '*.{h,m}'
s.requires_arc = true
end
63 changes: 61 additions & 2 deletions AMTagListView/AMTagListView.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,71 @@

#import "AMTagView.h"

@class AMTagView;

typedef void (^AMTagListViewTapHandler)(AMTagView*);

@interface AMTagListView : UIScrollView

@property (nonatomic, assign) float marginX;
@property (nonatomic, assign) float marginY;
/**-----------------------------------------------------------------------------
* @name AMTagListView
* -----------------------------------------------------------------------------
*/

/** Add a new tag
*
* Adds a new tag to the scroll view.
*
* @param text The text that the tag will display
*/
- (void)addTag:(NSString*)text;

/** Add a multiple tags
*
* Adds multiple tags to the scroll view.
*
* @param array An array of strings
*/
- (void)addTags:(NSArray*)array;

/** Remove a tag
*
* Removes a given tag.
*
* @param view A AMTagView instance
*/
- (void)removeTag:(AMTagView*)view;

/** Set a tap handler for the tags
*
* Sets a tap block that will be fired on each tap on a tag
*
* @param tapHandler The handler block
*/
- (void)setTapHandler:(AMTagListViewTapHandler)tapHandler;

/**-----------------------------------------------------------------------------
* @name AMScrollingNavbarViewController Properties
* -----------------------------------------------------------------------------
*/

/** Horizontal margin
*
* Holds the horizontal inner margin of the view.
*/
@property (nonatomic, assign) float marginX;

/** Vertical margin
*
* Holds the vertical inner margin of the view.
*/
@property (nonatomic, assign) float marginY;

/** Tags list
*
* An array holding the current tags objects
*/
@property (nonatomic, strong, readonly) NSMutableArray* tags;


@end
100 changes: 68 additions & 32 deletions AMTagListView/AMTagListView.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

@interface AMTagListView ()

@property (nonatomic, copy) AMTagListViewTapHandler tapHandler;

@end

@implementation AMTagListView
Expand All @@ -18,10 +20,7 @@ - (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Default margins
_marginX = 4;
_marginY = 4;
self.clipsToBounds = YES;
[self setup];
}
return self;
}
Expand All @@ -30,53 +29,83 @@ - (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Default margins
_marginX = 4;
_marginY = 4;
self.clipsToBounds = YES;
[self setup];
}
return self;
}

- (void)setup
{
// Default margins
_marginX = 4;
_marginY = 4;
self.clipsToBounds = YES;
_tags = [@[] mutableCopy];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserverForName:AMTagViewNotification
object:nil
queue:nil
usingBlock:^(NSNotification *notification) {
self.tapHandler(notification.object);
}];
}

- (void)setTapHandler:(AMTagListViewTapHandler)tapHandler
{
_tapHandler = tapHandler;
}

- (void)addTag:(NSString*)text
{
UIFont* font = [[AMTagView appearance] textFont] ? [[AMTagView appearance] textFont] : kDefaultFont;
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: font}];

float padding = [[AMTagView appearance] textPadding] ? [[AMTagView appearance] textPadding] : kDefaultTextPadding;
float tagLength = [[AMTagView appearance] tagLength] ? [[AMTagView appearance] tagLength] : kDefaultTagLength;

size.width = (int)size.width + padding*2 + tagLength;
size.width = (int)size.width + padding * 2 + tagLength;
size.height = (int)size.height + padding;
size.width = MIN(size.width, self.frame.size.width - self.marginX * 2);

AMTagView* tagView = [[AMTagView alloc] initWithFrame:(CGRect){0, 0, size.width, size.height}];
[tagView setupWithText:text];
[self.tags addObject:tagView];

__block float maxY = 0;
__block float maxX = 0;
[self rearrangeTags];
}

- (void)rearrangeTags
{
[self.subviews enumerateObjectsUsingBlock:^(UIView* obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[AMTagView class]]) {
maxY = MAX(maxY, obj.frame.origin.y);
}
[obj removeFromSuperview];
}];

[self.subviews enumerateObjectsUsingBlock:^(UIView* obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[AMTagView class]]) {
if (obj.frame.origin.y == maxY) {
maxX = MAX(maxX, obj.frame.origin.x + obj.frame.size.width);
__block float maxY = 0;
__block float maxX = 0;
__block CGSize size;
[self.tags enumerateObjectsUsingBlock:^(AMTagView* obj, NSUInteger idx, BOOL *stop) {
size = obj.frame.size;
[self.subviews enumerateObjectsUsingBlock:^(UIView* obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[AMTagView class]]) {
maxY = MAX(maxY, obj.frame.origin.y);
}
}];

[self.subviews enumerateObjectsUsingBlock:^(UIView* obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[AMTagView class]]) {
if (obj.frame.origin.y == maxY) {
maxX = MAX(maxX, obj.frame.origin.x + obj.frame.size.width);
}
}
}];

// Go to a new line if the tag won't fit
if (size.width + maxX > (self.frame.size.width - self.marginX)) {
maxY += size.height + self.marginY;
maxX = 0;
}
obj.frame = (CGRect){maxX + self.marginX, maxY, size.width, size.height};
[self addSubview:obj];
}];

// Go to a new line if the tag won't fit
if (size.width + maxX > (self.frame.size.width - self.marginX)) {
maxY += size.height + self.marginY;
maxX = 0;
}

size.width = MIN(size.width, self.frame.size.width - self.marginX * 2);

AMTagView* tagView = [[AMTagView alloc] initWithFrame:(CGRect){maxX + self.marginX, maxY, size.width, size.height}];
[tagView setupWithText:text];
[self addSubview:tagView];

[self setContentSize:(CGSize){self.frame.size.width, maxY + size.height +self.marginY}];
}

Expand All @@ -87,4 +116,11 @@ - (void)addTags:(NSArray*)array
}
}

- (void)removeTag:(AMTagView*)view
{
[view removeFromSuperview];
[self.tags removeObject:view];
[self rearrangeTags];
}

@end
3 changes: 3 additions & 0 deletions AMTagListView/AMTagView.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#define kDefaultTagColor [UIColor redColor]
#define kDefaultInnerTagColor [UIColor colorWithWhite:1 alpha:0.3]

extern NSString * const AMTagViewNotification;

@interface AMTagView : UIView

@property (nonatomic, assign) float radius UI_APPEARANCE_SELECTOR;
Expand All @@ -31,5 +33,6 @@
@property (nonatomic, strong) UIColor *innerTagColor UI_APPEARANCE_SELECTOR;

- (void)setupWithText:(NSString*)text;
- (NSString*)tagText;

@end
18 changes: 17 additions & 1 deletion AMTagListView/AMTagView.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@

#import "AMTagView.h"

NSString * const AMTagViewNotification = @"AMTagViewNotification";

@interface AMTagView ()

@property (nonatomic, strong) UILabel *labelText;
@property (nonatomic, strong) UIButton *button;

@end

Expand All @@ -23,6 +26,7 @@ - (id)initWithFrame:(CGRect)frame
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.labelText = [[UILabel alloc] init];
self.button = [[UIButton alloc] init];
_radius = kDefaultRadius;
_tagLength = kDefaultTagLength;
_holeRadius = kDefaultHoleRadius;
Expand All @@ -33,13 +37,19 @@ - (id)initWithFrame:(CGRect)frame
_tagColor = kDefaultTagColor;
_innerTagColor = kDefaultInnerTagColor;
[self addSubview:self.labelText];
[self addSubview:self.button];
[self.button addTarget:self action:@selector(actionButton:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}

- (void)setupWithText:(NSString*)text
- (void)actionButton:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotification:[[NSNotification alloc] initWithName:AMTagViewNotification object:self userInfo:nil]];
}

- (void)setupWithText:(NSString*)text
{
[self.labelText setText:text];
}

Expand All @@ -53,6 +63,7 @@ - (void)layoutSubviews
self.frame.size.width - self.radius * 2 - self.radius / 2,
self.frame.size.height - self.radius
}];
[self.button setFrame:self.labelText.frame];
[self.labelText setTextColor:self.textColor];
[self.labelText setFont:self.textFont];
}
Expand Down Expand Up @@ -115,4 +126,9 @@ - (void)drawRect:(CGRect)rect
[background fill];
}

- (NSString*)tagText
{
return self.labelText.text;
}

@end
5 changes: 5 additions & 0 deletions TagListViewDemo/TagListViewDemo/AMViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ - (void)viewDidLoad
[self.tagListView addTag:@"hi there"];

[self.view addSubview:self.tagListView];

__weak AMViewController* weakSelf = self;
[self.tagListView setTapHandler:^(AMTagView *view) {
[weakSelf.tagListView removeTag:view];
}];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
Expand Down

0 comments on commit 37715d2

Please sign in to comment.