UIButton Analog for reversesTitleShadowWhenHighlighted for Selected State - iphone

I am using the reversesTitleShadowWhenHighlighted property on UIButton to reverse the title's text shadow(and it works great), but I really want the same thing for the selected state of the button(UIControlStateSelected).
Any answers to the related questions are also welcome:
Is there a way to do this with a UIButton without modifications?
Is there a way to set the shadowOffset of the title label per state with UIButton(similar to what is possible with the shadowColor)?
If you were to extend UIButton to add this, how would you do it?

I run into the same problem, so I guess it's no for your first two questions. Here is how I subclassed it :
#interface MyButton : UIButton
#property (nonatomic) BOOL reversesTitleShadowWhenSelected;
#end
#implementation MyButton
#synthesize reversesTitleShadowWhenSelected;
- (void)setSelected:(BOOL)selected
{
if (self.reversesTitleShadowWhenSelected)
{
if ((selected && !self.isSelected) ||
(!selected && self.isSelected))
{
CGSize offset = self.titleLabel.shadowOffset;
offset.width *= -1;
offset.height *= -1;
self.titleLabel.shadowOffset = offset;
}
}
[super setSelected:selected];
}
#end

Related

Linking stepper to Slider UIObject in C4

I am very new to C4 so please be gentle...
If I want to link a slider value to a label this is done with NSString stringWithFormat... e.g.:
self.mylabel.text = [NSString stringWithFormat:#"%4.2f",slider.value];
I added a stepper object as well, and now it also updates mylabel:
self.mylabel.text = [NSString stringWithFormat:#"%4.2f",stepper.value];
But it would be intuitive if the slider position follows the label value when I'm using the stepper. but .value is not an available property in UILabel... so how do I take the mylabel.text property and push that into the slider.value property without getting a datatype mismatch error?
This question has 2 answers, how to do it using C4 objects and how to do it with Interface Builder / UIControls. I'll show both ways, UI first so that I can compare the C4 way afterwards.
UIControl
To do this with UIControls first set up your C4WorkSpace.h header so that it has the following methods and properties:
#property (assign, nonatomic) IBOutlet UILabel *myLabel;
#property (assign, nonatomic) IBOutlet UISlider *mySlider;
#property (assign, nonatomic) IBOutlet UIStepper *myStepper;
-(IBAction)sliderWasUpdated:(UISlider *)slider;
-(IBAction)stepperWasUpdated:(UIStepper *)stepper;
Then, in your drag all three components onto your projects XIB file (i.e. a UISlider, UILabel and UIStepper). Link the action sliderWasUpdated: to the slider using the valueChanged option, and the stepperWasUpdated: action to the stepper also using the valueChanged option. You do this step by selecting C4Canvas.xib from your project then right-clicking on the yellow cube, then dragging from the actions listed in the pop-up menu to each of the objects that you recently placed on the canvas.
Next, add the following code to your C4WorkSpace.m file:
#implementation C4WorkSpace
-(void)setup {
self.myStepper.minimumValue = 0.0f;
self.myStepper.maximumValue = 10.0f;
self.mySlider.minimumValue = 0.0f;
self.mySlider.maximumValue = 10.0f;
}
-(IBAction)sliderWasUpdated:(UISlider *)slider {
slider.value = [C4Math round:slider.value];
self.myLabel.text = [NSString stringWithFormat:#"%4.2f",slider.value];
self.myStepper.value = slider.value;
[self.myLabel sizeToFit];
}
-(IBAction)stepperWasUpdated:(UIStepper *)stepper {
self.myLabel.text = [NSString stringWithFormat:#"%4.2f",stepper.value];
self.mySlider.value = stepper.value;
[self.myLabel sizeToFit];
}
#end
In the setup we make sure that the min/max values of both UI objects are the same (so that we can keep them matched up).
In the stepperWasChanged: method we do two things:
We use the stepper's value to set the label's text
We also use the stepper's value to set the slider's value!
In the sliderWasChanged: method we do the same thing, updating the stepper, but we also round the value of the slider so that it increments in steps (just to keep things tidy).
C4Control
To do the same with C4 objects, instead of native UI objects, we set things up a little differently. First, we don't add anything to our C4Canvas.xib, instead we'll set the objects up manually.
In your C4WorkSpace.h file, add the following lines of code:
#property (readwrite, nonatomic, strong) C4Label *myLabel;
#property (readwrite, nonatomic, strong) C4Slider *mySlider;
#property (readwrite, nonatomic, strong) C4Stepper *myStepper;
-(void)sliderWasUpdated:(C4Slider *)slider;
-(void)stepperWasUpdated:(C4Stepper *)stepper;
Notice that most of this is the same except we're using C4 instead of UI prefixes. Also, we call our methods -(void) instead of -(IBAction) because we're not using Interface Builder.
Next, add the following code to your C4WorkSpace.m:
#implementation C4WorkSpace
-(void)setup {
[self createAddObjects];
//calibrate the min/max values
self.myStepper.minimumValue = 0.0f;
self.myStepper.maximumValue = 10.0f;
self.mySlider.minimumValue = 0.0f;
self.mySlider.maximumValue = 10.0f;
}
-(void)sliderWasUpdated:(C4Slider *)slider {
slider.value = [C4Math round:slider.value];
self.myLabel.text = [NSString stringWithFormat:#"%4.2f",slider.value];
self.myStepper.value = slider.value;
[self.myLabel sizeToFit];
}
-(void)stepperWasUpdated:(C4Stepper *)stepper {
self.myLabel.text = [NSString stringWithFormat:#"%4.2f",stepper.value];
self.mySlider.value = stepper.value;
[self.myLabel sizeToFit];
}
-(void)createAddObjects {
//set up the objects
self.myLabel = [C4Label labelWithText:#"values"];
self.myStepper = [C4Stepper stepper];
self.mySlider = [C4Slider slider:CGRectMake(0, 0, 192, 44)];
//position them
CGPoint centerPoint = CGPointMake(self.canvas.center.x,
self.canvas.center.y - 100);
self.myStepper.center = centerPoint;
centerPoint.y += 100;
self.myLabel.center = self.canvas.center;
centerPoint.y += 100;
self.mySlider.center = centerPoint;
//set up action bindings
[self.mySlider runMethod:#"sliderWasUpdated:"
target:self
forEvent:VALUECHANGED];
[self.myStepper runMethod:#"stepperWasUpdated:"
target:self
forEvent:VALUECHANGED];
[self.canvas addObjects:#[self.myStepper,self.myLabel,self.mySlider]];
}
#end
DIFFERENCES
The major difference between the two approaches is whether or not you use Interface Builder. In the C4 approach we need to add a method called createAddObjects to our project so that our slider, label and stepper all get added to the canvas.
This method also contains the methods for binding the actions of our C4UIElements to our code, which happens in the lines:
[self.mySlider runMethod:#"sliderWasUpdated:"
target:self
forEvent:VALUECHANGED];
[self.myStepper runMethod:#"stepperWasUpdated:"
target:self
forEvent:VALUECHANGED];
Once these are set up the only difference is specifying the use of C4 objects instead of UI objects, like:
-(void)sliderWasUpdated:(C4Slider *)slider {...}
instead of
-(IBAction)sliderWasUpdated:(UISlider *)slider {...}

iOS - Can not set Button 'Disable', without removing the content of it

Sorry for what should be a simple solution.
I am trying to 'Disable' a button in code using the following Code:
in the first Class which Called 'CheckBox':
checkBox.h :
#interface CheckBox : UIViewController
{
BOOL checkboxSelected;
UIButton *checkBoxButton;
}
#property (nonatomic, retain) IBOutlet UIButton *checkBoxButton;
- (IBAction)checkBoxButton:(id)sender;
-(void) setCheckBoxSelected:(BOOL)checkingStatus;
-(void) setCheckBoxEnabled:(BOOL)enablingStatus;
in checkBox.m :
- (IBAction)checkBoxButton:(id)sender {
if (checkboxSelected == 0){
[checkBoxButton setSelected:YES];
checkboxSelected = 1;
} else {
[checkBoxButton setSelected:NO];
checkboxSelected = 0;
}
}
-(void) setCheckBoxSelected:(BOOL)checkingStatus {
checkBoxButton.selected = checkingStatus;
}
-(void) setCheckBoxEnabled:(BOOL)enablingStatus {
[checkBoxButton setEnabled:enablingStatus];
}
and in the implementation of another class which called 'MainViewController.m' :
- (void)viewDidLoad{
allTransactionCheckBox = [[CheckBox alloc] init];
[self.viewWithdraw addSubview:withdrawCheckBox.view ];
withdrawCheckBox.labelCheckBox.textColor = [UIColor blackColor];
withdrawCheckBox.labelCheckBox.font = [UIFont systemFontOfSize:14];
withdrawCheckBox.labelCheckBox.text = #"Withdraw";
[withdrawCheckBox setCheckBoxSelected:YES];
}
The above code is 'Disable' the button, but it (Remove/ Hide) the 'check mark Picture' inside the button.Why?
All links ( outlet + Actions ) are connected .
What obvious thing am I missing? Thanks.
What exactly are you trying to do? Maybe setting userInteractionEnabled is what you want?
Cheers
You have defined the button in interface builder. It looks like you havent set the image for all control states - select the button and look at the attributes inspector - there is a drop down for normal, highlighted, etc. is your check mark image defined for all those states?
This looks way too complex for what you want to do. You have a reference to your button -- checkBoxButton. Just use checkBoxButton.enabled = NO;

UITableViewCell, Delete Button Frame?

Is there a way to alter the frame of the "swipe" [DELETE] button used on UITableViewCells? Currently its centred vertically within the cell, but if possible I would like to move it down to the cyan guide show.
If you are looking for a strongly true way to solve this problem then you should to subclass of UITableViewCell and override the all state handling methods for correct drawing your own delete button (do not call super in those methods). But there is another easy way:
#implementation CustomCell
- (void)layoutSubviews {
[super layoutSubviews];
if (self.showingDeleteConfirmation) {
if ([self.subviews count] < 4) return;
UIView *delBtn = [self.subviews objectAtIndex:3];
delBtn.frame = CGRectOffset(delBtn.frame, 0, 10);
}
}
#end
Instead of didTransitionToState:,
How about using the -(void)willTransitionToState: and setting the frame of the editingAccessoryView?
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
if (state == UITableViewCellEditingStyleDelete)
{
NSInteger num = 10;
UIView.frame = CGRectMake(UIView.frame.origin.x,UIView.frame.origin.y - num,
UIView.size.width,UIView.size.height);
}
}
Try changing the frame for Accessory View

Implementing steps/snapping UISlider

I am trying to implement some form of snapping or steps with the UISlider. I have written the following code but it does not work as smooth as I hoped for. It works, but when the I slide it upwards it snap 5points to the right leaving the finger not centered over the "slide-circle"
This is my code where self.lastQuestionSliderValue is a property of the class which I have set to the initial value of the slider.
if (self.questionSlider.value > self.lastQuestionSliderValue) {
self.questionSlider.value += 5.0;
} else {
self.questionSlider.value -= 5.0;
}
self.lastQuestionSliderValue = (int)self.questionSlider.value;
It's actually considerably easier than I first thought. Originally I was trying to get the thumbrect property and do complicated math. Here's what I ended up with:
h File:
#property (nonatomic, retain) IBOutlet UISlider* questionSlider;
#property (nonatomic) float lastQuestionStep;
#property (nonatomic) float stepValue;
m File:
- (void)viewDidLoad {
[super viewDidLoad];
// Set the step to whatever you want. Make sure the step value makes sense
// when compared to the min/max values for the slider. You could take this
// example a step further and instead use a variable for the number of
// steps you wanted.
self.stepValue = 25.0f;
// Set the initial value to prevent any weird inconsistencies.
self.lastQuestionStep = (self.questionSlider.value) / self.stepValue;
}
// This is the "valueChanged" method for the UISlider. Hook this up in
// Interface Builder.
-(IBAction)valueChanged:(id)sender {
// This determines which "step" the slider should be on. Here we're taking
// the current position of the slider and dividing by the `self.stepValue`
// to determine approximately which step we are on. Then we round to get to
// find which step we are closest to.
float newStep = roundf((questionSlider.value) / self.stepValue);
// Convert "steps" back to the context of the sliders values.
self.questionSlider.value = newStep * self.stepValue;
}
Make sure you hook up the method and the outlet for your UISlider view and you should be good to go.
The simplest solution to me was just
- (IBAction)sliderValueChanged:(id)sender {
UISlider *slider = sender;
slider.value = roundf(slider.value);
}
Another Swift approach is to do something like
let step: Float = 10
#IBAction func sliderValueChanged(sender: UISlider) {
let roundedValue = round(sender.value / step) * step
sender.value = roundedValue
// Do something else with the value
}
SWIFT VERSION
Example:
You want a slider to go from 1-10000 in steps of 100.
UISlider setup is as follows:
slider.maximumValue = 100
slider.minimumValue = 0
slider.continuous = true
In the action func() for the slider use:
var sliderValue:Int = Int(sender.value) * 100
Maybe someone will need!
In my situation I needed any integer step, so I used the following code:
-(void)valueChanged:(id)sender {
UISlider *slider = sender;
slider.value = (int)slider.value;
}
A really simple one:
- (void)sliderUpdated:(UISlider*)sli {
CGFloat steps = 5;
sli.value = roundf(sli.value/sli.maximumValue*steps)*sli.maximumValue/steps;
}
Great if you want a fast solution and you've added the target by UIControlEventValueChanged.

Moving an UIView - newbie iphone sdk

Hey guys... today is my first day hacking away on the iphone SDK. Having a blast but have a quick question.
I'm trying to move an UIView around the screen dynamically by sending it information from a slider. My slider is working fine but I cant seem to figure out how to get the UIView to move.
My .h file...
#interface Slider_BallViewController : UIViewController
{
IBOutlet UISlider *theslider;
IBOutlet UITextField *ytext;
IBOutlet UIView *theball;
}
- (IBAction)moveVert:(id)sender;
My .m file...
- (IBAction)moveVert:(id)sender
{
int progressAsInt = (int)(theslider.value);
NSString *newText = [[NSString alloc] initWithFormat:#"%d", progressAsInt];
ytext.text = newText;
theball.frame.origin.y += progressAsInt;
}
I get an error on the frame.origin line in my .m file that says... lvalue required as left operand assignment. Not sure what im doing wrong.
Any help is great, thanks.
If you want to modify a UIView's frame property, you should do it by following:
CGRect curFrame = theball.frame;
curFrame.origin.y += progressAsInt;
theball.frame = curFrame;