UIButton position to right side of UITextView in a growing textView - swift

I have a UIButton() in a textView.
let expanButtonHeight = bounds.size.height
expanButton.frame = CGRect(x: textView.bounds.size.width - expanButtonHeight, y: 0, width: expanButtonHeight, height: expanButtonHeight)
self.addSubview(expanButton)
self.layoutIfNeeded()
But when I type text in my textView the expanButton doesn't change. How do I keep the UIButton position fixed at right side of UITextView even when textView is growing in width?
This is the problem I'm facing:
I want the button to stay at end of textView:

With what you wish, I suggest you to have a UIView as a parent container of UITextView and UIButton. Your button should add to UIView instead of adding to UITextView. if the UITextView grow, make the parent container UIView grow as well and you can stick your UIButton at any place you want based on UIView.

Related

Adjust vertical position of UIBarButtonItem title inside UIToolbar

Is it possible to adjust the title of a UIBarButtonItem inside an UIToolbar?
I've tried the following lines of code without success:
UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset(horizontal: 30, vertical: 30), forBarMetrics: UIBarMetrics.Default)
And this one:
self.setTitlePositionAdjustment(UIOffset(horizontal: 30, vertical: 30), forBarMetrics: UIBarMetrics.Compact)
Offset an UIBarButtonItem (Text!) inside a UIToolBar vertically seems not to work with Xcode 7 (Beta 6).
You are right, according to the docs, this should do it:
UIBarButtonItem.appearance().setTitlePositionAdjustment
either globally in AppDelegate:
UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset(horizontal: 30, vertical: 30), forBarMetrics: UIBarMetrics.Default)
or locally with the item outlet itself:
(Swift)
self.myBarItem.setTitlePositionAdjustment(UIOffset(horizontal: 30, vertical: 30), forBarMetrics: UIBarMetrics.Default)
(Obj C)
[self.myBarItem setTitlePositionAdjustment:UIOffsetMake(30, 30) forBarMetrics: UIBarMetricsDefault];
Is this a bug with Appearance?
Change the baselineOffset of the text.
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.someFunction))
let attributes = [NSAttributedString.Key.baselineOffset: NSNumber(value: -3)]
doneButton.setTitleTextAttributes(attributes, for: .normal)
A negative baselineOffset will shift the title text down, a positive value will shift it up. 0 is the default value.
I tested this on iOS 11.
I was frustrated with this too so I subclassed UIBarButtonItem to work as expected. Taking from this answer I came up with this:
#interface TitleAdjustingBarButtonItem(){
UIView* _parentView;
UIButton* _button;
}
#end
#implementation TitleAdjustingBarButtonItem
-(id) initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action{
_button = [[UIButton alloc] init];
[_button setTitle:title forState:UIControlStateNormal];
[_button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[_button sizeToFit];
_parentView = [[UIView alloc] initWithFrame:_button.bounds];
[_parentView addSubview:_button];
return [super initWithCustomView:_parentView];
}
#pragma mark - property setters -
-(void) setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics{
[_button sizeToFit];
_parentView.bounds = CGRectMake(0.0, 0.0, _button.bounds.size.width - (adjustment.horizontal * 2.0), _button.bounds.size.height - (adjustment.vertical * 2.0));
}
Admittedly it does not account for the different bar metrics but for default metrics I've gotten this to work pretty well.
I found a workaround. I was trying to change the position of the back button title in the navigation bar. The title seems to be fixed in the lower left corner of it. So I changed the position of the whole navigation bar and adjusted its size accordingly so it would seem to be the same size in the view.
let xDisplacement: CGFloat = -25 // Adjust horizontal position
let yDisplacement: CGFloat = 9 // Adjust vertical position
let h = (self.viewIfLoaded?.frame.size.height)!/12 //Set your height in reference to the size of the view
let w = (self.viewIfLoaded?.frame.size.height)!//Set your width in reference to the size of the view
//Change placement adjusting size for change.
self.navigationController?.navigationBar.frame = CGRect(x: xDisplacement, y: yDisplacement, width: w-xDisplacement, height: h-yDisplacement)
In my case the background is transparent so the adjusting doesn't really make a difference. Also I was trying to move the title left. I think that is the only situation where de adjusting is useful.
Anyway, just a workaround, but I hope it helps.
Total noob here, feedback appreciated.
Suggestion for this: Use UIButton inside of UIBarButtonItem.
I have a toolbar that has two taller buttons in it on either side (Up Button and Down Button in the screenshot) and when the user initiates an action I show two buttons in the toolbar that only have text on them. When I originally put them on the toolbar as UIBarButtonItem objects, they sat very low on the toolbar and nothing I tried would get them to sit higher. Their position made it hard for the user to press them on iPadPro devices because the bar at the bottom of the device was kind of blocking them.
I found that if I dragged a UIButton to the toolbar, IB would automatically put those inside a UIBarButtonItem as the view, and they were centered vertically in the toolbar. I was then able to adjust the content Insets for the UIButton like I normally would and the change was reflected properly. (Since I was only looking to get them centered vertically, merely using UIButtons worked for me). Remember that any IBActions you hook up should be hooked up to the UIButtons.
I did this with XCode 10.1 and swift 4.

how to add a subview to a tableView cell.contentView swift

I'm a little confused where should I declare and how to add a subView to a cell to make the cell shorter in width.
I tried to use func viewWillLayoutSubviews(){} in my tableViewCell class but I can't access the tableView from there...weird..
What do I need to subclass for this to work and where do I need to insert this code?
Currently this code just adds a subview to the cell and kind of floats on top of the cell instead of containing the cell. I'm using it in cellForRowAtIndexPath.
let testFrame : CGRect = cell.contentView.frame
var testView : UIView = UIView(frame: testFrame)
testView.backgroundColor = UIColor.redColor()
testView.alpha=0.5
testView.bounds = CGRectMake(cell.bounds.origin.x,
cell.bounds.origin.y,
cell.bounds.size.width - 50,
cell.bounds.size.height);
//TableViewCell.addSubview(testView)
cell.contentView.addSubview(testView)
return cell
A subview is added inside of the cell, you are adding testView as a subview of the cell's content view. The frame of testView will be relative to the cell's content view (testView's superview).
It is not a good idea to change the width of UITableViewCell because there may be unintended side effects. You can override setFrame in a subclass of UITableViewCell which you return from cellForRowAtIndexPath:. More info here: How to set the width of a cell in a UITableView in grouped style
You should look at UICollectionView if you need cells that are not full width or make your table view the width you need.

Swift: How to resize UIView and keep contents centered?

I have a UIView ("myUIView") in my ViewController ("mainView") that has a UILabel ("myUILabel") inside, centered vertically with autolayout constraints. I'm animating this UIView to change its height.
Originally, I thought auto layout would keep track of the animation/change and keep the UILabel centered, but instead the UILabel acts as though it is constrained to the top of the UIView.
The UILabel isn't in the animation code itself. Code for reference:
UIView.animateWithDuration(currentAnimationTime, delay: 0.0, options: .CurveEaseOut, animations: {
self.myUIView.frame = CGRectMake(0, self.mainView.frame.height * 0.2, self.mainView.frame.width, self.mainView.frame.height * 0.6 )
}, completion: nil)
How can I increase the UIView's height and keep my UILabel entered vertically? Will I need to add something that directly affects the UILabel itself, or am I going about the resize itself (CGRectMake) all wrong?
I have had luck by calling layoutIfNeeded on the animated view inside the animation.
It would be preferable to create an outlet for the height constraint of the view and then set the constant of that constraint rather than constructing a CGRect. Change the constant outside the animation as demonstrated in this answer.

UIImageView caching while tableviewcell height is reduced

I have UITableview which has custom cells with UIImageViews. In the UITableview I am increasing the height of the cell using didSelectRowAtIndexPath method. Also i am adding method to increase cell height and revert to normal height.
When i tap on the cell the height is increasing , when i tap on the cell again (in order to make the tableviewcell return to default height) while in transition the image which is on tableviewcell is stays like its shown below and goes back to default height ..(i dont know how the image is being displayed while in transition)
-(void) zoomOutProperties
{
fruitImage.frame=CGRectMake(0.0, 46.0, 320.0, 83.5);
backgroundCellImage.frame=CGRectMake(0.0, 0.0, 320.0,129.5);
customCellView.frame=CGRectMake(0.0, 0.0, 320.0, 129.5); // UIView
}
Please note ::
[UIImage imageNamed:#""] caches the image. Instead use: [UIImage imageWithContentsOfFile:#""]
To make the image equal to the UIImageView size, you should use:
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
Refer: https://stackoverflow.com/a/9945160/667586
Your numbers for the frames don't add up very well. For instance, in zoomInProperties, you set fruitImage to have origin.y at 73.0, but its height is 82.5 (fractional pixels?) so it will end at 155.5, which is below the bottom of the customCellView which is 135.6. If the outer cell UIView is not set to clip, then the image will draw partly into the next cell.
Also, by setting the inner frames before setting the outer customCellView, you could have 2 changes to the sizes if they have autoResizeMask applied.

How to make a UITextView Expand with the text like the Notes app

How can you make a UITextView expand with the text that is inside of it?
you could try this...
UITextView *textView; // your UITextView
NSString *text; // the text that you want to place in the UITextView
UIFont *textViewFont; // the font that you are using for your UITextView
CGSize size = {255,2000.0f}; //The default width, and max height you want to use
CGSize newSize = [text sizeWithFont:textViewFont
constrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
textView.frame = CGRectMake(0,0,newSize.width, newSize.height);
You can try this..
CGRect frame = textView.frame;
frame.size.height = [textView contentSize].height;
textView.frame = frame;
Are you using UITextView inside UITableView?
Let's suppose you are using UITextView inside UITableView. In order to make UITextView height dynamic(As per the content inside it) we need to take care of following things:-
Make sure UITextView constraints are properly given. e.g: I had used XIB for tableview cell and inside cell I had a UITextView. So, I will give constraint to UITextView 0 to all four sides e.g: Top, bottom, leading, trailing. (Depends on your requirements).
Make sure UITextView attribute, autoscroll is disabled. It should be off.
Make sure TableView cell height is UITableView.automaticDimension
Now inside your 'textViewDidChange' delegate method, Just add this below mentioned code:
UIView.setAnimationsEnabled(false)
tableView?.beginUpdates()
tableView?.endUpdates()
UIView.setAnimationsEnabled(true)
Now your textView will auto expand, while you are typing init.