what is the best way to add a bottom line border to a TextView
?
i have tried this but it seems it doesn't work. It is affected by the scrolling ability of the textview
and the line is being drawn in the middle of the TextView
func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.CGColor
border.frame = CGRectMake(0, self.frame.size.height - width, self.frame.size.width, width)
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
Edit: The TextView has a dynamic height.
Swift 4 Version
func addBottomBorderWithColor() {
let border = CALayer()
border.backgroundColor = UIColor.black.cgColor
border.frame = CGRect(x: 0, y: yourTextArea.frame.height - 1, width: yourTextArea.frame.width, height: 1)
yourTextArea.layer.addSublayer(border)
self.view.layer.masksToBounds = true
}
Update:
I thought a lot about my original solution.
If you are subclassing UITextView
to add a bottom line, then the bottom line had better be a subview of the text view itself, rather than its super view's.
And finally, I figure out one solution that can add bottom line as a subview of TextView
itself and the bottom line will not move when the user scrolls the text of TextView
. In your view controller, you can also change the frame of TextView
dynamically, and the bottom line will also stick to the the bottom.
Here is the reference code:
import UIKit
class TextView: UITextView {
var border: UIView
var originalBorderFrame: CGRect
var originalInsetBottom: CGFloat
deinit {
removeObserver(self, forKeyPath: "contentOffset")
}
override var frame: CGRect {
didSet {
border.frame = CGRectMake(0, frame.height+contentOffset.y-border.frame.height, frame.width, border.frame.height)
originalBorderFrame = CGRectMake(0, frame.height-border.frame.height, frame.width, border.frame.height);
}
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "contentOffset" {
border.frame = CGRectOffset(originalBorderFrame, 0, contentOffset.y)
}
}
func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
border.backgroundColor = color
border.frame = CGRectMake(0, frame.height+contentOffset.y-width, self.frame.width, width)
originalBorderFrame = CGRectMake(0, frame.height-width, self.frame.width, width)
textContainerInset.bottom = originalInsetBottom+width
}
}
Note: Since I used to write code in Objective-C, I am not familiar with Swift. The code above is only for your reference (though I have tested the corresponding Objective-C code, and it works as expected):
As you can see, there is no initialisation code. I have tried to write such code, but it always shows an error and I still have no idea about that. Just make sure to add the below code to your TextView
initialisation code:
border = UIView()
addSubview(border)
originalInsetBottom = textContainerInset.bottom
addObserver(self, forKeyPath: "contentOffset", options: .New, context: nil)
I am not familiar with the concept of optional value, wrap, unwrap... So you should add ?
, !
to the code if needed.
Original answer:
Does self
in your code mean TextView
?
If so, when you add border
as a sublayer of the TextView
, the border
will move up and down when the user scrolls the text of TextView
.
Try to add border
as a sublayer of TextView
's super view rather than TextView
itself.
Here is the code (Note that I change border
from CALayer
to UIView
):
func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
let border = UIView()
border.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y+self.frame.height-width, textView.frame.width, width)
border.backgroundColor = color
self.superview!.insertSubview(border, aboveSubview: textView)
}
Here is the capture:
PS. I suggest you to change the second paramter name from width to height since width is ambiguous in this context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With