Space Behind TabBar Unrecognizable - ios

In my app, there exist a scenario where I hide the bottom TabBar by [self.tabBarController.tabBar setHidden:YES] and later add a UIView containing UIButtons in the vacated area at the bottom of the view.
The area where the TabBar was will not respond to touch events so I can't select any of the buttons in the UIView.
I've done research on here and this question has been around for awhile but the old answers don't seem to work anymore. [self setNeeds Display] and self.tabBarController.tabBar.translucent = YES, do not work anymore as you still can't press the UIButtons. On a side note, I created my UIView with UIButtons in storyboards and put a bottom constraint to the superview. Please provide an answer known to work for iOS 9 and 10.

I created a project according to question. It's work fine. Please try this.
- (void)viewDidLoad {
[super viewDidLoad];
[self.tabBarController.tabBar setHidden:YES];
UIView *view = [[UIView alloc]initWithFrame:self.tabBarController.tabBar.frame];
[self.view addSubview:view];
view.backgroundColor = [UIColor redColor];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 100,view.frame.size.height)];
[view addSubview:btn];
[btn setTitle:#"clicked me " forState:UIControlStateNormal];
[btn addTarget:self action:#selector(btnclicked:) forControlEvents:UIControlEventTouchDown];
}
-(void)btnclicked:(UIButton *)sender{ NSLog(#"button clicked event."); }

I created a test project to check the functionality that you want.
class ViewController: UIViewController {
#IBOutlet weak var testButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
testButton.addTarget(self, action: #selector(tapped), for: .touchUpInside)
self.tabBarController?.tabBar.isHidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tapped(_ sender:UIButton){
print("Tapped")
}
}
As per your requirement, i created a uiview containing a UIButton as a subview and created a outlet for the button.
As, i tab on on the button the action - tapped is triggered.

Related

Rotate BarButtonItem by 45 degrees (animated)

looks like animations are not my speciality :/
In my navigation bar I have a custom BarButtonItem, a plus, to add stuff to the list. I wanted to rotate the plus by 45 degrees so it becomes a X when it was pressed and works as a cancel button then.
I added a button as custom view to the BarButtonItem by doing this:
#IBOutlet weak var addQuestionaryButton: UIBarButtonItem!
{
didSet {
let icon = UIImage(named: "add")
let iconSize = CGRect(origin: CGPoint.zero, size: icon!.size)
let iconButton = UIButton(frame: iconSize)
iconButton.setBackgroundImage(icon, for: .normal)
addQuestionaryButton.customView = iconButton
iconButton.addTarget(self, action: #selector(QuestionaryListViewController.addClicked(_:)), for: .touchUpInside)
}
}
This seems to work fine.
Now if the button is pressed I do the following:
UIView.animate(withDuration: 0.5, animations:{
self.addQuestionaryButton.customView!.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI_4))
})
I can see the button starting to rotate but somehow it gets totally deformed. See the pictures for that:
Before:
After:
I don't understand why this happens.
How do I correctly animate the BarButtonItem?
Thanks in advance.
Greetings
Don't know why this is happening(my guess is when doing the transform, the frame of the customView will be messed up) but found a solution.
Just put the button into another UIView and then set this UIView as the customView of the UIBarButtonItem.
When doing the animation, don't rotate the UIView, rotate the button.
Reminder: Don't forget to set the frame of this UIView.
Sample code in Objective C:
Init:
#interface ViewController ()
#property (nonatomic, strong) UIButton* itemButton;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//button init
self.itemButton = [[UIButton alloc] init];
[self.itemButton setBackgroundImage:[UIImage imageNamed:#"imgName"] forState:UIControlStateNormal];
self.itemButton.frame = CGRectMake(0, 0, 30, 30);
//container for the button
UIView* btnContainer = [[UIView alloc] init];
btnContainer.frame = CGRectMake(0, 0, 30, 30);
[btnContainer addSubview:self.itemButton];
//set the container as customView of the UIBarButtonItem
UIBarButtonItem* applyButton = [[UIBarButtonItem alloc] initWithCustomView:btnContainer];
self.navigationItem.rightBarButtonItem = applyButton;
}
Code to trigger the rotation:
[UIView animateWithDuration:0.5 animations:^{
self.itemButton.transform = CGAffineTransformRotate(self.itemButton.transform, M_PI_4);
}];

UIButton not clickable in UITableViewCell

I added multiple buttons in my UITableViewCell wrapped with a toolbar, but all of them are not clickable, once I drag a button to the outside of the table view it's clickable already.
Here is the screenshot of my sample app and scene:
Button 1 is not clickable but button 2 is clickable, User Interaction Enabled has been ticked.
Okay found the issue already, was a mistake by my own, it's because I set the tableViewCell "User Interaction Enabled" to NO, cause I want to disable the Table View default row selection.
So I need to set each layers of view "User Interaction Enabled" to YES, then the button is now clickable, thanks for all the replies!
Create you button in viewForHeaderInSection, like this..
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *sectionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 30)];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[btn addTarget:self action:#selector(btnClicked) forControlEvents:UIControlEventTouchUpInside];
[sectionView addSubview:btn];
//add other subviews to section viewww..
//return
return sectionView;
}
- (void) btnClicked
{
//do your thing here..
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
cell.button.tag = indexPath.row
cell.button.addTarget(self, action: "btnClicked:", forControlEvents: .TouchUpInside)
}

UISearchBar Customization

I'm trying to customize UISearchBar but I"m having a hard time with it.
This is what my searchbar looks like currently. What I want to be able to do is set a uiimage on the entire uisearchbar. I tried setSearchFieldBackgroundImage but it does not affect the text field part of the searchbar. How can I put an image in the white part? I also want to extend the white part to the edge to have equal margins on all sides.
for the image purpose u could use this one,dont forget to import Quartzcore framework
[searchbar setBackgroundImage:[UIImage imageNamed:#"base_200x50.png"]];
[searchbar setTranslucent:YES];
UITextField *txtSearchField = [searchbar valueForKey:#"_searchField"];
[txtSearchField setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"base_200x50.png"]]];
[txtSearchField setBorderStyle:UITextBorderStyleRoundedRect];
txtSearchField.layer.borderWidth = 8.0f;
txtSearchField.layer.cornerRadius = 10.0f;
txtSearchField.layer.borderColor = [UIColor clearColor].CGColor;
and to extend textfeild u can set frame of txtSearchField.
I hope this may help you:
Pattern image I used:
#IBOutlet weak var sbSearchBar: UISearchBar!
// if you wan to set background color for searchbar, except field
func setupSearchbarBackgroundImage() -> Void {
sbSearchBar.setBackgroundImage(UIImage(named: "pattern2"), for: UIBarPosition.any, barMetrics: UIBarMetrics.default)
}
Result:
func setupSearchbar() -> Void {
// if you wan to set background color for field only
if let textfield = sbSearchBar.value(forKey: "searchField") as? UITextField {
textfield.backgroundColor = UIColor(patternImage: UIImage(named: "pattern2")!)
}
}
Here is result:

Adding Background Image into View Controller

I tried to use this code under in my app delegate in order to add a PNG image as a view controller's background :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[self window] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
return YES;
}
but I have no luck with it... the view controller still has a white background. What's wrong with that code?
The accepted answer and Michael's answer will work, however, proper way is to use a UIImageView instead. It gives more control over resizing, scaling etc according to different screen sizes on devices. Here is the example;
First create a UIImage.
UIImage *backgroundImage = [UIImage imageNamed:#"iphone_skyline3.jpg"];
Second create a UIImageView. Set the frame size to the parent's (self) frame size. This is important as the frame size will vary on different devices. Stretching will occur depending on the image size. Next assign the image to the view.
UIImageView *backgroundImageView=[[UIImageView alloc]initWithFrame:self.view.frame];
backgroundImageView.image=backgroundImage;
Finally, to keep the image behind all controls do the following. It is important if you are setting the image as a background for your app.
[self.view insertSubview:backgroundImageView atIndex:0];
You need to set the background for your ViewController's view
In your ViewController init or viewDidLoad:
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
Here is how it is in swift:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(patternImage: UIImage(named: "background.png"))
}
Swift 4 version of the #hadaytullah answer with some improvements in image adjustments:
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImage.init(named: "yourImageNameHere")
let backgroundImageView = UIImageView.init(frame: self.view.frame)
backgroundImageView.image = backgroundImage
backgroundImageView.contentMode = .scaleAspectFill
backgroundImageView.alpha = 0.1
self.view.insertSubview(backgroundImageView, at: 0)
}
You could also write extension to UIViewController to use in multiple places
extension UIViewController {
func setBackgroundImage(imageName: String) {
let backgroundImage = UIImage(named: imageName)
let backgroundImageView = UIImageView(frame: self.view.frame)
backgroundImageView.image = backgroundImage
self.view.insertSubview(backgroundImageView, at: 0)
}
}
In viewDidLoad, I use:
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"yourImageString.png"]];
Alternatively, if you want to do it in appDelegate, I think its possible to
[self.window setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"yourImageString.png"]]];
Then in viewDidLoad set background to [UIColor clearColor] ?
If your view controller is having tableView/collection view the below code will suitable for you.
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourImage.png"]];
}
you may consider the following solution i use in swift 3.0 and tested in xcode 8
// init and image with your pattern image
var bgUIImage : UIImage = UIImage(named: "yourIamgeName")!
let myInsets : UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
bgUIImage = bgUIImage.resizableImage(withCapInsets: myInsets)
self.view.backgroundColor = UIColor.init(patternImage:bgUIImage)
the result will be the following image
You can do it from the storyboard.
Add UIImageView and just set your background image for the Image property in the Attribute Inspector.

Dismissing the keyboard in a UIScrollView

Alright, I have a couple of UITextFields and UITextViews inside a UIScrollView, and I'd like to set the keyboard to disappear whenever the scrollview is touched or scrolled (except when you touch down inside the text field/view, of course).
My current attempt at doing this is replacing the UIScrollView with a subclass, and setting it to call a removeKeyboard function (defined inside the main view controller) inside the touchesBegan method. However, this only removes the keyboard for a normal touch, not when the view is simply scrolled. So, what's the best way to remove the keyboard inside a UIScrollView?
Thanks in advance for your help.
Here is the cleanest way to achieve this in iOS 7.0 and above.
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
Or
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
In Swift:
scrollView.keyboardDismissMode = .onDrag
Or
scrollView.keyboardDismissMode = .interactive
Bit late but if anyone else is searching an answer to this problem, this is how I have gone about solving it:
1) Create a tap gesture recognizer with a target callback method to dismiss your keyboard using resignFirstResponder on all your fields.
2) Add the tap gesture to the scrollview.
Here's an example:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
// prevents the scroll view from swallowing up the touch event of child buttons
tapGesture.cancelsTouchesInView = NO;
[pageScrollView addGestureRecognizer:tapGesture];
[tapGesture release];
...
// method to hide keyboard when user taps on a scrollview
-(void)hideKeyboard
{
[myTextFieldInScrollView resignFirstResponder];
}
Although the essence is the same, I prefer less code.
Setting the keyboard to disappear when the scrollView is scrolled in Attributes inspector:
Then disappear keyboard when scrollView is tapped:
Drag a Tap Gesture Recognizer onto your scrollView
Only one line in the action —— scrollView.endEditing(true). If you are using Objective-C, [self.scrollView endEditing: YES];
In Swift:
Bit late but if anyone else is searching an answer to this problem, this is how I have gone about solving it:
1) Create a tap gesture recognizer with a target callback method to dismiss your keyboard using resignFirstResponder on all your fields.
2) Add the tap gesture to the scrollview.
Here's an example:
import UIKit
class ViewController: UIViewController {
#IBOutlet var t1: UITextField!
#IBOutlet var t2: UITextField!
#IBOutlet var t3: UITextField!
#IBOutlet var t4: UITextField!
#IBOutlet var srcScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard")
// prevents the scroll view from swallowing up the touch event of child buttons
tapGesture.cancelsTouchesInView = false
srcScrollView.addGestureRecognizer(tapGesture)
}
func hideKeyboard() {
t1.resignFirstResponder()
t2.resignFirstResponder()
t3.resignFirstResponder()
t4.resignFirstResponder()
}
}
Look at keyboardDismissMode property of UIScrollView.
// will hide keyboard when your text field is about to go beyond the keyboard.
vwScrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
// will hide keyboard instantly once the scroll view started scrolling by user.
vwScrollView.keyboardDismissMode = UIScrollViewKeyboardDismissOnDrag;
// If you need to hide keyboard on tap of scroll view,consider adding a tap gesture or sub class and override touchesbegan: method.
Swift Version
vwScrollView.keyboardDismissMode = .interactive
vwScrollView.keyboardDismissMode = .onDrag
Create a extension class for hiding keyboard when touches scrollview/view anywhere
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
And call this method in viewDidLoad like
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
Try This
[self.selectedViewController.view endEditing:YES];
A bit late but if anyone else is searching an answer to this problem with Swift 3:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
view.endEditing(true)
}
When I added the gesture to a subclass of UIScrollView, I was having problems with the various gestures in my view tree interfering with each other, such as being able to click on subviews, scroll the view, and have the keyboard dismiss in all cases. I came up with this solution, which can be setup from a superclass of UIScrollView or from a UIViewController.
The DismissKeyboardTapGesture class uses ARC, works with any text fields under the view, and doesn't take over any clicks from subviews like buttons. Also takes advantage of iOS7 scrolling effect to dismiss keyboard.
Setting up from UISScrollView superclass:
_dismissKeyboard = [[DismissKeyboardTapGesture alloc] initWithView:self];
or from UIViewController:
_dismissKeyboard = [[DismissKeyboardTapGesture alloc] initWithView:self.view];
Here is the class:
#interface DismissKeyboardTapGesture : NSObject <UIGestureRecognizerDelegate>
#end
#implementation DismissKeyboardTapGesture
- (id)initWithView:(UIView *)view
{
self = [super init];
if (self) {
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTap:)];
singleTap.cancelsTouchesInView = NO;
singleTap.delegate = self;
[view addGestureRecognizer:singleTap];
if ([view respondsToSelector:#selector(setKeyboardDismissMode:)]) {
// Bonus effect to dismiss keyboard by scrolling
((UIScrollView *)view).keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
}
}
return self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// Don't stop any existing gestures in our view from working
if (otherGestureRecognizer.view == gestureRecognizer.view) {
return YES;
}
return NO;
}
- (void)singleTap:(UIGestureRecognizer*)gestureRecognizer
{
// Close keyboard for any text edit views that are children of the main view
[gestureRecognizer.view endEditing:YES];
}
#end
Try this scroll view delegate method -
link delegate in IB to scroll view and then cop this code (modify as per your need).
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
//sample code
[challengeABallotComponent.voterNameTextField resignFirstResponder];
[challengeABallotComponent.ballotNumberTextField resignFirstResponder];
[locationInformation.pollingLocation resignFirstResponder];
}
This should work. You can try other delegate methods too like
-(void)scrollViewDidScroll: (UIScrollView *)scrollView
{
//do your stuff
}
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
extension UIView{
//Set tag via storyboard
func keyboardDissmissInteractiveMode(_ tag:Int){
if let scrollView = self.viewWithTag(tag) as? UIScrollView{
scrollView.keyboardDismissMode = .interactive
}
if let tableview = self.viewWithTag(tag) as? UITableView{
tableview.keyboardDismissMode = .interactive
}
}
func keyboardDissmissOnDragMode(_ tag:Int){
if let scrollView = self.viewWithTag(tag) as? UIScrollView{
scrollView.keyboardDismissMode = .onDrag
}
if let tableview = self.viewWithTag(tag) as? UITableView{
tableview.keyboardDismissMode = .onDrag
}
}
func keyboardDissmissInteractiveMode(_ view:UIView){
if let scrollView = view as? UIScrollView{
scrollView.keyboardDismissMode = .interactive
}
if let tableview = view as? UITableView{
tableview.keyboardDismissMode = .interactive
}
}
func keyboardDissmissOnDragMode(_ view:UIView){
if let scrollView = view as? UIScrollView{
scrollView.keyboardDismissMode = .onDrag
}
if let tableview = view as? UITableView{
tableview.keyboardDismissMode = .onDrag
}
}
}

Resources