A have an issue with UIProgressView value. I'm trying to embed ProgressView into Table View cell.
This code works - ProgressView fills it's cell. But there's problem with filling ProgressView itself - it's value rounds to 0.5 (e.g. if value is 0.2 then progressView is not filled, if 0.8 - then it filled 100%, see the image bellow)
Can anyone help with making things right?
CGAffineTransform transform = CGAffineTransformMakeScale(cell.frame.size.width, cell.frame.size.height);
cell.attendanceProgress.transform = transform;
[cell.attendanceProgress setAlpha:0.5];
[cell setUserInteractionEnabled:NO];
float progr = (float)attended / (float)classes.count;
if (classes.count == 0) { progr = 0; }
[cell.attendanceProgress setProgress:progr];
Use
cell.attendanceProgress.frame=CGRectMake(0,0,cell.attendanceProgress.frame.size.width, cell.frame.size.height);
CATransform3D transform = CATransform3DScale(cell.attendanceProgress.layer.transform, 1.0f,cell.frame.size.height, 1.0f);
cell.attendanceProgress.layer.transform = transform;
Make sure set frame before transform.
Related
I am rotating my view using UIRotationGestureRecognizer, But after taht when i want to increase or decrease my view size using UISlider. My view angle first setting to its initial state the it is increasing or decreasing my view size. My requirement is if my view rotated by some angle it still rotated after performing UISlider operation.
My Rotation Gesture Code:
gesture.view.transform = CGAffineTransformRotate(gesture.view.transform, gesture.rotation);
gesture.rotation = 0.0;
My UISlider Code
myView.transform = CGAffineTransformScale(CGAffineTransformIdentity, slider.value * 2, slider.value * 2);
If you want to keep the rotation, you'll have to store that CGAffineTransform and then concatinate it with your scale transform. You can use CGAffineTransformConcat for that (https://developer.apple.com/documentation/coregraphics/1455996-cgaffinetransformconcat?language=objc). Something like this:
CGAffineTransform scale = CGAffineTransformScale(CGAffineTransformIdentity, slider.value * 2, slider.value * 2);
myView.transform = CGAffineTransformConcat(savedRotationTransform, scale);
where savedRotationTransform is CGAffineTransformRotate(gesture.view.transform, gesture.rotation); saved from that other step. It might be easier to encapsulate the whole thing in your UIView subclass.
I'm using https://bitbucket.org/javieralonso/japanoview to create 360 degree panoramic views for an iOS app. What I want to do now is split the view into 2 identical views and use one input for both of them and be able to use it inside google cardboard. Please help. Thank you.
I once used this as inspiration to do the same thing. https://github.com/nicklockwood/ReflectionView
Set reflection to dynamic. View is mirrored but you can fix if by removing values smaller than zero.
Also translate method to make it next to each other. Remove gradient drawing and you are set to go :)
In storyboard add view you want to duplicate on left half of screen and set its Class to ReflectionView.
Reflection view implementation changes will look like this:
- (void)update {
//update instances
CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
layer.shouldRasterize = YES;
layer.rasterizationScale = [UIScreen mainScreen].scale;
layer.instanceCount = 2;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, layer.bounds.size.width + _reflectionGap, 0.0f, 0.0f);
transform = CATransform3DScale(transform, 1.0f, 1.0f, 0.0f);
layer.instanceTransform = transform;
layer.instanceAlphaOffset = 1.0f;
}
- (void)setUp {
//set default properties
_reflectionGap = 0.0f;
_dynamic = YES;
//update reflection
[self setNeedsLayout];
}
Hey guys I've been trying to use two UISliders to manipulate one UIImageView. One slider to scale the image and one to rotate it. However, when I switch from one slider to the other it resets the previous rotation. (So if I scale the image to say 125x125 when its normally 100x100 and then go to use the other slider to rotate the image, it rotates it but changes its size back to 100x100 and vice versa). So anyways, Ive tried using CGAffineTransformConcat to combine the two transformations, Ive tried setting the frame of the ImageView after every transformation, I've tried deleting and readding the imageView to _myArray to "save" it, and I briefly tried using anchorpoints but all with no luck. So my question is, what am I doing wrong??? I feel like my code should work and each action shouldn't reset my UIImageView but I have no idea why it won't.
- (IBAction)scaleImage:(UISlider *)sender {
NSLog(#"ScaleImage Called");
UIImageView *selectedImage = [_myArray objectAtIndex:0];
CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, sender.value, sender.value);
selectedImage.transform = transform;
_scaleValue = sender.value;
//_width = selectedImage.frame.size.width
//_height = selectedImage.frame.size.height
_sizeLabel.text = [NSString stringWithFormat:#"%d", _scaleValue];
}
- (IBAction)rotateImage:(UISlider *)sender {
UIImageView *selectedImage = [_myArray objectAtIndex:0];
//selectedImage.frame = CGRectMake(selectedImage.frame.origin.x, selectedImage.frame.origin.y, _width, _height);
selectedImage.transform = CGAffineTransformMakeRotation(sender.value * 2*M_PI / sender.maximumValue);
_rotationLabel.text = [NSString stringWithFormat:#"%d", _rotationValue];
_rotationValue = sender.value;
}
Does anyone know why each method resets the others previous transformation.
If you look at your code, you will notice that you are explicitly setting the transform to the new value across the Identity transform.
CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, sender.value, sender.value);
What you will want to do is apply the two together... you could save a rotation transform and a scale transform as properties and the IBActions would update those and then set the transform as a concatenation of the two.
So, the scale would look like:
self.scaleValue = sender.value;
And the rotation would look like:
self.rotateValue = sender.value * 2*M_PI / sender.maximumValue;
And you would have another method called transform
-(void)transform
{
CGAffineTransform fullTransform = CGAffineTransformMakeRotation(self.rotateValue);
CGAffineTransformScale(fullTransform, self.scaleValue, self.scaleValue);
UIImageView *selectedImage = [_myArray objectAtIndex:0];
selectedImage.transform = fullTransform;
}
You would then call that transform method in the IBAction calls at the end instead of trying to set the transforms separately
I'm trying to create a "page flip effect" using UIView instead of CALayer due to a project limitation. This requires flipping 1 UIView 180 degrees and essentially "sticking it" to the back of the other UIView. You then rotate the two UIViews simultaneously by rotating the superview in 3D space.
I'm trying to port AFKPageFlipper's "initFlip" method to use UIView instead of UIImage.
Below is a snippet of my attempt to port it. The initial page flip works, but the "front layer" in the code doesn't seem to show up. As if I"m not able to see the backend of the page. When I'm flipping the page, the animation is initially correct (back layer is fine), but then the other side of the page (front layer), I see the inverted view of the first page (backLayer).
Any help would be awesome!
flipAnimationLayer = [[UIView alloc] init];
flipAnimationLayer.layer.anchorPoint = CGPointMake(1.0, 0.5);
flipAnimationLayer.layer.frame = rect;
[self addSubview:flipAnimationLayer];
UIView *backLayer;
UIView *frontLayer;
if (flipDirection == AFKPageFlipperDirectionRight)
{
backLayer = currentViewSnap2;
backLayer.layer.contentsGravity = kCAGravityLeft;
frontLayer = nextViewSnap2;
frontLayer.layer.contentsGravity = kCAGravityRight;
}else
{
backLayer = nextViewSnap2;
backLayer.layer.contentsGravity = kCAGravityLeft;
frontLayer= currentViewSnap2;
frontLayer.layer.contentsGravity = kCAGravityRight;
}
backLayer.frame = flipAnimationLayer.bounds;
backLayer.layer.doubleSided = NO;
backLayer.clipsToBounds = YES;
[flipAnimationLayer addSubview:backLayer];
frontLayer.frame = flipAnimationLayer.bounds;
frontLayer.layer.doubleSided = NO;
frontLayer.clipsToBounds = YES;
frontLayer.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);
[flipAnimationLayer addSubview:frontLayer];
if (flipDirection == AFKPageFlipperDirectionRight)
{
CATransform3D transform = CATransform3DMakeRotation(0.0, 0.0, 1.0, 0.0);
transform.m34 = 1.0f / 2500.0f;
flipAnimationLayer.layer.transform = transform;
currentAngle = startFlipAngle = 0;
endFlipAngle = -M_PI;
} else
{
CATransform3D transform = CATransform3DMakeRotation(-M_PI / 1.1, 0.0, 1.0, 0.0);
transform.m34 = 1.0f / 2500.0f;
flipAnimationLayer.layer.transform = transform;
currentAngle = startFlipAngle = -M_PI;
endFlipAngle = 0;
}
Your code is rotating layers, not views. That's fine.
I would not expect the code you posted to animate, since a layer's backing view doesn't do implicit animation, You could make it animate by using a CABasicAnimation. Or, you could create layers for your front and back views and attach them as sublayers of your view's layers. If you do that than manipulating the transform on the layers will use implicit animations.
What I've done to create my own font-to-back flip as you describe is to fake it.
I animate in 2 steps: First from zero degrees (flat) to 90 degrees (where the layers become invisible.) At that moment I hide the first layer and make the second layer visible, rotated 90 degrees the other way, and then rotate the other layer back to zero. This creates the same visual effect as showing the back face of the rotation.
If you use implicit layer animation to do this you'll need to put the changes to the transform inside a CATransaction block and set the animation timing to linear, or use ease-in for the first half and ease-out for the second half. That's because animations default to ease-in,ease-out timing, and the first animation to 90 degrees will slow down at the end, and then the second 90 degree animation will ease in.
I have 1 view, in this view I have 1 UIImageView and UILabel, when I rotate my view half of view disappear.
This is my code
viewToAnimate is the view cointains image and label.
CATransform3D _3Dt = CATransform3DRotate(viewToAnimate.layer.transform, DEGREES_TO_RADIANS(beginValue), 0.0, 1.0, 0);
_3Dt.m34 = 1.0 / -300;
viewToAnimate.layer.transform = _3Dt;
CATransform3D _scale;
if (needZoom) {
_scale = CATransform3DScale(viewToAnimate.layer.transform , 1+scale, 1+scale, 1+scale);
if (_scale.m11 > 1) {
_scale.m11 = 1;
_scale.m22 = 1;
_scale.m33 = 1;
}
}
else {
_scale = CATransform3DScale(viewToAnimate.layer.transform , 1-scale, 1-scale, 1-scale);
}
viewToAnimate.layer.transform = _scale;
//viewToAnimate.layer.zPosition = sin(DEGREES_TO_RADIANS(beginValue)*MOSAIC_WIDTH)+1;
What is the value of DEGREES_TO_RADIANS? Is it by any chance M_PI/2?
Your code tells that you are rotating around y-axis. See last 3 parameters in first line:
0.0, 1.0, 0
If you are supplying this then this is expected behavior - consider a plane facing you and imagine it rotate around y-axis by +/- 90 degrees, it will definitely disappear.
As mentioned in Diego's comment on the other answer this can be caused by zPosition issues. Make your view above all the others by setting it's zPosition to a higher value.