I am using the UIImagePickerController with a custom camera overlay view and wish to add a custom button to toggle the flash mode between auto, on, and off. Here is the method the button calls:
- (void)didTapFlash:(id)sender
{
if (self.imagePickerController.cameraFlashMode == UIImagePickerControllerCameraFlashModeAuto)
{
[imagePickerController setCameraFlashMode:UIImagePickerControllerCameraFlashModeOn];
[self.flashButton setImage:[UIImage imageNamed:#"flashIconOn.png"] forState:UIControlStateNormal];
}
else if (self.imagePickerController.cameraFlashMode == UIImagePickerControllerCameraFlashModeOn)
{
self.imagePickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
[self.flashButton setImage:[UIImage imageNamed:#"flashIconOff.png"] forState:UIControlStateNormal];
}
else if (self.imagePickerController.cameraFlashMode == UIImagePickerControllerCameraFlashModeOff)
{
self.imagePickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
[self.flashButton setImage:[UIImage imageNamed:#"flashIconAuto.png"] forState:UIControlStateNormal];
}
}
The problem is this doesn't work. The value of self.imagePickerController.cameraFlashMode never changes once the controller is presented. The flash value can be changed before it is presented but, once it is, it will always return a value of 0 (Auto). The strange part is, even though the value doesn't change, the flash behaves as if it does so if I change the above code to:
- (void)didTapFlash:(id)sender
{
if (flashButton.tag == 0)
{
[imagePickerController setCameraFlashMode:UIImagePickerControllerCameraFlashModeOn];
self.flashButton.tag = 1;
[self.flashButton setImage:[UIImage imageNamed:#"flashIconOn.png"] forState:UIControlStateNormal];
}
else if (flashButton.tag == 1)
{
self.imagePickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
self.flashButton.tag = -1;
[self.flashButton setImage:[UIImage imageNamed:#"flashIconOff.png"] forState:UIControlStateNormal];
}
else if (flashButton.tag == -1)
{
self.imagePickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
self.flashButton.tag = 0;
[self.flashButton setImage:[UIImage imageNamed:#"flashIconAuto.png"] forState:UIControlStateNormal];
}
}
Everything works as expected. (the flashButton.tag is just storing the flash value)
Does anyone know what is happening here? Why does the value of cameraFlashMode always 0 (both in NSLog statements and when checked directly through the debugger) even though the flash is behaving as though it is set properly?
It seems to be a bug in latest iOS version,
you'll notice that it will work with enabling the flag of
self.picker.showsCameraControls = true
but it shows the native camera control to your overlayview, so i hacked it with this code:
self.picker.showsCameraControls = true
self.picker.cameraFlashMode = .On
self.picker.showsCameraControls = false
It is fast enough to not disturb user with the showing and hiding controls.
It Worked for me and i'm sure it will work in your case too!
Related
I have 8 buttons, I want to do so: When click on one of the buttons will be grayed out three and four are active. But it will be happening when I hold the button, but do not push it. If move finger on the button, and press it, all the buttons will be active. I tried using "exclusiveTouch" but it becomes inactive all 7 buttons.
Code:
- (void)viewDidLoad
{
qsq.exclusiveTouch = YES;
qsq2.exclusiveTouch = YES;
qsq3.exclusiveTouch = YES;
qsq4.exclusiveTouch = YES;
qsq_plr2.exclusiveTouch = YES;
qsq2_plr2.exclusiveTouch = YES;
qsq3_plr2.exclusiveTouch = YES;
qsq4_plr2.exclusiveTouch = YES;
}
When I click "qsq" then All the buttons are inactive. But I need qsq2, qsq3, qsq4 becomes inactive, and the other buttons are active.
It seems your design is a bit more complicated than the basic UIView properties can handle. Here's an example of the solution, only using 2 buttons.
Setup:
[button1 addTarget:self action:#selector(disableButtons:) forControlEvents:UIControlEventTouchDown];
[button1 addTarget:self action:#selector(reenableButtons:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside|UIControlEventTouchCancel];
[button2 addTarget:self action:#selector(disableButtons:) forControlEvents:UIControlEventTouchDown];
[button2 addTarget:self action:#selector(reenableButtons:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside|UIControlEventTouchCancel];
And in the callbacks, you disable the buttons that need disabled:
-(void) disableButtons:(UIButton*)button {
if (button == button1) {
button2.enabled = FALSE;
} else if (button == button2) {
button1.enabled = FALSE;
}
}
-(void) reenableButtons:(UIButton*)button {
if (button == button1 || button == button2) {
button1.enabled = TRUE;
button2.enabled = TRUE;
}
}
I have a code that creates a button depending whenever a user has an iphone 4 or 5 and whenever they purchased an IAP to remove ads. Below is the code for it:
if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
// This is iPhone 5 screen
if (intvalue == 1) {
//No Ads
self.infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
self.infoButton.tintColor = [UIColor whiteColor];
self.infoButton.center = CGPointMake(289, 495);
[self.view addSubview:self.infoButton];
}
else{
//Yes Ads
self.infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
self.infoButton.tintColor = [UIColor whiteColor];
self.infoButton.center = CGPointMake(289, 451);
[self.view addSubview:self.infoButton];
}
} else {
// This is iPhone 4/4s screen
if (intvalue == 1|) {
//No Ads
self.infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
self.infoButton.tintColor = [UIColor whiteColor];
self.infoButton.center = CGPointMake(289, 429);
[self.view addSubview:self.infoButton];
}
else{
//Yes Ads
self.infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
self.infoButton.tintColor = [UIColor whiteColor];
self.infoButton.center = CGPointMake(289, 400);
[self.view addSubview:self.infoButton];
}
}
However one issue for me occurs when the ads don't load. The button is still placed higher in the screen that when it should be. How do I detect if ads did not load place the button in the location of when ads are removed?
You need to implement the ADBannerViewDelegate Protocol in your class.
https://developer.apple.com/library/ios/documentation/userexperience/Reference/ADBannerViewDelegate_Ref/Reference/Reference.html
When an ad is loaded, Apple will call bannerViewDidLoadAd.
When an ad is not loaded, Apple will call bannerView:didFailToReceiveAdWithError:
So for a temporary fix, in your code I would always draw the button as if an ad did not load. Then when the ad does load (inside bannerViewDidLoadAd) move the button down and display the ad.
This is my code to change the flash mode on iphone.
In ios7.0 works: flashmode(0,1,-1)
In ios7.1 don't works: flashmode(0,0,0)
//UIImagePickerControllerCameraFlashModeOff = -1,
//UIImagePickerControllerCameraFlashModeAuto = 0,
//UIImagePickerControllerCameraFlashModeOn = 1
NSInteger flashMode = self.pickerReference.cameraFlashMode;
NSLog(#"flashmode %i",flashMode);
if (flashMode == UIImagePickerControllerCameraFlashModeAuto) {
[(UIButton *)sender setImage:[UIImage imageNamed:#"flashYesComposeButton.png"] forState:UIControlStateNormal];
self.pickerReference.cameraFlashMode = UIImagePickerControllerCameraFlashModeOn;
}
else if (flashMode == UIImagePickerControllerCameraFlashModeOn) {
[(UIButton *)sender setImage:[UIImage imageNamed:#"flashNoComposeButton.png"] forState:UIControlStateNormal];
self.pickerReference.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
}
else if (flashMode == UIImagePickerControllerCameraFlashModeOff)
{
[(UIButton *)sender setImage:[UIImage imageNamed:#"flashAutoComposeButton.png"] forState:UIControlStateNormal];
self.pickerReference.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
}
I ran into that bug before
The problem is that no matter what the real flash state is in ios 7.1, it always returns UIImagePickerControllerCameraFlashModeAuto. Funny thing is, if you set the flash mode to UIImagePickerControllerCameraFlashModeOff, the flash will really be off, but if you ask the state, it will still be UIImagePickerControllerCameraFlashModeAuto.
So I solved my problem by keeping my own "flashState". When, clicked, I manually change my own state and never trust the one sent back but the UIImagePickerController.
#property (nonatomic) UIImagePickerControllerCameraFlashMode flashMode;
when the button is clicked :
if (self.flashMode == UIImagePickerControllerCameraFlashModeAuto) {
//toggle your button to "on"
self.flashMode = UIImagePickerControllerCameraFlashModeOn;
}else if (self.flashMode == UIImagePickerControllerCameraFlashModeOn){
//toggle your button to "Off"
self.flashMode = UIImagePickerControllerCameraFlashModeOff;
}else if (self.flashMode == UIImagePickerControllerCameraFlashModeOff){
//toggle your button to "Auto"
self.flashMode = UIImagePickerControllerCameraFlashModeAuto;
}
I have a button on my custom camera overlay that invokes this method:
- (void) changeFlash:(id)sender
{
//UIImagePickerControllerCameraFlashModeOff = -1,
//UIImagePickerControllerCameraFlashModeAuto = 0,
//UIImagePickerControllerCameraFlashModeOn = 1
NSLog(#"before %d", self.picker.cameraFlashMode);
switch (self.picker.cameraFlashMode) {
case UIImagePickerControllerCameraFlashModeAuto:
[(UIButton *)sender setImage:[UIImage imageNamed:#"flashOn"] forState:UIControlStateNormal];
self.picker.cameraFlashMode = UIImagePickerControllerCameraFlashModeOn;
break;
case UIImagePickerControllerCameraFlashModeOn:
[(UIButton *)sender setImage:[UIImage imageNamed:#"flashOff"] forState:UIControlStateNormal];
self.picker.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
break;
case UIImagePickerControllerCameraFlashModeOff:
[(UIButton *)sender setImage:[UIImage imageNamed:#"flashAuto"] forState:UIControlStateNormal];
self.picker.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
break;
}
NSLog(#"after %d", self.picker.cameraFlashMode);
}
self.picker.cameraFlashMode is always 0, before and after changing it. What am I doing wrong?
Also, the flash never works, even though it's supposedly stuck in UIImagePickerControllerCameraFlashModeAuto.
self.picker is nil. This is a common mistake, and you need to check this often, because, unlike Java and other languages, it's valid to send a message to nil in Objective-C.
I have a simple button with two images for each UIControlStates.
I want this button to behave as a control and as indicator so that I can press it down - "activate" and press again "deactivate", While some other functions can cause it to be turned off ("deactivate").
My question is how can I change it's state from selected to not-selected?
Changing the selected property would not do the trick :)
You can disable the button so it can't be press able.
yourButton.enabled = NO;
and When you want it back to be press able, then you can enabled it
yourButton.enabled = YES;
Simplest way would be consider button as switch and change it's state according switch on/off. For example use BOOL variable which upon button touch gets its value YES or NO while according to it button gets its image.
- (void) buttonTouched:(id)sender
{
switchOn = !switchOn;
UIImage *buttonImage = nil;
if (switchOn == YES)
{
buttonImage = [UIImage imageNamed:#"on.png"];
}
else
{
buttonImage = [UIImage imageNamed:#"off.png"];
}
[myButton setImage:buttonImage forState:UIControlStateNormal];
[myButton setImage:buttonImage forState:UIControlStateSelected];
}
if you need to programmatically set button "disabled":
- (void) setButtonDisabled
{
switchOn = YES; //calling buttonTouched: will turn it to NO
[self buttonTouched:nil];
}