Communication between objects - C4Framework - ios

I'm working with the alpha release of C4 and I'm trying to send messages between objects but i cant make it work. Im trying with a really simple example but i cant make it work... I've tried this:
[ashape listenFor:#"touch" from:anothershape andRunMethod:#"receive"];
but I dont get any messages or nothing...
this is what i have:
#import "MyShape.h"
#implementation MyShape
-(void)receive {
C4Log(#"this button");
}
#end

I see one main problem with the code you posted.
By default, all visible objects in C4 post a touchesBegan notification when they are tapped. In your code you are listening for #"touch" whereas #"touchesBegan" is what you should be listening for.
The changing color method is easy to implement... In your MyShape.m file, you can use a method like:
-(void)changeColor {
CGFloat red = RGBToFloat([C4Math randomInt:255]);
CGFloat green = RGBToFloat([C4Math randomInt:255]);
CGFloat blue = RGBToFloat([C4Math randomInt:255]);
self.fillColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
}
In order to get things working nicely, your C4WorkSpace.m should look like:
#import "C4WorkSpace.h"
#import "MyShape.h"
#implementation C4WorkSpace {
MyShape *s1, *s2;
}
-(void)setup {
s1 = [MyShape new];
s2 = [MyShape new];
[s1 rect:CGRectMake(100, 100, 100, 100)];
[s2 rect:CGRectMake(300, 100, 100, 100)];
[s1 listenFor:#"touchesBegan" fromObject:s2 andRunMethod:#"changeColor"];
[s2 listenFor:#"touchesBegan" fromObject:s1 andRunMethod:#"changeColor"];
[self.canvas addShape:s1];
[self.canvas addShape:s2];
}
#end

Related

Create circle button in iOS7 without images

I would like to recreate the circular buttons found in the Clock app in iOS7. The buttons are basically circles with different appearance depending on the button states (green border, red border, grey fill).
I could of course achieve this using a simple UIButton with images for the different states.
However I am looking for a solution which draws the circle programmatically, so I can easily change radius, stroke width, etc.
As far as I can see UIButton only allows me to define an UIImage for each state, so I cannot modify the layers per state directly (e.g. provide a layer with cornerRadius). Is there another way?
Creating a custom button may be helpful.
in the .h file;
#import <UIKit/UIKit.h>
#interface CircleLineButton : UIButton
- (void)drawCircleButton:(UIColor *)color;
#end
in the .m file;
#import "CircleLineButton.h"
#interface CircleLineButton ()
#property (nonatomic, strong) CAShapeLayer *circleLayer;
#property (nonatomic, strong) UIColor *color;
#end
#implementation CircleLineButton
- (void)drawCircleButton:(UIColor *)color
{
self.color = color;
[self setTitleColor:color forState:UIControlStateNormal];
self.circleLayer = [CAShapeLayer layer];
[self.circleLayer setBounds:CGRectMake(0.0f, 0.0f, [self bounds].size.width,
[self bounds].size.height)];
[self.circleLayer setPosition:CGPointMake(CGRectGetMidX([self bounds]),CGRectGetMidY([self bounds]))];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
[self.circleLayer setPath:[path CGPath]];
[self.circleLayer setStrokeColor:[color CGColor]];
[self.circleLayer setLineWidth:2.0f];
[self.circleLayer setFillColor:[[UIColor clearColor] CGColor]];
[[self layer] addSublayer:self.circleLayer];
}
- (void)setHighlighted:(BOOL)highlighted
{
if (highlighted)
{
self.titleLabel.textColor = [UIColor whiteColor];
[self.circleLayer setFillColor:self.color.CGColor];
}
else
{
[self.circleLayer setFillColor:[UIColor clearColor].CGColor];
self.titleLabel.textColor = self.color;
}
}
#end
And in the view controller, call [self.myCircleButton drawCircleButton:[UIColor myColor]]
There are lot of ways you could accomplish this, for example:
Use CAShapedLayer
Subclass UIView and use the drawRect: method to draw a circle
Just have a square UIView and use the layer.cornerRadius
property.
Depending on your needs, something as simple as creating normal UIButton and calling
myButton.layer.cornerRadius = myButton.bounds.size.width / 2.0;
could work (you'll need to include the Quartz Framework)
The pattern I've used to achieve this kind of thing is:
Subclass UIButton and implement drawRect to draw the button as you want, customising colours based on the selected and highlighted properties of the button.
Then override setSelected and setHighlighted to force redraws like so:
-(void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}
Add this code
imagePreview.layer.cornerRadius = (imagePreview.bounds.size.height/2);
where imagePreview is UIview/UIimageview/UIButton
don't forget to add
#import <QuartzCore/QuartzCore.h>
Solution with a swift Extension :
extension UIView{
func asCircle(){
self.layer.cornerRadius = self.frame.size.width / 2;
self.layer.masksToBounds = true
}
}
Just call
myView.asCircle()
Can work with any type of view, not only a button
You can use this control, it's subclass from UIButton.
https://github.com/alvaromb/AMBCircularButton
I think it work good.
override func viewDidLoad() {
super.viewDidLoad()
var button = UIButton.buttonWithType(.Custom) as UIButton
button.frame = CGRectMake(160, 100, 50, 50)
button.layer.cornerRadius = 0.5 * button.bounds.size.width
button.setImage(UIImage(named:"thumbsUp.png"), forState: .Normal)
button.addTarget(self, action: "thumbsUpButtonPressed", forControlEvents: .TouchUpInside)
view.addSubview(button)
}
func thumbsUpButtonPressed() {
println("thumbs up button pressed")
}
In storyboard, Make square UIButton (eg. 100 * 100 )
Link outlet (eg. #property (Strong, nonatomic) UIButton IBOutlet * myButton; )
In your code write this:
self.myButton.layer.cornerRadius = 50;
// 50 is half of square's length of one side.

iOS: Color-changing circle button

I'm trying to make a button that will show/hide a color-selection slider. That's the easy part.
What I am not sure how to do is to make the button be a circle with an outline (say black) and the fill be the color shown in the slider. As the user moves the slider, the color of the circle should change accordingly.
I am new to iOS development, so probably I am approaching this all wrong. I would really appreciate any ideas even they are completely different from what I have here.
I started to approach this with a subclass using QuartzCore layers, and the result is decent, but there are issues/things that bother me:
For some reason I get no highlight state when pressing the button
It's obviously odd to use rounded corners to achieve a circle
Unfortunately, it seems at the point were I draw the layers, the button is not laid out yet so I have had to hardcode the radius instead of making it based on the button size.
So, yeah I hardly think this approach is ideal. I will greatly appreciate any and all help. Thank you!
#import "ColorPickerButton.h"
#implementation ColorPickerButton
#pragma mark - UIButton Overrides
+ (ColorPickerButton *)buttonWithType:(UIButtonType)buttonType
{
return [super buttonWithType:UIButtonTypeCustom];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
r = 0.3;
g = 0.6;
b = 0.9;
[self drawOutline];
[self drawColor];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)layoutSubviews
{
_outlineLayer.frame = CGRectInset(self.bounds, 5, 5);
_colorLayer.frame = CGRectInset(self.bounds, 5+_outlineLayer.borderWidth, 5+_outlineLayer.borderWidth);
[super layoutSubviews];
}
#pragma mark - Layer setters
- (void)drawOutline
{
if (!_outlineLayer)
{
_outlineLayer = [CALayer layer];
_outlineLayer.cornerRadius = 20.0;
_outlineLayer.borderWidth = 3;
_outlineLayer.borderColor = [[UIColor colorWithRed:170.0/255.0 green:170.0/255.0 blue:170.0/255.0 alpha:1.0] CGColor];
_outlineLayer.opacity = 0.6;
[self.layer insertSublayer:_outlineLayer atIndex:1];
}
}
- (void)drawColor
{
if (!_colorLayer)
{
_colorLayer = [CALayer layer];
}
_colorLayer.cornerRadius = 16.0;
_colorLayer.backgroundColor = [[UIColor colorWithRed:r green:g blue:b alpha:1.0] CGColor];
_colorLayer.opacity = 1.0;
[self.layer insertSublayer:_colorLayer atIndex:2];
}
- (void)changeColorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue
{
r = red;
g = green;
b = blue;
[self drawColor];
}
#end
We do this in our app. We use the CALayer on the button and add rounded corners 1/2 the size of the component width. We add a border to the button and then set the button background color to achieve the 'fill' color. Works well.

iOS CAEmitterCell firework effect

I'm wanna create an effect like firework. I know that I can use for it CAEmitterCell. I tried to download few examples, but I still in progress with this feature in iOS 5.0
Anybody know good tutorial how to create firework effect using CAEmitterCell?
I need to create something like below:
All particles are going from the center (red circle) in direction to green circles. Red circle this is initial point that will have some CGPoint value.
I have found this solution:
it's how DWFParticleView.h file looks
#import <UIKit/UIKit.h>
#interface DWFParticleView : UIView
#property (nonatomic) CGFloat time;
-(void)configurateEmmiter;
-(void)setEmitterPositionFromTouch: (UITouch*)t;
-(void)setIsEmitting:(BOOL)isEmitting andPoint:(CGPoint)point;
#end
this is how looks DWFParticleView.m
#import "DWFParticleView.h"
#import <QuartzCore/QuartzCore.h>
#implementation DWFParticleView
{
CAEmitterLayer* fireEmitter; //1
}
-(void)configurateEmmiter
{
//set ref to the layer
fireEmitter = (CAEmitterLayer*)self.layer; //2
//configure the emitter layer
fireEmitter.emitterPosition = CGPointMake(50, 50);
fireEmitter.emitterSize = CGSizeMake(5, 5);
CAEmitterCell* fire = [CAEmitterCell emitterCell];
fire.birthRate = 0;
fire.lifetime = 2.0;
fire.lifetimeRange = 0.5;
//fire.color = [[UIColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:0.6] CGColor];
fire.contents = (id)[[UIImage imageNamed:#"star_icon.png"] CGImage];
[fire setName:#"fire"];
fire.velocity = 80;
fire.velocityRange = 20;
fire.emissionRange = M_PI * 2.0f;
fire.scaleSpeed = 0.1;
fire.spin = 0.5;
//add the cell to the layer and we're done
fireEmitter.emitterCells = [NSArray arrayWithObject:fire];
fireEmitter.renderMode = kCAEmitterLayerAdditive;
}
+ (Class) layerClass {
return [CAEmitterLayer class];
}
-(void)setEmitterPositionFromTouch: (UITouch*)t
{
//change the emitter's position
fireEmitter.emitterPosition = [t locationInView:self];
}
-(void)setIsEmitting:(BOOL)isEmitting andPoint:(CGPoint)point
{
fireEmitter.emitterPosition = point;
//turn on/off the emitting of particles
[fireEmitter setValue:[NSNumber numberWithInt:isEmitting?50:0]
forKeyPath:#"emitterCells.fire.birthRate"];
[self performSelector:#selector(decayStep) withObject:nil afterDelay:self.time];
}
- (void)decayStep {
[fireEmitter setValue:[NSNumber numberWithInt:0]
forKeyPath:#"emitterCells.fire.birthRate"];
}
#end
this is method one tap on screen for example that shows our effect
- (void)tap {
DWFParticleView *fireView = [[DWFParticleView alloc] init];
fireView.time = 0.3;
[fireView setUserInteractionEnabled:NO];
[fireView configurateEmmiter];
[fireView setFrame:CGRectMake(0, 0, 0, 0)];
[fireView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:fireView];
}
the material I have found here: ray

Artifacts when animating shapes in C4 - c4framework

When animating a shape in C4 the undefined preset characteristics of the shape, such as line width and fillcolour, also animate. Is there a work around or solution to this problem?
C4Shapes are setup to use the default colors C4Red (for the strokeColor) and C4Blue (for the fillColor). Also, the default animationDuration is set to 0.25 seconds.
Technically, what's happening, is the C4Shape is constructing itself with C4Red / C4Blue colors and then initiates an animation from those to any new colors as soon as it hits the canvas.
To get around these, and to generate your own settings you can subclass C4Shape and add the coloring / timing / other property changes to your class's own init method.
In the implementation (.m file) of a MyShape class I have:
#implementation MyShape
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self != nil) {
self.animationDuration = 0.0f;
self.fillColor = [UIColor purpleColor];
self.strokeColor = [UIColor greenColor];
}
return self;
}
#end
... and my C4WorkSpace.m looks like this:
#import "C4WorkSpace.h"
#import "MyShape.h"
#implementation C4WorkSpace
-(void)setup {
MyShape *ms = [MyShape new];
[ms ellipse:CGRectMake(100, 100, 100, 100)];
[self.canvas addShape:ms];
}
#end
I know this is a bit crude at the moment, but we haven't worked through setting the default colors before the object hits the canvas.

ios bar that changes colors while loading

I am currently working on a project of my own and I would like to implement a custom loading control.
It's pretty much what you can find in the app Amen. The colored bar appears only when the app is loading content from the server.
Any tips will be much appreciated. Thanks.
Here are some images to make it more clear
The "hard" part will be writing a UIView subclass that will handle drawing the colors. You'll want to override the drawRect: method and figure out how to know the progress (or will it just "auto-increment"?) and draw/fill in based on that. Then, you can simply add a UIView in Interface Builder, change the Class type of the view, size it appropriately and off you go!
The "easy" part is that when you want the view to not be visible, you can do one of a number of things:
Move the view off-screen by changing its frame property. (This can be "instantaneous" or animated.)
Set the view invisible by changing its hidden property. (You can animate this, too!)
Get rid of the view entirely by using [barView removeFromSuperview].
Update/Edit
For the actual drawing, try this (done quickly and not tested, so YMMV):
// ColorProgressBar.h
#import <UIKit/UIKit.h>
#interface ColorProgressBar : UIView {
float colorWidth;
float progressPercent;
NSMutableArray *colors;
}
#property (assign, nonatomic) float colorWidth;
#property (assign, nonatomic) float progressPercent;
#property (strong, nonatomic) NSMutableArray *colors;
#end
// ColorProgressBar.m
#import "ColorProgressBar.h"
#implementation ColorProgressBar
#synthesize colors;
#synthesize colorWidth;
#synthesize progressPercent;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Make the color array to use (this is spelled out for clarity)
[self setColors:[NSMutableArray array]];
[[self colors] addObject:[UIColor redColor]];
[[self colors] addObject:[UIColor orangeColor]];
[[self colors] addObject:[UIColor yellowColor]];
[[self colors] addObject:[UIColor greenColor]];
[[self colors] addObject:[UIColor blueColor]];
[[self colors] addObject:[UIColor purpleColor]];
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGFloat left = 0;
CGRect drawBox = CGRectZero;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextClearRect(ctx, rect);
int colorIndex = -1;
// Draw each color block from left to right, switching to the next color each time
do {
colorIndex = colorIndex + 1;
if (colorIndex >= [[self colors] count]) colorIndex = 0;
[(UIColor *)[[self colors] objectAtIndex:colorIndex] setFill];
drawBox = CGRectMake(left, 0, [self colorWidth], rect.size.height);
CGContextFillRect(ctx, drawBox);
} while (left < rect.size.width);
// Figure out where the "faded/empty" part should start
left = [self progressPercent] * rect.size.width;
drawBox = CGRectMake(left, 0, rect.size.width - left, rect.size.height);
[[UIColor colorWithWhite:1.0 alpha:0.5] setFill];
CGContextFillRect(ctx, drawBox);
}
#end
With this code, you could use this UIView subclass and each time you wanted to update your progress, you would simply set your progressPercent (it's a float with a designed range from 0.00 to 1.00) and call [myView setNeedsDisplay]. That should be it! ;-)

Resources