I used UITableviewcellEditingstyleDelete to show button for user click on it to show delete button (it's the same way you can see on email app, when user click edit and then click on button to show the delete button). It's work fine in ios6 but when I build my app on device which have ios 7, the delete button is disappear, but when you tap in the delete button's area it's also can delete. The prolem is user cannot see the delete button (The button which have red color provide by OS).
My code is:
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Detemine if it's in editing mode
if (self.editing)
{
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
please help me to find the solution, I'm not know much with iOS7 enviroment.Thanks!
Thanks all for your advice, and this solution can solved it, I make it into custom cell
UIImageView* backgroundImage;
//Variable for animation delete button
// Keep the ContactView in normal state
BOOL bFirstEditingCell;
BOOL bShownRedMinus;
BOOL bShownDeleteButton;
CGRect frameOfContactViewInNormal;
CGPoint centerOfCellInNormal;
UITableViewCellAccessoryType accessoryTypeInNormal;
//
- (id)initWithCoder:(NSCoder *)decoder
{
if (self = [super initWithCoder:decoder])
{
super.backgroundColor = [UIColor clearColor];
self.selectionStyle = UITableViewCellSelectionStyleNone;
backgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"row_gradient" ]];
self.backgroundView = backgroundImage;
bShownDeleteButton = false;
bShownRedMinus = false;
bFirstEditingCell = true;
accessoryTypeInNormal = UITableViewCellAccessoryNone;
}
return self;
}
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
if (!isOS7()) {
return;
}
for (UIView *subview in self.subviews) {
//Keep normal value of contact view and cell
if (bFirstEditingCell ) {
frameOfContactViewInNormal = self->contactView.frame;
frameOfContactViewInNormal.size.width = kContactViewWidth;
centerOfCellInNormal = subview.center;
bFirstEditingCell = false;
}
if (state == UITableViewCellStateDefaultMask) {
self.backgroundView = backgroundImage;
subview.center = centerOfCellInNormal;
//Set for position of speed dial image
CGRect f = frameOfContactViewInNormal;
if (bShownRedMinus) {
f.size.width -= kRedMinusButtonWidth;
}
self->contactView.frame = f;
bShownDeleteButton = false;
self.accessoryType = accessoryTypeInNormal;
}
else if (state == UITableViewCellStateShowingDeleteConfirmationMask)
{
float sectionIndexWidth = 0.0;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
sectionIndexWidth = 30.0;
}
else {
sectionIndexWidth = 15.0;
}
CGPoint center = centerOfCellInNormal;
subview.center = CGPointMake(center.x - sectionIndexWidth, center.y);
self.backgroundView = nil;
//Set width of contact name
UIView* view = [subview.subviews objectAtIndex: 0];
CGRect f = view.frame;
f.origin.x = (kDeleteButtonWidth + sectionIndexWidth);
view.frame = f;
f = frameOfContactViewInNormal;
f.size.width = self.frame.size.width - (kDeleteButtonWidth + sectionIndexWidth);
self->contactView.frame = f;
bShownDeleteButton = true;
bShownRedMinus = false;
accessoryTypeInNormal = self.accessoryType;
self.accessoryType = UITableViewCellAccessoryNone;
}
else if (state == UITableViewCellStateShowingEditControlMask) {
CGRect f = frameOfContactViewInNormal;
f.size.width -= 5;
self->contactView.frame = f;
bShownRedMinus = true;
}
else if (state == 3) { //State for clicking red minus button
CGRect f = frameOfContactViewInNormal;
f.size.width += kRedMinusButtonWidth;
self->contactView.frame = f;
self.backgroundView = nil;
}
}
}
It looks like one of the Bug from iOS 7. For some reason the backgroundView is moved by iOS over the delete button. You can work-around this by sub classing your backgroundView and implementing the setFrame function of your derived view like this :
UITableViewCell delete button gets covered up.
It may also happen when the accesoryView is specified and the editingAccessoryView is nil. Detailed explanation of this issue and solution is mentioned here :
UITableViewCell content overlaps delete button when in editing mode in iOS7.
You do not need to check if the tableView is being edited...just implement:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
Best way to remove this problem is that add an image in cell and set it in Backside.
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bgImg.png"]];
imageView.frame = CGRectMake(0, 0, 320, yourCustomCell.frame.size.height);
[yourCustomCell addSubview:imageView];
[yourCustomCell sendSubviewToBack:imageView];
If your text would overlap the delete button then implement Autolayout. It'll manage it in better way.
One more case can be generate that is cellSelectionStyle would highlight with default color. You can set highlight color as follows
yourCustomCell.selectionStyle = UITableViewCellSelectionStyleNone;
Set your table cell's selection style to UITableViewCellSelectionStyleNone. This will remove the blue background highlighting or other. Then, to make the text label or contentview highlighting work the way you want, use this method in yourCustomCell.m class.
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
if (highlighted)
self.contentView.backgroundColor = [UIColor greenColor];
else
self.contentView.backgroundColor = [UIColor clearColor];
}
I hope it will help you to understand.
Simpler Workaround
Assuming an iOS7 only app, with a technique similar to that linked in the post by Vin above, I believe the approach here: https://stackoverflow.com/a/19416870/535054 is going to be cleaner.
In this approach, you don't need to subclass your backgroundView, which could be different for different cells.
Place the code in the answer I've linked to above, in the root of your custom table cell hierarchy, and all of your table cells (that inherit from it), get the fix whenever they use the backgroundView or selectedBackgroundView properties.
Copy the solution from this gist: https://gist.github.com/idStar/7018104
An easy way to solve this problem is to make the delete confirmation button view as a front view. It can be done by implementing the delegate method layoutSubviews in customtableviewcell.m file.
In my case I solved it by just adding the following code into customtableviewcell.m file. It may be little different according to how the views are placed in your cell. But surely it will give you an idea about how to solve the problem.
- (void)layoutSubviews // called when a interface orientation occur ie. in our case when the '-' button clicks
{
[super layoutSubviews];
for (UIView *subview in self.subviews) { // Loop through all the main views of cell
// Check the view is DeleteConfirmationView or not, if yes bring it into the front
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationView"]) {
[self bringSubviewToFront:subview];// code for bring the view into the front of all subviews
}
}
}
Related
anybody know how to resize the dimmed black overly, once you clicked the search bar ?
i having problem when i clicked cancelled the tableview will expend then animated to disappear.
i using this to resize my result tableview.
-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
tableView.frame =fTableView.frame;//CGRectMake(26, 100, 280, 310); //fTableView.frame;
tableView.backgroundColor = [UIColor colorWithRed:243.0/255.0 green:236.0/255.0 blue:212.0/255.0 alpha:1];
}
when clicked on the search bar, gray overlay are full instead of my defined size.
when clicked cancel button, the view will expend back.
I combined several answers in order to move the dimmed overlay frame.
1: override UISearchDisplayController class
#interface MySearchController : UISearchDisplayController
2: override setActive function
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
[super setActive: visible animated: animated];
//move the dimming part down
for (UIView *subview in self.searchContentsController.view.subviews) {
//NSLog(#"%#", NSStringFromClass([subview class]));
if ([subview isKindOfClass:NSClassFromString(#"UISearchDisplayControllerContainerView")])
{
CGRect frame = subview.frame;
frame.origin.y += 10;
subview.frame = frame;
}
}
}
3: change the xib/storyboard Search Display Controller from UISearchDisplayController to
MySearchController
I thought the searchDisplayController owned a seperate tableview, so my guess is that you would need to resize that one.
Something along the lines of: <yourSearchViewController>.view.frame =self.tableView.frame;
or if you don't have it as class variable, in a method which receives it as argument, eg:
-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
controller.view.frame = self.tableView.frame;
tableView.backgroundColor = [UIColor colorWithRed:243.0/255.0 green:236.0/255.0 blue:212.0/255.0 alpha:1];
}
Alternativily you might want to subclass it and override its view properties locally.
Hope this helps!
The UISearchDisplayController does owns its own tableview which not as easy to tame.
I came across something like this and am still looking for a better solution.
-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[controller.searchResultsTableView setDelegate:self];
CGFloat gr = 12.0;
controller.searchResultsTableView.backgroundColor = [UIColor colorWithRed:gr green:gr blue:gr alpha:0.0];
[controller.searchResultsTableView setSeparatorStyle:UITableViewCellSelectionStyleNone];
CGRect searchTableFrame = CGRectMake(7, 105, 305, 292);
[controller.searchResultsTableView setFrame:searchTableFrame];
}
The above code does sets the background to transparent but seems to silently ignore the frame size.
EDIT:SOLVED
I found the robust solution to this here.
This saved my life.
i will like to know how do i need to change a UISearchBar from the default round curve to a rectangle.
for (UIView *searchBarSubview in [mySearchBar subviews]) {
if ([searchBarSubview conformsToProtocol:#protocol(UITextInputTraits)]) {
#try {
[(UITextField *)searchBarSubview setBorderStyle:UITextBorderStyleRoundedRect];
}
#catch (NSException * e) {
// ignore exception
}
}
}
Swift 4:
mySearchBar.subviews().forEach { searchBarSubview in
if searchBarSubview is UITextInputTraits {
do {
(searchBarSubview as? UITextField)?.borderStyle = .roundedRect
} catch {
// ignore exception
}
}
}
Much better in my opinion:
UITextField *txfSearchField = [_searchBar valueForKey:#"_searchField"];
txfSearchField.borderStyle = UITextBorderStyleNone;
Simple add background image, left view and right view for your TextField.
Example below
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 10., nameField.bounds.size.height)];
nameField.leftView = leftView;
nameField.leftViewMode = UITextFieldViewModeAlways;
leftView release];
UISearchBar has the round curve, and it is fix if you like to make it rectangle you have to use custom search bar with rectangular image as like of search bar and 1 uibutton and UItextfield, and your own searching logic
In the target image I don't see the default shadow, so I'll mention that setting the background property to nil will remove it. I needed to do this in my project and removing the image and manipulating the border works well. I had to cast the control to get to the background property.
UITextField * x = (UITextField*)searchBarSubview;
x.background = nil;
#Keller thanks for the tip for finding the control.
I would use a UIView, with these features:
- set your frame.
- import CoreGraphics in your class
- set a white background of the view
- set view.layer.cornerRadius=10;
- set view.layer.borderWidth=8;
- set view.layer.borderColor=[UIColor blackColor].CGColor;
- insert a label(with a clear background) inside the created view
For the button on the left i would use an uiimage, for the right button set textField.clearButtonMode= UITextFieldViewModeAlways;
Hope this helps.
Why not use the UIAppearance protocol?
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar class]]] setBorderStyle:UITextBorderStyleRoundedRect];
In our earlier project we also tried to implement in such manner but customization is not possible.
Could you try this.
for (UIView *searchBarSubview in [search_bar subviews]) {
if ([searchBarSubview conformsToProtocol:#protocol(UITextInputTraits)]) {
if([searchBarSubview isKindOfClass:[UITextField class]])
{
[(UITextField *)searchBarSubview setBorderStyle:UITextBorderStyleRoundedRect];
}
}
}
I also recently achieved this in a project by traversing the subviews of the UISearchBar object. However, the text field was not an immediate child as the accepted answer suggested, but a subview of another subview of it. The inner view hierarchy was probably changed at some point. (SDK 8.4)
+ (void)setSearchBar:(UISearchBar *)searchBar cornerRadius:(CGFloat)radius {
//set searchbar corner radius
for(UIView *possibleSearchBarTextFieldSuperview in [searchBar subviews]) {
if([[possibleSearchBarTextFieldSuperview subviews] count] > 0) {
for(UIView *possibleInnerSearchBarTextField in [possibleSearchBarTextFieldSuperview subviews]) {
if([possibleInnerSearchBarTextField conformsToProtocol:#protocol(UITextInputTraits)]) {
possibleInnerSearchBarTextField.layer.cornerRadius = radius;
possibleInnerSearchBarTextField.layer.masksToBounds = YES;
return;
}
}
}
}
}
This method does not use any undocumented methods so it's probably App Store safe, although it is susceptible to stop working with future changes to the SDK.
Swift 3
let textFieldInsideUISearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideUISearchBar?.borderStyle = .none
textFieldInsideUISearchBar?.backgroundColor = UIColor.white
The way that it worked with me on Swift 4 is to Subclass the UISearchBar and make the necessary adjustment there without any kind of hacking or workaround ...
I have used the Subclass used in this tutorial and it worked like charm
Here is the code from the example used
//
// SearchBar.swift
// Yomu
//
// Created by Sendy Halim on 9/3/17.
// Copyright © 2017 Sendy Halim. All rights reserved.
//
import Foundation
import UIKit
class SearchBar: UISearchBar {
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
searchBarStyle = .minimal
// Create search icon
let searchIcon = UIImageView(image: #imageLiteral(resourceName: "search"))
let searchImageSize = searchIcon.image!.size
searchIcon.frame = CGRect(x: 0, y: 0, width: searchImageSize.width + 10, height: searchImageSize.height)
searchIcon.contentMode = UIViewContentMode.center
// Configure text field
let textField = value(forKey: "_searchField") as! UITextField
textField.leftView = searchIcon
textField.borderStyle = .none
textField.backgroundColor = UIColor(hex: "#F7F7F7")
textField.clipsToBounds = true
textField.layer.cornerRadius = 6.0
textField.layer.borderWidth = 1.0
textField.layer.borderColor = textField.backgroundColor!.cgColor
textField.textColor = UIColor(hex: "#555555")
}
}
I am trying to add two UIScrollView's into one UIView, Both the scrollView's show up properly, the problem that I am having is how to determine which scrollView is scrolled because based on that I have to populate the images. This is what I am doing:
I have a ViewController with UIScrollViewDelegate.
In the loadView method of my ViewConroller, I do the following:
CGRect scrollViewFrame1;
CGPoint scrollViewPoint1;
scrollViewPoint1.x = 0;
scrollViewPoint1.y = 57;
CGSize scrollViewSize1;
scrollViewSize1.width = 320;
scrollViewSize1.height = 154;
scrollViewFrame1.size = scrollViewSize1;
scrollViewFrame1.origin = scrollViewPoint1;
CGRect scrollViewFrame2;
CGPoint scrollViewPoint2;
scrollViewPoint2.x = 0;
scrollViewPoint2.y = 258;
CGSize scrollViewSize2;
scrollViewSize2.width = 320;
scrollViewSize2.height = 154;
scrollViewFrame2.size = scrollViewSize2;
scrollViewFrame2.origin = scrollViewPoint2;
scrollView1 = [[UIScrollView alloc] initWithFrame:scrollViewFrame1];
scrollView2 = [[UIScrollView alloc] initWithFrame:scrollViewFrame2];
And then:
scrollView1.delegate = self;
scrollView2.delegate = self;
And then:
[self.view addSubView:scrollView1];
[self.view addSubView:scrollView2];
I have one scrollViewDidScroll: method, how do I determine which scrollView this method got invoked by, because based on that i need to populate different images for my scrollView.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//Code to populate the next or previous images for scrollView
// If it was one i am able to show the images
}
Thanks for the help.
Delegate methods send with it the object that sent the message (the UIScrollView in this case). So, all you have to do is check that against your instance variables of scrollView1 and scrollView2.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == scrollView1) {
//do stuff with scrollView1
} else if (scrollView == scrollView2) {
//do stuff with scrollView2
}
}
FYI
You can also set a tag for both of the scrollView to differentiate
scrollView1.tag=10;
scrollView2.tag=11;
[self.view addSubView:scrollView1];
[self.view addSubView:scrollView2];
In your delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView1.tag==10) {
//do stuff with scrollView1
} else if (scrollView2.tag==11) {
//do stuff with scrollView2
}
}
Been searching for this for quite a while, and I still haven't found a way to do it.
I'd like to reproduce the section headers of the iPhone's Spotlight into a UITableView.
"Regular" table view headers stay visible at the top of a section when you scroll, as we all know. But there is one kind of header that I've never seen elsewhere than in the Spotlight page of Springboard: there, the headers span the whole height of the section and are not stuck on the top of the section, but on the left side.
How the heck is that achieved?
Good question. I made a little experiment. It almost looks like the view from spotlight. But it's lacking one import feature. The lower "image" doesn't push the upper image to the top if they collide.
I doubt that there is a built in solution without the use of private frameworks.
I achieved this:
As you can see the two header images at the top overlap. They don't push each other like normal headers to. And I had to deactivate the cell separators. If I would use them they would appear at the whole cell. So you have to draw them yourself. Not a big deal.
But I have no idea how I could fix the overlapping.
Here is the code that made this happen:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 1;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
contentView.backgroundColor = [UIColor lightGrayColor];
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 34, 34)] autorelease];
imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%d", section]];;
[contentView addSubview:imageView];
return [contentView autorelease];
}
Okay I have done something similar to what the music app and spotlight search does.
I have not subclassed UITableView, I have just tracked the sections through it's scrollViewDidScroll method, and added the header views to the left of the tableView (so you will have to put the tableview to the right in your viewController's view, which means you can't use UITableViewController).
this method should be called in the scrollViewDidScroll, ViewDidLoad, and in didRotateFromInterfaceOrientation: (if you support rotation)
keep in mind that you will have to make space in the left equal to the size of the headers in any interface orientation that you support.
-(void)updateHeadersLocation
{
for (int sectionNumber = 0; sectionNumber != [self numberOfSectionsInTableView:self.tableView]; sectionNumber++)
{
// get the rect of the section from the tableview, and convert it to it's superview's coordinates
CGRect rect = [self.tableView convertRect:[self.tableView rectForSection:sectionNumber] toView:[self.tableView superview]];
// get the intersection between the section's rect and the view's rect, this will help in knowing what portion of the section is showing
CGRect intersection = CGRectIntersection(rect, self.tableView.frame);
CGRect viewFrame = CGRectZero; // we will start off with zero
viewFrame.size = [self headerSize]; // let's set the size
viewFrame.origin.x = [self headerXOrigin];
/*
three cases:
1. the section's origin is still showing -> header view will follow the origin
2. the section's origin isn't showing but some part of the section still shows -> header view will stick to the top
3. the part of the section that's showing is not sufficient for the view's height -> will move the header view up
*/
if (rect.origin.y >= self.tableView.frame.origin.y)
{
// case 1
viewFrame.origin.y = rect.origin.y;
}
else
{
if (intersection.size.height >= viewFrame.size.height)
{
// case 2
viewFrame.origin.y = self.tableView.frame.origin.y;
}
else
{
// case 3
viewFrame.origin.y = self.tableView.frame.origin.y + intersection.size.height - viewFrame.size.height;
}
}
UIView* view = [self.headerViewsDictionary objectForKey:[NSString stringWithFormat:#"%i", sectionNumber]];
// check if the header view is needed
if (intersection.size.height == 0)
{
// not needed, remove it
if (view)
{
[view removeFromSuperview];
[self.headerViewsDictionary removeObjectForKey:[NSString stringWithFormat:#"%i", sectionNumber]];
view = nil;
}
}
else if(!view)
{
// needed, but not available, create it and add it as a subview
view = [self headerViewForSection:sectionNumber];
if (!self.headerViewsDictionary && view)
self.headerViewsDictionary = [NSMutableDictionary dictionary];
if (view)
{
[self.headerViewsDictionary setValue:view forKey:[NSString stringWithFormat:#"%i", sectionNumber]];
[self.view addSubview:view];
}
}
[view setFrame:viewFrame];
}
}
also we need to declare a property that would keep the views that are visible:
#property (nonatomic, strong) NSMutableDictionary* headerViewsDictionary;
these methods return the size and X axis offset of the header views:
-(CGSize)headerSize
{
return CGSizeMake(44.0f, 44.0f);
}
-(CGFloat)headerXOrigin
{
return 10.0f;
}
I have Built the code so that any header view that's not needed gets removed, so we need a method that would return the view whenever needed:
-(UIView*)headerViewForSection:(NSInteger)index
{
UIImageView* view = [[UIImageView alloc] init];
if (index % 2)
{
[view setImage:[UIImage imageNamed:#"call"]];
}
else
{
[view setImage:[UIImage imageNamed:#"mail"]];
}
return view;
}
here's how it will look :
How it will look in lanscape, I have used contraints to give 44px in the left of the tableView
hope this helps :).
Good news: See answer of How to achieve an advanced table view header
result http://i.minus.com/jyea3I5qbUdoQ.png
Is there a way to control the position of the auto correct view that pops up while typing in a UITextField?
By default it appears to always appear below the text field. However in Apple's apps like SMS it sometimes appears above the text field.
For text fields aligned right above the keyboard the auto correct is blocked by the keyboard and not usable.
The position of the auto correction prompt is determined by the firstRect... method of the UITextInput protocol. Unfortunately UITextField uses a private class as delegate for this protocol so you cannot subclass and override it.
You COULD however implement your own UITextField replacement by drawing the contents yourself (like with CoreText), implement your own selection and loupe handling and then you would be able to affect the position of the auto correction prompt. Though it's designed to always be below the edited text, so you would have to essentially lie on the firstRect ... method.
Long story short: it's too much hassle.
One answer it worked for me is to use setInputAccessoryView method of the textview/textview.
I have a toolbar which contains the textView.
If I set the toolbar as the inputaccessoryview of the textfield, and set to NO clipsToBound property of the toolbar, I don't know exactly why, but the balloon appears above the keyboard
Here is a solution using private APIs as there are no ways to do this using public APIs.
Hunt through the application's -windows property to find the private UITextEffectsWindow window and figure out its frame. This is the keyboard
Hunt through the TextView's subviews to find the private UIAutocorrectInlinePrompt view. This is the autocorrect bubble.
Move that subview into a separate wrapper view (added to the TextView) and then move that wrapper view so it's above the above-mentioned keyboard window.
Using swizzled layoutSubViews,
- (void) moveSpellingCorrection {
for (UIView *view in self.subviews)
{
if ([[[view class] description] isEqualToString:#"UIAutocorrectInlinePrompt"])
{
UIView *correctionShadowView = nil; // [view correctionShadowView];
for (UIView *subview in view.subviews)
{
if ([[[subview class] description] isEqualToString:#"UIAutocorrectShadowView"])
{
correctionShadowView = subview;
break;
}
}
if (correctionShadowView)
{
UIView *typedTextView = nil; //[view typedTextView];
UIView *correctionView = nil; //[view correctionView];
for (UIView *subview in view.subviews)
{
if ([[[subview class] description] isEqualToString:#"UIAutocorrectTextView"])
{
if (CGRectContainsRect(correctionShadowView.frame,subview.frame))
{
correctionView = subview;
}
else
{
typedTextView = subview;
}
}
}
if (correctionView && typedTextView)
{
CGRect textRect = [typedTextView frame];
CGRect correctionRect = [correctionView frame];
if (textRect.origin.y < correctionRect.origin.y)
{
CGAffineTransform moveUp = CGAffineTransformMakeTranslation(0,-50.0);
[correctionView setTransform: moveUp];
[correctionShadowView setTransform: moveUp];
CGRect windowPos = [self convertRect: view.frame toView: nil ];
[view removeFromSuperview];
[self.window addSubview: view];
view.frame = windowPos;
}
}
}
}
}
}
For more details check.
In my case, the AutoCorrect view's position is shifted because of the font's leading (line gap).
So, I tried to move it up the leading px by using firstRect function as the code below.
class CustomTextView: UITextView {
override var font: UIFont? {
didSet {
if let font = font {
leadingFont = font.leading
} else {
leadingFont = 0
}
}
}
var leadingFont: CGFloat = 0
override func firstRect(for range: UITextRange) -> CGRect {
var newRect = super.firstRect(for: range)
newRect.origin = CGPoint(x: newRect.origin.x, y: newRect.origin.y - leadingFont)
print("newRect: \(newRect)")
return newRect
}
}
Although it's UITextView but you can do the same thing with UITextField