I created a custom slider with a uiview class ... everything works fine but I just have a problem ...
in my view controller implements the Custom Slider class this way
Main ViewController
#pragma mark SMALL STATS
-(KPStatsSlider *)statsSlider {
if (!_statsSlider) {
_statsSlider = [[KPStatsSlider alloc] init];
_statsSlider.minimumValue = 18;
_statsSlider.maximumValue = 30;
_statsSlider.currentValue = 12;
_statsSlider.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.statsSlider];
[self.statsSlider.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:115].active = YES;
[self.statsSlider.rightAnchor constraintEqualToAnchor:self.view.rightAnchor constant:0].active = YES;
[self.statsSlider.heightAnchor constraintEqualToConstant:70].active = YES;
[self.statsSlider.leftAnchor constraintEqualToAnchor:self.view.centerXAnchor constant:0].active = YES;
}
return _statsSlider;
}
as you can see, I can assign the value:
Current /
Minimum /
Maximum
In my personalized UIView I implemented this feature to prevent the CurrentValue value being smaller than MinimumValue but I can not get it running can you help me with this?
Custom Slider UIView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
[self defaultValue];
[self setupStatsTitle];
[self trackLine];
if (self.currentValue <= self.minimumValue) {
self.currentValue = self.minimumValue;
}
}
return self;
}
Seems like you want
if (self.currentValue <= self.minimumValue) {
self.currentValue = self.minimumValue;
}
In the setter of currentValue. For example:
- (void)setCurrentValue:(CGFloat)currentValue {
_currentValue = currentValue;
if (_currentValue < self.minimumValue) {
_currentValue = self.minimumValue;
}
if (_currentValue > self.maximumValue) {
_currentValue = self.maximumValue
}
}
Your code currently only checks when the slider is initialized, but not if currentValue is set later.
In general, I prefer to access an instance variable directly if I’m in that instance variable’s setter/getter to avoid confusion and possible infinite recursion, but your code as written is okay.
Related
I try to implement side bar menu. I already have done it with standard UIView animations, but now i want to add some feelings to it. I decided to use UIViewDynamics. I noticed that, after main view frame changed, it is necessary to recreate UIViewAnimator and all behaviors.
I usually use layoutSubviews view's method. But in that case, my controller inherit UINavigationController and i couldn't override its view, so i worked with controller life cycle methods.
To avoid unexpected result, first i remove all animator behaviors in viewWillLayoutSubviews method. After that, at end of viewDidLayoutSubviews I create an animator and behaviors (gravity, item, push, collision).
That works fine, but when layoutSubviews triggered, it is some lags (looks like low fps).
Some code:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (_animator) {
[_animator removeAllBehaviors];
_animator = nil;
}
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self configSubviewFrames];
[self configAnimator];
}
- (void)configSubviewFrames
{
CGFloat offset = [UIApplication sharedApplication].isStatusBarHidden ? 0 : _statusBarHeight;
CGRect drawerFrame, protectionFrame, unusedFrame;
CGRectDivide(self.view.frame, &drawerFrame, &unusedFrame, _drawerWidth, CGRectMinXEdge);
protectionFrame= self.view.frame;
if (!_isMenuShown) {
drawerFrame.origin.x -= _drawerWidth;
}
drawerFrame.origin.y += offset;
drawerFrame.size.height -= offset;
protectionFrame.origin.y += offset;
protectionFrame.size.height -= offset;
_drawerView.frame = drawerFrame;
_protectionView.frame = protectionFrame;
}
- (void)configAnimator
{
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
_collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[_drawerView]];
_itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:#[_drawerView]];
_gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[_drawerView]];
_pushBehavior = [[UIPushBehavior alloc] initWithItems:#[_drawerView] mode:UIPushBehaviorModeInstantaneous];
_itemBehavior.allowsRotation = NO;
_itemBehavior.elasticity = kDrawerElacity;
_gravityBehavior.gravityDirection = CGVectorMake(_isMenuShown ? 1.0f : -1.0f, 0.0f);
_pushBehavior.magnitude = 0.0f;
_pushBehavior.angle = 0.0f;
_collisionBehavior.collisionDelegate = self;
[_collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(0, - _drawerWidth, 0, self.view.frame.size.width - _drawerWidth)];
[self addInititalBihaviors];
}
- (void)addInititalBihaviors
{
[_animator addBehavior:_collisionBehavior];
[_animator addBehavior:_pushBehavior];
[_animator addBehavior:_gravityBehavior];
[_animator addBehavior:_itemBehavior];
}
Hope you will help and feel free to ask any related questions.
Thanks you.
App consume 9-12 % cpu on screen rotate.
P.S.: I already tried to move animator and behaviors creation into separated thread, but:
Working with view in background thread - bad idea
It just didn't help
I am using table view with dynamic height.
-(void)ShowTblRoomType
{
// [self.tableView_roomType setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.tableView_roomType setFrame:CGRectMake(self.tableView_roomType.frame.origin.x, self.tableView_roomType.frame.origin.y, self.tableView_roomType.frame.size.width, self.tableView_roomType.rowHeight*self.roomtypeDetails.count)];
self.tableView_roomType.hidden = NO;
//set shadow to uitableview........
self.tableView_roomType.layer.masksToBounds = NO;
self.tableView_roomType.layer.cornerRadius = 8; // if you like rounded corners
self.tableView_roomType.layer.shadowOffset = CGSizeMake(-15, 20);
self.tableView_roomType.layer.shadowRadius = 3;
self.tableView_roomType.layer.shadowOpacity = 0.5;
}
From here I am calling this method
- (IBAction)showRoomTypeDetails:(id)sender
{
if(self.tableView_roomType.hidden == NO){
self.tableView_roomType.hidden = YES;
}else
{
[self ShowTblRoomType];
}
// [self.view_reservation bringSubviewToFront:self.tableView_roomType];
}
it works on below ios 8 but dosn't work on ios8.
on ios8 it shows only one cell.
Appreciate for help
I was trying to figure out how to get a negative value of the slider when it goes back.
When I slide from left to right it returns a positive value. I need it to return a negative value when it goes back (from right to left).
In other words, how could I detect that the slider is going back?
self.borderSlider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
self.borderSlider.center = CGPointMake(self.view.centerX, SCREEN_WIDTH / 2);
self.borderSlider.minimumValue = 0.0f;
self.borderSlider.maximumValue = 100.0f;
self.borderSlider.tintColor = [UIColor grayColor];
[self.borderSlider addTarget:self action:#selector(borderSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
A simple example expressing what #rmaddy already stated in his comment:
#implementation YourClass {
float _sliderValue;
}
- (void)borderSliderValueChanged:(UISlider *)slider {
float currentValue = slider.value;
if (currentValue > _sliderValue) {
// right
} else if (currentValue < _sliderValue) {
// left
}
_sliderValue = currentValue;
}
#end
I had the same problem so I've developed it, check this repo: Repo
slider?.amplitude = 50
slider?.sliderDidChange = { [weak slider] value in
if value > 10 {
slider?.activeColor = .blue
} else if value < 0 {
slider?.activeColor = .red
} else {
slider?.activeColor = .lightGray
}
}
I've created this custom UIView named RoundView:
#import <QuartzCore/QuartzCore.h>
#implementation RoundedView
+(UIColor *)grayUIColor {
return [UIColor colorWithRed:161.0/255.0 green:157.0/255.0 blue:164.0/255.0 alpha:1.0];
}
+(UIColor *)darkBlueUIColor {
return [UIColor colorWithRed:86.0/255.0 green:88.0/255.0 blue:87.0/255.0 alpha:1];
}
+(UIColor *)greenUIColor {
return [UIColor colorWithRed:51.0/255.0 green:141.0/255.0 blue:130.0/255.0 alpha:1];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self)
{
//add pico icon as default image
_defaultImage = [UIImage imageNamed:#"actionBar_pico_icon"];
_isCreated = NO;
}
return self;
}
-(UIView*)createRoundViewWithBorder:(UIColor*)borderColor andPaddingColor:(UIColor*)paddingColor{
_borderColor = borderColor;
_paddingBackgroundColor = paddingColor;
[self setViewAppearance];
[self addImageToView];
_isCreated = YES;
return self;
}
/**
Set the current view appearance
*/
-(void) setViewAppearance {
self.layer.borderWidth = 1.5;
self.layer.borderColor = [_borderColor CGColor];
self.backgroundColor = _paddingBackgroundColor;
}
-(void) addImageToView {
CGRect frame = CGRectMake(0, 0, self.frame.size.width - 5, self.frame.size.height - 5);
_imageView = [[UIImageView alloc] initWithFrame:frame];
//calculate center x
float x = (self.frame.size.width - _imageView.frame.size.width) / 2;
//calculate center y
float y = (self.frame.size.height - _imageView.frame.size.height) / 2;
//create new frame
frame = CGRectMake(x, y, _imageView.frame.size.width, _imageView.frame.size.height);
_imageView.image = _defaultImage;
_imageView.frame = frame;
_imageView.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:_imageView];
[self makeViewRounded:_imageView];
[self makeViewRounded:self];
}
-(UIView*) makeViewRounded:(UIView*)view {
//set the look of the image
view.layer.cornerRadius= self.frame.size.height /2;
view.layer.opaque = NO;
view.layer.masksToBounds = YES;
return view;
}
-(void)updateImage:(UIImage *)image {
_image = image;
_imageView.image = image;
}
-(void)reset {
[self updateImage:_defaultImage];
}
#end
an example for the output will be :
If you look closely you will notice that the border is a circle, but the image view has edges.
How can i make the Image smooth as well ?
self.imgViewbg.layer.cornerRadius = self.imgViewbg.frame.size.width / 2;
self.imgViewbg.clipsToBounds = YES;
u Can Try This Code. And Implement in your Project..
It Will Definetly Work.. for u
I think the problem seems to be here:
view.layer.cornerRadius= self.frame.size.height /2;
Try giving it a constant small number and see the change. May be the height/2 is not making a perfect circle. You can give a smaller value than height/2 and see the change. It a wild guess by watching your image.
I have a couple of particle systems on my app that I checked originally on an iPad 3 with ios7. The particles looked and behaved like I expected them, but when I test on an iPad2 with ios6. The particles are displaced up and are smaller. I have a subclass for the particles. Here's the code for one of my particle systems. I was wandering if the CGREctMake is positioning the particle in a different area on a non retina display, but that doesn't happen when I position other things on the display.
Code to call the particles.
- (void)ShowSteamEffect
{
//Create view for Steam particle effect.
CGRect SteamFrame = CGRectMake(790, 380, 100, 100);
//Show Steam effect
ShowSteam = [[SteamEffect alloc]initWithFrame:SteamFrame];
ShowSteam.hidden = NO;
[self.view insertSubview:ShowSteam aboveSubview:imgComputerLights];
}
Steam subclass.
#import "SteamEffect.h"
#implementation SteamEffect
{
CAEmitterLayer* SteamEmitter;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
SteamEmitter = (CAEmitterLayer*) self.layer;
//SteamEmitter.emitterPosition= CGPointMake(0, 0);
//SteamEmitter.emitterSize = CGSizeMake(10,10);
CAEmitterCell* Steam = [CAEmitterCell emitterCell];
Steam.birthRate = 50;
Steam.spin = .6;
Steam.lifetime = 1.7;
Steam.alphaRange = 0.2;
Steam.alphaSpeed = 0.2;
Steam.contents = (id)[[UIImage imageNamed:#"Steam1.png"]CGImage];
Steam.velocity = 30;
Steam.velocityRange = 50;
Steam.emissionLongitude = -60;
Steam.emissionRange = M_1_PI;
Steam.scale = .2;
Steam.scaleSpeed = .5;
Steam.yAcceleration = -200;
SteamEmitter.renderMode = kCAEmitterLayerBackToFront;
SteamEmitter.emitterShape = kCAEmitterLayerCircle;
SteamEmitter.emitterCells = #[Steam];
}
return self;
}
-(void)didMoveToSuperview
{
[super didMoveToSuperview];
if (self.superview==nil) return;
[self performSelector:#selector(disableEmitterCell) withObject:nil afterDelay:0.5];
}
-(void)disableEmitterCell
{
[SteamEmitter setValue:#0 forKeyPath:#"birthRate"];
}
+ (Class) layerClass
{
//tell UIView to use the CAEmitterLayer root class
return [CAEmitterLayer class];
}
- (void) setEmitterPosition:(CGPoint)pos
{
SteamEmitter.emitterPosition = pos;
}
- (void) toggleOn:(bool)on
{
//SteamEmitter.birthRate = on? 300 : 0;
}