So, I'm having issues in a project where certain strings are not being rendered properly in some old iPhones with certain iOS versions (specifically it does not work for iPhone 5 with iOS10, while it does for iOS9.3, oddly enough). To reduce the issue, I wrote this code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Long HTML, although we'll make it even larger to prove a point
let string = "<h1>Thing 1</h1><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p><h1>Thing 2</h1><p>Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. </p><h1>Thing 3</h1><p>Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. </p><h1>Thing 4</h1><p>Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. </p><h1>Thing 5</h1><p>Integer lacinia sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet. Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede. Ut orci risus, accumsan porttitor, cursus quis, aliquet eget, justo. Sed pretium blandit orci. </p><h1>Thing 6</h1><p>Ut eu diam at pede suscipit sodales. Aenean lectus elit, fermentum non, convallis id, sagittis at, neque. Nullam mauris orci, aliquet et, iaculis et, viverra vitae, ligula. Nulla ut felis in purus aliquam imperdiet. Maecenas aliquet mollis lectus. Vivamus consectetuer risus et tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. </p>"
let attrStr = try! NSAttributedString(
data: (string + string + string + string + string + string + string + string).data(using: String.Encoding.unicode,allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
label.attributedText = attrStr
label.backgroundColor = UIColor(red:0.00, green:1.00, blue:0.00, alpha:1.0)
}
}
Simple enough. Of course the real issue is more complicated than this, but the idea is the same.
So, in an iPhone 7, all works fine:
However, when loading it on an iPhone 4s:
When debugging, attrStr seems to be properly set in both cases.
Any ideas? My theory is that older phones are too slow to render this on time, but I'm not quite sure how to workaround this.
Thanks!
EDIT: For those that asked, this is the Storyboard:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="JzW-qG-LFG">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="9PR-d2-hNU">
<objects>
<viewController id="JzW-qG-LFG" customClass="ViewController" customModule="things" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="VGp-YT-QQN"/>
<viewControllerLayoutGuide type="bottom" id="SeT-t7-CD0"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="gtg-CO-E9d">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Id1-A1-RaT">
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="Id1-A1-RaT" secondAttribute="trailing" id="0qp-Rk-PC2"/>
<constraint firstItem="Id1-A1-RaT" firstAttribute="leading" secondItem="gtg-CO-E9d" secondAttribute="leadingMargin" id="3Vc-he-HqH"/>
<constraint firstItem="Id1-A1-RaT" firstAttribute="top" secondItem="VGp-YT-QQN" secondAttribute="bottom" id="7IE-fY-4H0"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="Opz-px-hsl"/>
<connections>
<outlet property="label" destination="Id1-A1-RaT" id="TNv-G9-ASE"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="qlV-6d-ISJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2848.8000000000002" y="-280.20989505247377"/>
</scene>
</scenes>
</document>
The problem here is that UIView has an undocumented height limit of 8192 points. Once the label is 8192 points tall (or taller), it no longer updates the frame buffer. (Presumably the window server simply ignores the label's CALayer once the layer is too large.) Whatever was already in the frame buffer remains there. Presumably the behavior is undefined and may vary across devices and versions of iOS.
(Edit: Having thought about this more, I suspect the limit is 16,384 pixels, not 8,192 points. I don't think the window server deals in points.)
To demonstrate, I took your code and storyboard and added three things:
I constrained the height of your label to be less than or equal to 8185 points.
I added a slider that updates the constant of that height constraint. The slider allows the range 8185 to 8200.
I added another label that displays the constant of the height constraint.
Here's what happens in the iPhone SE simulator running iOS 10.2:
In the demo, you can see that as soon as the height limit crosses 8192 points, the thumb of the slider starts to look smeared, and the height label's text visibly overwrites itself. This is because the green label is no longer updating the frame buffer, so whatever was previously there (as drawn by the slider and the height label) remains, only overwritten where the slider and the height label redraw themselves. As soon as the height goes back down across the 8192 point threshold, the green label draws itself again, cleaning up the mess.
I think you're not seeing this in your iPhone 7 test because the iPhone 7 has a wider screen than the iPhone SE. All iPhones with 3.5 inch and 4 inch screens are 320 points wide. iPhones with 4.7 inch screens are 375 points wide, and iPhones with 5.5 inch screens are 414 points wide.
A wider screen means a wider UILabel. That means more text fits on each line, so the label doesn't have to be as tall to fit all the text. I suspect that on the larger screens, your labels are shorter than 8192 points so they don't hit undefined behavior.
Workarounds:
If you don't intend to let the user scroll to see the entire text, just put a height constraint on the label.
If you want to let the user scroll, try using a UIWebView or WKWebView instead of a UILabel to show the text. I believe these views can handle content more than 8192 points tall.
Incidentally, you're not the first person to run into this problem: UILabel view disappear when the height greater than 8192. However, your question currently has an open bounty, which prevents it from being closed as a duplicate.
You haven't provided any details about your Storyboard, or the settings or constraints for your label.
So I have initiated the label programmatically, and this solution works on the iPhone 4s running iOS 9.3:
Here is the working source code:
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: 0.0, y: 44.0, width: view.frame.size.width, height: view.frame.size.height - 88.0))
label.numberOfLines = 0
label.isUserInteractionEnabled = false
label.contentMode = .left
label.textAlignment = .natural
label.lineBreakMode = .byTruncatingTail
label.baselineAdjustment = .alignBaselines
label.adjustsFontSizeToFitWidth = false
// label.translatesAutoresizingMaskIntoConstraints = false //setting this causes the text to be layout wrong
label.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
view.addSubview(label)
// Long HTML, although we'll make it even larger to prove a point
let string = "<h1>Thing 1</h1><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p><h1>Thing 2</h1><p>Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. </p><h1>Thing 3</h1><p>Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. </p><h1>Thing 4</h1><p>Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. </p><h1>Thing 5</h1><p>Integer lacinia sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet. Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede. Ut orci risus, accumsan porttitor, cursus quis, aliquet eget, justo. Sed pretium blandit orci. </p><h1>Thing 6</h1><p>Ut eu diam at pede suscipit sodales. Aenean lectus elit, fermentum non, convallis id, sagittis at, neque. Nullam mauris orci, aliquet et, iaculis et, viverra vitae, ligula. Nulla ut felis in purus aliquam imperdiet. Maecenas aliquet mollis lectus. Vivamus consectetuer risus et tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. </p>"
let attrStr = try! NSAttributedString(
data: (string + string + string + string + string + string + string + string).data(using: String.Encoding.unicode,allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
label.attributedText = attrStr
label.backgroundColor = UIColor(red:0.00, green:1.00, blue:0.00, alpha:1.0)
}
A complete working project may be downloaded from here.
You are most definitely right. This is a time issue.
NSHTMLTextDocumentType of NSDocumentTypeDocumentAttribute is notorious for taking very long times. As you increase the attrStr string length (adding a couple of + string in data ) you'll be able to replicate the bug for higher end devises after a certain string length. I can reproduce this in an iPhone 6 plus emulator using iOS 10.1, since emulator works with less processing power than the actual devise.
If it's viable to you, you may try using DTCoreText to solve this issue. This library handles html string with methods other than the built in ones, reducing the rendering times. Which will make the bug less noticeable in lower end mobiles.
Related
I have created a view which contains an image and a textview (which changes dynamically) and a button. This view is embedded in UIScrollView. But when I run it the Scrollview is not working. I had this problem in Swift4.
You can refer the link:
https://github.com/sravyagajavalli/Scrolling
It is good to thing about UIScrollView as two separate views. The Frame View (it defines scroll view's size in superview and sibling views) and the Content View (it defines contentSize). In Autolayout point of view are this two views absolutely independent. So you need to define the frameView. And then you need to define autolayout correctly to correct sizing of content View (you do not need to solve the x and y position of course it is matter of contentOffset and scrolling principles). Lets start with example:
1) create UIScrollView add it to superView and define frame View
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
2) From my expirience is always good practice to create clear view and add it as contentView into scrollView for better autolayouting.
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contentView)
NSLayoutConstraint.activate([
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.widthAnchor.constraint(equalTo: view.widthAnchor)
])
notice the last constraint, where we need define the width of this content view as equal as screen - this is important to define that we want vertical scroll. Because of this, we can let autolayout do its job and count the scrollView's content height automatically according to content.
3) Add any content what you want into scrollView
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Maecenas libero. Etiam commodo dui eget wisi. Nullam at arcu a est sollicitudin euismod. Nullam rhoncus aliquam metus. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Duis risus. Fusce suscipit libero eget elit. Integer malesuada. Aliquam erat volutpat. Maecenas libero. Nam quis nulla. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Nunc tincidunt ante vitae massa. Sed convallis magna eu sem. Donec iaculis gravida nulla. Etiam commodo dui eget wisi. Integer in sapien. Nulla accumsan, elit sit amet varius semper, nulla mauris mollis quam, tempor suscipit diam nulla vel leo. Sed ac dolor sit amet purus malesuada congue. Vivamus luctus egestas leo. Etiam quis quam. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Nullam eget nisl. Mauris metus. Nulla turpis magna, cursus sit amet, suscipit a, interdum id, felis. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Etiam commodo dui eget wisi. Aliquam id dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Mauris metus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Maecenas libero. Etiam commodo dui eget wisi. Nullam at arcu a est sollicitudin euismod. Nullam rhoncus aliquam metus. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Duis risus. Fusce suscipit libero eget elit. Integer malesuada. Aliquam erat volutpat. Maecenas libero. Nam quis nulla. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Nunc tincidunt ante vitae massa. Sed convallis magna eu sem. Donec iaculis gravida nulla. Etiam commodo dui eget wisi. Integer in sapien. Nulla accumsan, elit sit amet varius semper, nulla mauris mollis quam, tempor suscipit diam nulla vel leo. Sed ac dolor sit amet purus malesuada congue. Vivamus luctus egestas leo. Etiam quis quam. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Nullam eget nisl. Mauris metus. Nulla turpis magna, cursus sit amet, suscipit a, interdum id, felis. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Etiam commodo dui eget wisi. Aliquam id dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Mauris metus."
label.numberOfLines = 0
contentView.addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
label.topAnchor.constraint(equalTo: contentView.topAnchor),
label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
IOS 11 news
Finally in IOS 11 are new layout guides what solves problems with this frame view and content view in UIScrollView as I mentioned it before.
It is
scrollView.frameLayoutGuide
scrollView.contentLayoutGuide
so for ios 11 only you can avoid the contentView good practice and do it in this way (but usually we need the backward support for older ios versions)
1) create UIScrollView same as before but define the width with the help of new layout guides
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
NSLayoutConstraint.activate([
scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
])
2) Now just add any content what you want, but attach autolayout into scrollView.contentLayoutGuide
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Maecenas libero. Etiam commodo dui eget wisi. Nullam at arcu a est sollicitudin euismod. Nullam rhoncus aliquam metus. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Duis risus. Fusce suscipit libero eget elit. Integer malesuada. Aliquam erat volutpat. Maecenas libero. Nam quis nulla. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Nunc tincidunt ante vitae massa. Sed convallis magna eu sem. Donec iaculis gravida nulla. Etiam commodo dui eget wisi. Integer in sapien. Nulla accumsan, elit sit amet varius semper, nulla mauris mollis quam, tempor suscipit diam nulla vel leo. Sed ac dolor sit amet purus malesuada congue. Vivamus luctus egestas leo. Etiam quis quam. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Nullam eget nisl. Mauris metus. Nulla turpis magna, cursus sit amet, suscipit a, interdum id, felis. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Etiam commodo dui eget wisi. Aliquam id dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Mauris metus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Maecenas libero. Etiam commodo dui eget wisi. Nullam at arcu a est sollicitudin euismod. Nullam rhoncus aliquam metus. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Duis risus. Fusce suscipit libero eget elit. Integer malesuada. Aliquam erat volutpat. Maecenas libero. Nam quis nulla. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Nunc tincidunt ante vitae massa. Sed convallis magna eu sem. Donec iaculis gravida nulla. Etiam commodo dui eget wisi. Integer in sapien. Nulla accumsan, elit sit amet varius semper, nulla mauris mollis quam, tempor suscipit diam nulla vel leo. Sed ac dolor sit amet purus malesuada congue. Vivamus luctus egestas leo. Etiam quis quam. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Nullam eget nisl. Mauris metus. Nulla turpis magna, cursus sit amet, suscipit a, interdum id, felis. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim. Etiam commodo dui eget wisi. Aliquam id dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Mauris metus."
label.numberOfLines = 0
scrollView.addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
label.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
label.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
label.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor)
])
And thats it. You can copy paste both ways into yours viewController viewDidLoad method and it will work.
Here is the undesired result I'm getting:
Click for image (can't embed yet)
Note how the tabs instead of being next to each other all stretch to 100% width and are lined up like a list.
The HTML:
<div id="tabs">
<ul>
<li>Nunc tincidunt</li>
<li>Proin dolor</li>
<li>Aenean lacinia</li>
</ul>
<div id="tabs-1">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
</div>
<div id="tabs-2">
<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>
</div>
<div id="tabs-3">
<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>
<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>
</div>
</div>
JS:
$("#tabs").tabs();
Jquery version: 1.11.0.
Jquery-ui version: 1.10.4.
CSS is the jquery-ui.css you get by downloading 1.10.4 from the official site.
Here is the link to my ThemeRoller just in case (though I've tried with default theme also, to no avail).
I've tried upgrading / downgrading, disabled any other css I have on the page - But I just can' get the tabs to look OK even with no edits or custom code (I've changed some colors but it was done using official jquery-ui ThemeRoller).
Ooops!!!! When downloading the theme from the jquery ui site, I just noticed the components were toggled off! Hence no .css for the Tabs component.
One of those moments...
And something to be aware of for others.
(I will accept this as answer but I have to wait 2 days. As a famous Austrian once said: I'll be back. -- I have now accepted the answer).
I have a blue box. I want to place a gradient overlay that fades from transparent to blue at the bottom of this blue box, so that overflowing text gradually fades out at the bottom.
Here's what it should look like (and does look like on most browsers):
Here's what it looks like on iOS Safari:
I've created a fiddle to demonstrate this issue: https://jsfiddle.net/cy89ocrs/11/
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0)), color-stop(100%, #034b81));
background-image: -moz-linear-gradient(rgba(0, 0, 0, 0), #034b81);
background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0), #034b81);
background-image: linear-gradient(rgba(0, 0, 0, 0), #034b81);
As you can see the color that is being faded to in Safari is darker, even though it is the same color. So when there's not enough text the fader is still awkwardly visible. Is there any way to fix this so Safari displays gradients like other browsers?
Safari is rendering correctly.
With linear-gradient you can define:
linear-gradient(
[ <angle> | to <side-or-corner> ,]? <color-stop> [, <color-stop>]+ )
\---------------------------------/ \----------------------------/
Definition of the gradient line List of color stops
where <side-or-corner> = [left | right] || [top | bottom]
and <color-stop> = <color> [ <percentage> | <length> ]?
So your gradient goes from black with zero opacity (rgba(0,0,0,0)) to your desired color (#034b81).
See: rgba(red,green,blue,opacity)
That's why you see that black line in Safari.
To achieve your desired appearance, just change the rgba value to the value of your color. so your code should look like:
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(3, 75, 129, 0)), color-stop(100%, #034b81));
background-image: -moz-linear-gradient(rgba(3, 75, 129, 0), #034b81);
background-image: -webkit-linear-gradient(rgba(3, 75, 129, 0), #034b81);
background-image: linear-gradient(rgba(3, 75, 129, 0), #034b81);
Demo
div {
position: relative;
width: 100%;
height: 300px;
background-color: #034b81;
color: white;
overflow: hidden;
}
div:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 25px;
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(3, 75, 129, 0)), color-stop(100%, #034b81));
background-image: -moz-linear-gradient(rgba(3, 75, 129, 0), #034b81);
background-image: -webkit-linear-gradient(rgba(3, 75, 129, 0), #034b81);
background-image: linear-gradient(rgba(3, 75, 129, 0), #034b81);
}
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ultricies eget quam sit amet eleifend. Sed luctus risus justo, ut finibus metus commodo ut. Curabitur sit amet lobortis mi. Curabitur vel felis id ante accumsan imperdiet. Etiam at ornare ligula.
Morbi consequat fermentum eros nec fermentum. Donec sodales molestie odio sollicitudin bibendum. Morbi semper ac nisl mattis semper. Donec sed lacus viverra, congue massa at, accumsan orci. Mauris et condimentum quam. Etiam imperdiet tempor quam non
aliquam. Integer et pharetra metus, et porttitor velit. Mauris at turpis dui. Etiam odio felis, placerat sit amet massa et, suscipit pretium eros. Nulla iaculis elit id turpis dictum, id scelerisque est eleifend. Quisque in ex tincidunt, bibendum nisl
non, tristique ligula. Curabitur venenatis purus nec sem placerat, sed sollicitudin libero tincidunt. Etiam ac turpis mattis, lobortis quam quis, sagittis nisi. Vivamus eget nisl commodo, vestibulum augue varius, pretium augue. Cras ultricies, velit
nec ultrices commodo, leo enim dignissim odio, vitae aliquam nibh ex nec elit. Duis egestas faucibus turpis, nec tristique nisl accumsan nec. Phasellus lacus massa, vulputate sed nisl lacinia, pretium vestibulum mi. In tincidunt luctus dictum. Praesent
elementum lorem eu erat mattis, quis convallis massa tristique. Cras rhoncus gravida dolor et rhoncus. Etiam et malesuada dolor. Sed in eros magna. Duis faucibus, ipsum eget ultrices dignissim, ipsum nunc consectetur nulla, in egestas nibh eros eget
turpis. Phasellus vestibulum mollis ullamcorper. Maecenas lectus mi, hendrerit vel justo at, dictum varius lectus. Cras ac libero vehicula, interdum eros sagittis, tristique tellus. Mauris tincidunt porttitor nisl, nec aliquam velit egestas nec. Mauris
nec gravida ipsum. Curabitur tempor velit nulla, sit amet laoreet elit euismod ac. Ut eros metus, consectetur sit amet purus eget, semper cursus nibh. In dolor nisl, vulputate ac augue et, luctus faucibus mauris. Donec eu ex ex. Donec ut elementum ligula.
Donec nisl justo, pharetra eget quam id, commodo lobortis augue. Suspendisse sit amet tellus interdum, tempor odio nec, iaculis sapien. Praesent maximus quis lacus a condimentum. Morbi convallis sem metus, vitae lacinia dui interdum sed. Proin eget
volutpat ex. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut molestie consectetur sem, at venenatis justo volutpat in. Sed lobortis dui vitae quam facilisis, gravida mattis justo volutpat. Aliquam elementum
non nunc consequat elementum. Vestibulum vitae sodales nulla, a iaculis tellus. Nullam tincidunt, dui sed elementum dapibus, mauris turpis aliquam odio, id laoreet nisl sapien a metus. Suspendisse potenti. Integer viverra fermentum nulla at sodales.
Proin viverra nulla eu felis tempus, vitae lacinia velit commodo. Phasellus eu nulla elementum, consequat orci eu, interdum metus. Nunc in tellus sed arcu egestas ullamcorper fringilla non purus. Nunc efficitur elementum sapien, in mollis diam volutpat
at. Suspendisse non luctus risus. Nam rutrum est ligula, vel scelerisque felis volutpat id. Maecenas ornare molestie dui sed varius. Praesent vulputate dui purus, sed venenatis purus pellentesque ac. Etiam neque arcu, imperdiet sed enim in, laoreet
ultrices nisl. Phasellus rhoncus lobortis ipsum, viverra accumsan eros feugiat id. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris eget commodo risus. Donec tellus elit, imperdiet a fermentum eget,
lobortis ac diam. Nulla dictum eros at neque tincidunt, at commodo tortor ultrices. In dapibus risus at tellus lobortis condimentum. In hendrerit et erat sit amet scelerisque. Vestibulum ultricies egestas efficitur. Ut finibus dolor et leo lobortis
egestas. Nulla aliquam quam ut metus molestie tincidunt. Aenean ac commodo mauris. Nullam ultrices urna nisi, vitae commodo quam viverra pulvinar.</div>
Is it possible to make a Primefaces Layout Scrollable? I dont want to make my layoutUnits scrollable as I dont really want multiple scrollable elements on the pages. I would prefer for the page & content panels to resize according to the content, so the user can view the data in a linear fashion. I am currently using a full page primefaces layout:
<p:layout fullPage="true">
If this isnt possible then what is my best alternatives as I quite like the primefaces components but could live without its layout features.
Cheers
You can create a layoutUnit for center, then provide a style class in it, where in your css you can provide scrollable along to x and y position.
<p:layoutUnit position="center">
<div id="myScreen" class="right col scroll-x scroll-y">
<ui:insert name="content">My Screen Content Goes Here</ui:insert>
</div>
</p:layoutUnit>
And in cc file --
.col {
top: 0; bottom: 0;
}
.scroll-x {
overflow-x: auto;
}
.scroll-y {
overflow-y: auto;
}
Hope this would help.
as far as i can tell it cannot be done! I dumped the primefaces layout and went with a generic web layout...
Just put everything in a <p:scrollPanel> component inside the <p:layoutunit>, that will work (now that it's 2015 and we are on Primefaces v5.1.x!). Make sure you add absolute positioning and height to stretch the <p:scrollPanel> to the innards of the <p:layoutunit> - see below.
http://www.primefaces.org/showcase/ui/panel/scrollPanel.xhtml
<p:scrollPanel mode="native" style="position: absolute; height: 100%;">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean blandit tortor a ipsum vehicula, in semper sapien auctor. Nulla tempor eget est non consequat. Nulla sit amet lorem justo. Cras non tellus eros. Sed ultricies orci ut quam interdum fringilla. Nam vitae massa ac mi elementum mattis vel vitae sem. Ut eros ipsum, scelerisque a erat a, eleifend luctus nibh. Interdum et malesuada fames ac ante ipsum primis in faucibus.
</p>
<p>
Vivamus ac ullamcorper magna. Aenean felis ante, elementum sit amet urna at, eleifend aliquet velit. Morbi a convallis magna. In nec leo vel dolor hendrerit pharetra. Cras in iaculis enim. Aenean porta sapien dignissim turpis dapibus, eu dictum velit elementum. Aliquam sollicitudin gravida luctus.
</p>
<p>
Ut vel nulla sit amet erat laoreet eleifend nec sed lacus. Quisque placerat diam vitae justo eleifend, rutrum mollis mauris fringilla. Curabitur turpis odio, euismod id lorem a, ultricies suscipit ligula. Pellentesque ut erat a leo rhoncus porta ac sed velit. Nunc at erat ligula. Fusce vehicula posuere interdum. Curabitur tempus, tortor at sollicitudin dapibus, erat ante varius nisl, id dictum erat ipsum porttitor ipsum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla id varius enim, sed rutrum orci.
</p>
<p>
Sed tincidunt urna quis metus lacinia commodo. Praesent convallis eros vel quam scelerisque bibendum. Mauris eget dignissim libero. Pellentesque sagittis sem quis ipsum viverra, sed consequat mi consectetur. Donec facilisis dapibus ultrices. Donec luctus auctor lacus, at congue nisi aliquet eu. Praesent in justo at risus faucibus ultricies. Fusce et libero lectus. Donec elementum pharetra sapien, at placerat purus sodales et. Vivamus iaculis lacus sed placerat rhoncus. Mauris iaculis sit amet nunc at placerat. Donec consequat euismod lacinia. Etiam nec quam vehicula, cursus massa in, ullamcorper erat.
</p>
<p>
Praesent volutpat scelerisque vestibulum. In eu massa non neque rutrum commodo. Nunc vel enim nisi. Aenean leo ipsum, molestie vel justo nec, pharetra luctus dui. Nunc rhoncus turpis id lorem luctus consequat. Nulla condimentum adipiscing turpis consequat semper. Etiam ullamcorper velit nec hendrerit malesuada. Praesent venenatis leo sit amet arcu commodo, sit amet porta tellus suscipit. Quisque mi tortor, vestibulum in arcu non, pretium auctor libero. In commodo luctus placerat.
</p>
</p:scrollPanel>
I don't believe that layouts are right for what you want to do here. This is good for enabling templating on a single page and the such. You might be able to however put an iframe within a layoutUnit to emulate the same effect though I have never tried this personally and couldn't tell you if it will work or not.
This should be any easy one for you. I have an accordion that I'd like to be a fixed height. Each pane should be the same size, if there is any overflow on a pane a scroll bar should appear. In the code below the scroll bars appear on load for the first pane, but after the first pane change, the accordion expands it's height, so scroll bars are no longer needed.
What am I doing wrong?
<head>
<script type="text/javascript">
jQuery(document).ready(function(){
$('#accordion').accordion({autoHeight: false, clearStyle: true});
});
</script>
</head>
<body>
<div id="accordion">
<h3>First Section</h3>
<div style="height:50px; overflow:auto">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut venenatis vehicula dui, quis volutpat odio bibendum a. Proin posuere convallis lorem id mattis. Vestibulum lacinia lacinia enim ut euismod. Aenean sit amet tincidunt nunc. Vestibulum gravida, ipsum in tempor dictum, diam nulla auctor purus, a vehicula ante odio quis massa. Pellentesque imperdiet urna ut elit adipiscing ac gravida lectus facilisis. Curabitur laoreet, justo vel dapibus auctor, enim sem dapibus nulla, sed lacinia felis felis sit amet dolor. Nulla lacus dolor, tincidunt convallis sodales vitae, interdum a sapien. Cras ut iaculis orci. Mauris vel nisl vel leo venenatis hendrerit. Duis aliquet lobortis purus, non malesuada lorem sagittis quis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc sit amet posuere eros. Nam vel turpis at sem adipiscing scelerisque a ac dolor. Morbi lobortis tristique felis, at aliquam libero suscipit sed. Aliquam erat volutpat. Donec porta lorem sed nisl fermentum pulvinar vehicula risus tempus. Integer ultricies dignissim vehicula. Morbi non dolor a arcu rutrum congue. Fusce non urna vitae eros blandit vehicula quis vel ligula.
</div>
<h3>Second Section</h3>
<div style="height:50px; overflow:auto">
Etiam varius, orci sit amet pharetra laoreet, diam augue dictum justo, et aliquam enim leo ut nulla. Quisque mi nunc, sagittis at euismod vel, feugiat a erat. In a metus quam. Pellentesque ullamcorper volutpat congue. Nunc facilisis varius velit eu lacinia. Quisque est nulla, tempus commodo gravida quis, consequat ut felis. Donec mattis, neque sagittis feugiat sollicitudin, augue lectus vulputate ligula, eget interdum nulla massa at nunc. Proin rhoncus nunc non felis mattis accumsan. Aliquam metus ligula, adipiscing ac ullamcorper vel, lobortis non erat. Aenean placerat libero porta enim dictum malesuada molestie sapien ultricies. Nullam ac commodo ligula.
</div>
<h3>Third Section</h3>
<div style="height:50px; overflow:auto">
Morbi nec risus velit, eget ornare nibh. Duis semper elementum erat, ac egestas purus congue et. Sed commodo lacinia lorem, ac semper risus dapibus mattis. Aliquam quam quam, ultrices quis luctus sit amet, cursus vitae dolor. Nam id lectus justo. Pellentesque in leo sit amet metus eleifend lobortis eget nec turpis. Praesent vitae magna eget mauris cursus tempus vel at mi. Nulla vitae leo accumsan magna mollis luctus. Curabitur viverra nisi ac nisl pulvinar gravida. Curabitur consectetur, diam non placerat sagittis, velit nunc porttitor quam, vel interdum lorem est ut arcu. Suspendisse potenti. Pellentesque vitae leo nunc.
</div>
</div>
</body>
</html>
I appears that the height property is being animated as the accordion opens and closes. So once the top panel has been closed one time, it's height has been changed from the one specified in the inline style and is 'lost'.
I found when I factor the style out into the header the accordion works as desired:
<head>
<style type="text/css">
#accordion>div{
height:50px;
overflow:auto;
}
</style>
</head>