calimarkus / jdflipnumberview Goto Github PK
View Code? Open in Web Editor NEW[iOS] Animated analog flip numbers like airport/train-station displays (Swift/SwiftUI ready)
License: MIT License
[iOS] Animated analog flip numbers like airport/train-station displays (Swift/SwiftUI ready)
License: MIT License
JDFlipNumberViewImageFactory.m
lines 53 and 96 use [NSBundle mainBundle]
as the bundle from which to load the digit images. This causes trouble when trying to use JDFlipNumberView
as a framework, with Carthage, or in an IB_DESIGNABLE since the bundle for JDFlipNumberView
is not necessarily the same as [NSBundle mainBundle]
.
Unfortunately, the fix isn't as simple as just replacing [NSBundle mainBundle]
with [NSBundle bundleForClass:[self class]]
since the default images JDFlipNumberView.bundle
will be in the JDFlipNumberView
bundle, but any custom images may be in another bundle.
Probably the right solution is to allow the option of passing an NSBundle
object along with the image bundle name. For example, here are a few methods that would get renamed.
- (void)generateImagesFromBundleNamed:(NSString*)bundleName;
becomes
- (void)generateImagesFromImageBundleName:(NSString*)imageBundleName inBundle:(NSBundle*)bundle;
And
- (void)setImageBundleName:(NSString*)imageBundleName;
becomes
- (void)setImageBundleName:(NSString*)imageBundleName inBundle:(NSBundle*)bundle;
If necessary, the old methods could stick around for backwards compatibility. They would just call the new methods with [NSBundle mainBundle]
for the bundle
parameter
Just displays the current time..
Optionally also support custom date/time formats:
I set the date in method initWithTimeIntervalSince1970. The only thing that is coming wrong is the hour.
If the application receive a didReceiveMemoryWarning: the app release all the images and later on load only the default image bundle, a problem if the user changed default bundle to a custom one.
Everything seems ok on emulator.
But in actual machine when number changed there is a slight flickering of old number.
The internal usage of Autoresizing masks leed to a a weird behavior of JDFlipNumberView when using AutoLayout in the iOS Project
i will like the value from 99999 to 1, but the flipview have infinite loop.
- (void)viewDidLoad
{
[self performSelector:@selector(changeCreditValue:) withObject:@"1" afterDelay:3];
}
- (void)setupCreditBar
{
//Credit
self.flipView = [[JDFlipNumberView alloc] initWithDigitCount:5];
self.flipView.value = 99999;
self.flipView.maximumValue = 99999;
// add to view hierarchy and resize
[self.view addSubview: self.flipView];
self.flipView.frame = CGRectMake(190,7,90,50);
}
- (void)changeCreditValue:(NSString *)newCreditValue
{
NSDate *startDate = [NSDate date];
NSLog(@"new Credit %@",newCreditValue);
[self.flipView animateToValue:[newCreditValue intValue] duration:3.5];
}
How to disable flip on JDFlipCLockView.m? There is JDFlipAnimationType that can be set to JDFlipAnimationTypeNone
- (void) animateToValue: (NSInteger) value withDuration: (CGFloat) duration
is limited to the minimum timer speed of 0.001s currently set within JDFlipNumberView.m
.
currently you have "- (void)animateToValue:(NSInteger)newValue duration:(CGFloat)duration;"
it might be nice to add animateToValue for time. Like animateTimeFrom to animateTimeTo in duration
I'm using the JDFlipImageView flipToView Method to animate 2
Views concurrently. One on an iOS 8 Device and one on a connected
Beamer (simply an UIWindow with UIView where an UIImageView is
displayed and flipped, same constellation on the iOS Device).
The animation is invoked first for the Beamer's View and then for the
iOS Device View.
It's quite simple something like:
...
if(self->secondScreen) {
UIImageView* beamerLastImageView = self->newBeamerImageView;
self->newBeamerImageView = [[UIImageView alloc]
initWithImage:self->beamerImage];
}
UIImageView* lastImageView = self->newImageView;
self->newImageView = [[UIImageView alloc] initWithImage:self->newImage];
...
if(self->secondScreen) {
[beamerLastImageView flipToView:self->newBeamerImageView
duration:dur direction:dir completion:^(BOOL finished){ ... }];
}
[lastImageView flipToView:self->newImageView duration:dur
direction:dir completion:^(BOOL finished){ ... }];
The Problem is that shortly before the flip animation an Image appears
on the iOS Device View, but not on the Beamer. It is half the Size
(may be due to the Beamers windows frame being 1/2 of that of the
Devices View) and rotated by 180 degree.
After few hours of reading my code (can't exactly debug the APP while
using a connected display) which is quite short for the animations, I
started reading through the code path invoked by flipToView and it
seems that imageSnapshotAfterScreenUpdates either makes a wrong Image
or somehow mixes things between the 2 screens.
For now I worked around it by exposing the
addFlipViewWithAnimationFromImage and using my own Images directly
from the UIImageViews. This works without Problems.
I couldn't find any Information as to why this Problem occurs.
Include the source file for the images of the flip charts so that changes can be modifyed depending on the project. I would really like letters too.
When changing a number, e.g. 3520 to 9250 every digit should animate on its own to the new number iterating over every digit inbetween.
Means:
3 to 9 (in 6 flips)
5 upwards to 2 (in 7 flips)
2 to 5 (in 3 flips)
0 stays like it is (0 flips)
Working Title: JDClassicFlipNumberView
Send notification when graphics are replaced. And listen to that notification in each flipview to replace the current graphics.
for those of us who load the view from a nib file (initWithCoder)
Hi
thanks for this great library.
Is there any way to add shadow when flipping views? it makes flipping more realistic.
Discussion with MattFoley@dcdbd01
I'm sorry, this is a bit in progress on my fork and didn't have time to fully fix it. The starting issue, an infinite loop, was caused calling something like:
[self.countdownView animateToValue:someValue duration:someDuration completion:^(BOOL finished) {
[self.countdownView animateToValue:someValue duration:someDuration completion:^(BOOL finished) {
if (finished) {
[self doStuff];
}
}];
}];
The first line of animateToValue called [self stopAnimation] would try to call the previous completion block, which executed the second animateToValue, which would hit the [self stopAnimation] again, on and on forever.
You can see in my fork I started to try to fix it but wasn't able to fully fix it before I ran out of time.
My current workaround is this:
[self.countdownView animateToValue:someValue duration:someDuration completion:^(BOOL finished) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.flipNumberView animateToValue:someValue duration:someDuration completion:^(BOOL finished) {
if (finished) {
[self doStuff];
}
}];
});
}];
I believe the timer issue was just a nested block/threading issue as a result of some of the other changes I've made.
CC: @MattFoley
Darken views while flipping to fake shadow.
HI, I'm using Xcode 4.2 because my macbook running Mac 10.6.
I can't run this source on Xcode 4.2. Please help.
Thanks.
I'm seeing an intermittent crash. Here's what it's looks like:
Fatal Exception: CALayerInvalidGeometry
CALayer position contains NaN: [32.5 nan]
Thread : Fatal Exception: CALayerInvalidGeometry
0 CoreFoundation 6495280712 __exceptionPreprocess
1 libobjc.A.dylib 6770999524 objc_exception_throw
2 CoreFoundation 6495280520 -[NSException initWithCoder:]
3 QuartzCore 6563416432 CA::Layer::set_position(CA::Vec2<double> const&, bool)
4 QuartzCore 6563416264 -[CALayer setPosition:]
5 QuartzCore 6563416152 -[CALayer setFrame:]
6 UIKit 6570418116 -[UIView(Geometry) setFrame:]
7 MyApp 4297676208 -[JDFlipNumberDigitView setFrame:] (JDFlipNumberDigitView.m:159)
8 MyApp 4297690220 -[JDFlipNumberView layoutSubviews] (JDFlipNumberView.m:495)
9 UIKit 6570433068 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
10 QuartzCore 6563453332 -[CALayer layoutSublayers]
11 QuartzCore 6563431780 CA::Layer::layout_if_needed(CA::Transaction*)
12 QuartzCore 6563431432 CA::Layer::layout_and_display_if_needed(CA::Transaction*)
13 QuartzCore 6563429384 CA::Context::commit_transaction(CA::Transaction*)
14 QuartzCore 6563428748 CA::Transaction::commit()
15 UIKit 6570441032 _UIApplicationHandleEventQueue
16 CoreFoundation 6494986472 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
17 CoreFoundation 6494983052 __CFRunLoopDoSources0
18 CoreFoundation 6494975036 __CFRunLoopRun
I've gotten this a handful of times on several devices (iPhone 5s, 6, 6s) on both iOS8 and 9.1. It's super intermittent so I haven't been able to reproduce in the debugger.
Seems like the things that affect CALayer
's position are bounds
, anchorPoint
, and possibly transform
. Though I haven't been able to figure out where a division by zero could have happened for any of those. I'll post here if I make any progress in diagnosing this.
I try to change animation direction to up when the number decreased. i hope its useful
in "- (void) animateIntoCurrentDirectionWithDuration: (CGFloat) duration
" changed
if (mCurrentDirection == eFlipDirectionDown) {
// exchange images & setup animation
if (mCurrentState == eFlipStateFirstHalf)
{
// setup first animation half
mImageViewFlip.frame = CGRectMake(0, self.frame.size.height/2.0, self.frame.size.width, self.frame.size.height/2.0);
mImageViewFlip.image = [mBottomImages objectAtIndex: mCurrentValue];
mImageViewBottom.image = [mBottomImages objectAtIndex: nextIndex];
mImageViewTop.image = [mTopImages objectAtIndex: mCurrentValue];
// inform delegate
if ([delegate respondsToSelector: @selector(flipNumberView:willChangeToValue:)]) {
[delegate flipNumberView: self willChangeToValue: nextIndex];
}
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0, 1, 0, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 1, 0, 0)];
animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut];
}
else
{
// setup second animation half
mImageViewFlip.image = [mTopImages objectAtIndex: nextIndex];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-M_PI_2, 1, 0, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0, 1, 0, 0)];
animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
}
}else{
// exchange images & setup animation
if (mCurrentState == eFlipStateFirstHalf)
{
// setup first animation half
mImageViewFlip.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height/2.0);
mImageViewFlip.image = [mTopImages objectAtIndex: mCurrentValue];
mImageViewBottom.image = [mBottomImages objectAtIndex: mCurrentValue];
mImageViewTop.image = [mTopImages objectAtIndex: nextIndex];
// inform delegate
if ([delegate respondsToSelector: @selector(flipNumberView:willChangeToValue:)]) {
[delegate flipNumberView: self willChangeToValue: nextIndex];
}
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0, 1, 0, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-M_PI_2, 1, 0, 0)];
animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
}
else
{
// setup second animation half
mImageViewFlip.image = [mBottomImages objectAtIndex: nextIndex];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 1, 0, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0, 1, 0, 0)];
animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut];
}
}
in "- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
" changed
// update images
if (mCurrentDirection == eFlipDirectionDown) {
mImageViewTop.image = [mTopImages objectAtIndex: mCurrentValue];
}else{
mImageViewBottom.image = [mBottomImages objectAtIndex: mCurrentValue];
}
in "- (void) updateFlipViewFrame
" changed
if (mCurrentDirection == eFlipDirectionDown) {
if (mCurrentState == eFlipStateFirstHalf)
{
mImageViewFlip.layer.anchorPoint = CGPointMake(0.5, 0.0);
mImageViewFlip.frame = mImageViewBottom.frame;
}
else
{
mImageViewFlip.layer.anchorPoint = CGPointMake(0.5, 1.0);
mImageViewFlip.frame = mImageViewTop.frame;
}
}else{
if (mCurrentState == eFlipStateFirstHalf)
{
mImageViewFlip.layer.anchorPoint = CGPointMake(0.5, 1.0);
mImageViewFlip.frame = mImageViewTop.frame;
}
else
{
mImageViewFlip.layer.anchorPoint = CGPointMake(0.5, 0.0);
mImageViewFlip.frame = mImageViewBottom.frame;
}
}
delegate method "flipNumberView: (JDFlipNumberView*)flipNumberView willChangeToValue: (NSUInteger)newValue" cannot be found and not used in JDFlipNumberView.m.
Change setFrame: logic: Place the view in the center of any given frame. Not at the top left.
Use setFrame:allowScaling: if desired.
There seems to be a problem with the countdown:
When it gets reached (0 days, 0 hours, 0 minutes, 0 seconds) it restarts to count down with 1 minute left. After that it restarts with 1 hour left.
The correct behavior would be IMHO to freeze the countdown when it reaches "0".
This value should be configurable someplace in the component to enhance the rendering.
For instance with my custom design, the views are too close one from each other, I would like to set JDFlipViewRelativeMargin to something like 30%.
Currently the classes do not use ARC.
Hi!
It would be great if your library will support NSNumberFormatter (for example, in our project we're using groupSeparator for NSNumberFormatter, and our numbers looks like "1 000 000", not "1000000")
Thanks!
Flip any image you like!
I tried updating to the latest version with "pod update" and I'm getting the following error:
[!] Pod::Executable fetch origin tags/pod-2.0.6 2>&1
fatal: Couldn't find remote ref tags/pod-2.0.6
fatal: The remote end hung up unexpectedly
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.