I have created a UIScrollView in a ContainerView and a UITextView as a subview of UIScrollView. I initialize the textView with scrollEnabled set to true. Now based on the contentOffset.y of the scrollView, I want to keep toggling scrollEnabled on the textView. But for some reason, once I set scrollEnabled to false, I can't seem to enable scroll again...
override func viewDidload() {
self.scrollView = UIScrollView(frame: CGRectMake(...))
self.scrollView.delegate = self
self.view.addSubview(self.scrollView)
self.textView = UITextView(frame: CGRectMake(...))
self.textView.scrollEnabled = true
self.textView.userInteractionEnabled = true
self.scrollView.addSubview(self.textView)
}
func scrollViewDidScroll(scrollView: UIScrollView) {
if self.scrollView.contentOffset.y >= 180 {
self.textView.scrollEnabled = true // This does not work!
} else {
self.textView.scrollEnabled = false // This works!
}
}
I was faced with the same problem, and eventually dealt with it by subclassing UITextView as shown below:
class TextView: UITextView {
var displayScrolling: Bool = true {
didSet {
self.showsVerticalScrollIndicator = displayScrolling
}
}
override var contentOffset: CGPoint {
set {
if displayScrolling {
super.contentOffset = newValue
}
}
get {
return super.contentOffset
}
}
}
At init (or in interface builder), set your instance of TextView to allow scrolling. In order to not scroll, set the 'displayScrolling' var to false. When you want to scroll, set 'displayScrolling' to true.
It will be scroll enabled if the text is longer.
I wish you luck!
Related
Here is the design I'm looking to achieve.
Seems easy enough to use a UITableView with UITableView.Style.insetGrouped and three sections. Then for the row in the second section, I figured I'd apply the old trick of overriding the cell's setFrame: method to inset the trailing edge, add a button outside the bounds, set clipsToBounds = false on both the cell and the cell's content view, and override point(inside:with:) to make sure the button is tappable.
However, the cell's clipsToBounds property always reverts to true and the button is not visible. Even if I subclass UITableViewCell and override clipsToBounds to always return false, the button is still not visible. However, if I change the table view's style to plain or grouped, the button is visible and tappable.
Obviously, there are other ways to achieve this design such as having each "section" be its own table view or setting my own view with corner radius to the cell's backgroundView. But, why does my approach not work specifically for the insetGrouped style and is there any workaround?
class InsetButtonTableViewCell: UITableViewCell {
#IBOutlet var buttonStack: UIStackView!
override var frame: CGRect {
get { super.frame }
set {
guard let buttonStack = buttonStack else { super.frame = newValue; return }
var insetFrame = newValue
insetFrame.size.width -= buttonStack.frame.width
super.frame = insetFrame
}
}
override func awakeFromNib() {
super.awakeFromNib()
clipsToBounds = false
contentView.clipsToBounds = false
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
frame.union(buttonStack.frame).contains(point)
}
}
I have a uiview in my app. I want to show the uiview when uiscrollview Y position changes. I tried some stackoverflow suggestion but can't get the expected result.
Here's my code that i tried:
if (topScrollView.contentOffset.y) >= 30{
slideInSearchView.isHidden = false
} else {
slideInSearchView.isHidden = true
}
Make sure code is inside scrollViewDidScroll
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (topScrollView.contentOffset.y) >= 30{
slideInSearchView.isHidden = false
} else {
slideInSearchView.isHidden = true
}
}
any chances to change UISearchBar's UITextField height?
I tried almost all solutions which I've could found, but all are unsuccessful.
Updated:
I realized that ios13 searchBar doesn't contains UITextField, but contains UISearchBarTextField class
and here is hierarchy
as I understood we have to looking for the new class for iOS13 instead of UITextField
I've tried looping and search TextField
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
for subView in searchBar.subviews {
for subsubView in subView.subviews{
for subsubsubView in subsubView.subviews{
if #available(iOS 13.0, *) {
if let textField = subsubsubView as? UISearchTextField{
var bounds: CGRect
bounds = textField.frame
bounds.size.height = 40 //(set height whatever you want)
textField.bounds = bounds
textField.layoutIfNeeded()
}
} else {
if let textField = subsubView as? UITextField {
var bounds: CGRect
bounds = textField.frame
bounds.size.height = 40 //(set height whatever you want)
textField.bounds = bounds
}
}
}
}
}
}
and debugger goes into condition and found UITextField and changed height, but on device - there no height changes
What I finally did was to set an UIImageView as a container for the UISearchBar.
Didn't work with a simple UIView, I guess it had to do with intrinsic content size?
func showSearchBar() {
self.searchNavigationItem?.setRightBarButton(nil, animated: false)
guard let searchBar = self.searchBar else {
assert(false, "Need a search bar to display")
return
}
self.searchContainer = UIImageView()
self.searchContainer?.isUserInteractionEnabled = true
let image = // Some image with the corresponding size.
self.searchContainer?.image = image
self.searchContainer?.alpha = 0
self.searchContainer?.frame = // Same size as the image
// Here you add the searchContainer into the titleView.
self.searchNavigationItem?.titleView = self.searchContainer
searchBar.translatesAutoresizingMaskIntoConstraints = false
// Create top/bottom/leading/trailing constraints
self.searchContainer?.addSubview(searchBar)
searchBar.sizeToFit()
self.searchContainer?.addConstraints([topConstraint, bottomConstraint, leadingConstraint, trailingConstraint])
self?.searchContainer?.alpha = 1
}
I have a chat app and I'm trying to show a custom view that I've made when the user scrolls to the top, also hide it if it's on the bottom of tableview. (like whatsapp does it)
To be honest I'm struggling with the logic of show/hide button.
Tried to save the contentOffset.y of my tableview right after I reload the data so I'll know that's the bottom, and if it's smaller to show the custom view, but mainTableView.contentOffset.y it's always 0.
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
if (scrollView == mainTableView) {
print(mainTableView.contentOffset.y)
if let point = startingPointForView {
//where var startingPointForView: CGFloat?
// and tried to save it after I reload the data
//self.startingPointForView = self.mainTableView.contentOffset.y
// but it's always 0
}
// Show and hide button logic
}
}
An image of what I m trying to achieve: https://imgur.com/ZkYEi2P
try this code to hide/show custom view according to UIscrollview contentOffset
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let scrollViewContentHeight = scrollView.contentSize.height
let scrollViewHeight = scrollView.frame.height
if scrollView.contentOffset.y < (scrollViewContentHeight - scrollViewHeight){
//Custom view show
}else{
//Custom view Hide
}
}
May be this code will help you
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.panGestureRecognizer.translation(in: scrollView).y > 0 {
// down
button.isHidden = false
} else {
// up
button.isHidden = true
}
}
For someone who is looking to hide a button when tableview is scrolling can use below code:
var previousContentOffset: CGFloat = CGFloat()
extension YourViewController: UIScrollViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.yourTableView{
let currentContentOffset = scrollView.contentOffset.y
if (currentContentOffset > previousContentOffset) {
// scrolling towards the bottom
if scrollView.contentOffset.y > 50 {
self.yourButton.isHidden = true
} else {
self.yourButton.isHidden = false
}
} else if (currentContentOffset < previousContentOffset) {
// scrolling towards the top
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
// Change 10.0 to adjust the distance from bottom
if maximumOffset - currentContentOffset <= 10.0 {
self.yourButton.isHidden = true
} else {
self.yourButton.isHidden = false
}
}
previousContentOffset = currentContentOffset
}
}
}
I have UIButton inside cell of UITableView, When i touch the button it is actually working but the animation of highlighted is not being seen, I have tried setting delaysContentTouches = false on viewDidLoad and also on IB
I even tried to find UIScrollVIew of table view so that i can set that properties to false, like...
for cls in cell.subviews
{
println("name of class is ::\(NSStringFromClass(cls.classForCoder))")
if NSStringFromClass(cls.classForCoder) == "UITableViewCellScrollView"
{
cls.scrollView.delaysContentTouches = false
break
}
}
Thanks in advance!
UITableView subclass
override public var delaysContentTouches: Bool {
didSet {
if let subviews = self.subviews as? [UIView] {
for view in subviews {
if let scroll = view as? UIScrollView {
scroll.delaysContentTouches = delaysContentTouches
}
break
}
}
}
}