I have html text returned from the server and I am using a UITextView on the IOS client to render the text. I am first converting the html string to attributed string and then enumerating over the attributes and changing the font, foreground color of the text as needed. Finally I am setting the attributed text of UiTextView. However, when the html contains images and I see that they get cut off when rendered in UITextView.
Any pointers on how I could change the width and height of images contained in the html text in order to fit my phone screen width?
I use SwiftSoup to extract data from html or edit the HTML string. I also have found that when images are present it's easier to manage the layout and format inside a WKWebView.
This example also helps to add support for dark mode in your WKWebView.
var newsRssBody: String = ""
let css = "#media (prefers-color-scheme: dark) {body { background-color: rgb(38,38,41); color: white; } a:link { color: #0096e2; } a:visited { color: #9d57df; } }"
try doc.head()?.append("<style>\(css)</style>")
self.newsRssBody = "\(doc)"
The headerString line helps with content sizing based on the device.
let headerString = "<header><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'></header>"
self.webView.loadHTMLString(headerSting + self.newsRssBody, baseURL: nil)
I want to change all dataDetectorType Colour in UIWebView including PhoneNo , emailID , Calendar and every dataDetctorType. I also need Tappable link for that dataDetector link.
Adding some CSS to set the link color works, but for auto-detected links and e-mails etc it is necessary to add !important for the color to be applied.
<style>a { color: red !important; }</style>
For UITextView, you can use linkTextAttributes for this, but there is no such thing for UIWebView. You will have to add CSS to the content you are loading to style the automatically inserted A tags.
CSS example to change the detected link color:
NSString *html = #"<style>a:link { color: red; }</style> <h3>detected phone number: 111122223333</h3> <a href='www.google.com'>google link</a>";
[webView loadHTMLString:html baseURL:nil];
The result in WebView:
I'm loading Youtube video inside UIWebView using following code.
let videoUrl = "https://www.youtube.com/embed/F9GujgK0y2M"
let embedHTML = "<iframe width=\(self.webView.frame.size.width)\" height=\(self.webView.frame.size.height)\" src=\(videoUrl)?&playsinline=1\" frameborder=\"0\" allowfullscreen></iframe>"
Starting thumbnail for video is very large. I need to fit it according to size of UIWebView. Please help me, How can I change it ?
maybe this code can help you:
let yourVideoID = "F9GujgK0y2M"
let css = ".video-container {position:relative;padding-bottom:56.25%;height:0;overflow:hidden;} .video-container iframe, .video-container object, .video-container embed { position:absolute; top:0; left:0; width:100%; height:100%; }"
let url = "https://www.youtube.com/embed/\(yourVideoID)?playsinline=1&modestbranding=1&showinfo=0&rel=0&showsearch=0&loop=1&iv_load_policy=3"
let htmlString = "<html><head><style type=\"text/css\">\(css)</style></head><body><div class=\"video-container\"><iframe src=\"\(url)\" frameborder=\"0\"></iframe></div></body></html>"
yourWebView.scalesPageToFit = false
yourWebView.allowsInlineMediaPlayback = true;
yourWebView.loadHTMLString(htmlString, baseURL: nil)
Try this:
webView.scalesPageToFit = true
From Apple Documentation, setting this to true scales the webpage to fit the screen.
For me, removing the height and width properties in the iframe HTML tag made the frame fit the page width altogether.
I am trying to embed a video from youtube with the following code:
func setUpVideo() {
let width = webView.frame.width
let height = webView.frame.height
let frame = 0
bmiWebView.allowsInlineMediaPlayback = true
let videoUrl = "https://www.youtube.com/embed/GCALWdwKr48"
let htmlUrl = "<html><body><iframe width=\(width) height=\(height) src=\(videoUrl)?&playsinline = 1 frameborder=\(frame) allowfullscreen></iframe></body></html>"
webView.loadHTMLString(htmlUrl, baseURL: NSBundle.mainBundle().bundleURL)
}
I'm able to load the video initially with white background but when it loads it looks like below. I'm not sure why there is a white background. If someone can tell me how to remove that will be really helpful. Thank you.
The white background is the margin on the body of the HTML of your UIWebView.
Add some CSS to set the margin to 0 like so:
<html>
<head>
<style>body{margin:0px;}</style>
</head>
<body>
<iframe width=\(width) height=\(height) src=\(videoUrl)?&playsinline = 1 frameborder=\(frame) allowfullscreen></iframe>
</body>
</html>
In iOS 6 everything works fine. The keyboard opens and moves the input into view. When the keyboard closes everything goes back where it should.
In iOS 7 the keyboard opens fine and the input remains in view. When the keyboard is closed the whole bottom half of the app is gone, though. I've tracked the issue down to the height of the window changing when the keyboard is opened, and not changing back when it's closed.
Right before the keyboard is opened the window height is 568 according to $(window).height() and after it's opened and after it's closed it is 828. The height of the document also changes accordingly.
I've attempted preventing the window from resizing with:
$(window).resize(function(e) {
e.preventDefault();
e.stopPropagation();
window.resizeTo(320,480);
return false;
});
I've also attempted to set the size back after the keyboard closes with no success.
I'm using phonegap 2.7 and have KeyboardShrinksView set to true.
I was seeing this too. After the height changes, some of our absolute positioned elements disappear off the bottom of the screen.
I found that with KeyBoardShrinksView = false in ios7, window.height stayed constant. This was the opposite of ios6 though, so a bit of a catch 22.
Not sure if there's a better way of handling this in Phonegap, but I put this in CDVViewController.m, created to config.xml files for ios < v7 and ios > v6, and my app works the way I want. Seemed a bit hacky, but not too disruptive of the rest of my code.
// read from config.xml in the app bundle
NSString* path = [[NSBundle mainBundle] pathForResource:#"config" ofType:#"xml"];
if (IsAtLeastiOSVersion(#"7.0")) {
path = [[NSBundle mainBundle] pathForResource:#"config_ios7" ofType:#"xml"];
}
(I also tried an app preference plugin at https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/ApplicationPreferences but don't think this was designed for this kind of preference.)
After I upgraded my project to iOS with cordova 3.1 I start having similar problems for the input fields in where I did not have the code listed above. The keyboard pushes things up and the header and footer did not returned to their original positions. I have tested and that solve the problem (maybe not very elegantly but it is a workaround). I just put that code on my pageinit event.
/*************************************************************************************************
* FIX: to avoid the buggy header and footer to jump and stick not
* to the top/bottom of the page after an input or textfield lost focus and the keyboard dissapear *
*************************************************************************************************/
$('input, textarea')
.on('focus', function (e) {
$('header, footer').css('position', 'absolute');
})
.on('blur', function (e) {
$('header, footer').css('position', 'fixed');
//force page redraw to fix incorrectly positioned fixed elements
setTimeout( function() {
window.scrollTo( $.mobile.window.scrollLeft(), $.mobile.window.scrollTop() );
}, 20 );
});
add code into CDVViewController.m
for example it added into webViewDidFinishLoad function
CGRect newFrame = self.webView.bounds;
NSLog(#"%f" , newFrame.size.height);
NSString *JS = [NSString stringWithFormat:#"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=0.5, minimum-scale=0.5, width=device-width, height=%d, target-densitydpi=device-dpi');", (int) newFrame.size.height*2 ];
[self.webView stringByEvaluatingJavaScriptFromString:JS];
this code change <meta name="viewport" content="..."> and set height of device
set your viewport meta tag to your html
<meta name="viewport" content="width=device-width,height=**yourheight**, initial-scale=1, maximum-scale=1, user-scalable=0" >
or
<meta name="viewport" content="width=device-width,height=**device-height**, initial-scale=1, maximum-scale=1, user-scalable=0" >
The Petrash's solution worked for me. But I had still problems supporting rotations on iPad.
So, in the same CDVViewController.m I've added this method:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
if (self.webView){
CGRect newFrame = self.webView.bounds;
//NSLog(#"%f" , newFrame.size.height);
NSString *JS = [NSString stringWithFormat:#"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=1, minimum-scale=1, width=device-width, height=%d, target-densitydpi=device-dpi');", (int) newFrame.size.height*1 ];
[self.webView stringByEvaluatingJavaScriptFromString:JS];
}
}
and, to support the "non scale" behaviour, edited the Petrash's solution in this way:
CGRect newFrame = self.webView.bounds;
//NSLog(#"%f" , newFrame.size.height);
NSString *JS = [NSString stringWithFormat:#"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=1, minimum-scale=1, width=device-width, height=%d, target-densitydpi=device-dpi');", (int) newFrame.size.height*1 ];
[self.webView stringByEvaluatingJavaScriptFromString:JS];
KeyboardShrinksView = false
This is hacky, but it works from 5.1 to 7.0.3. Tested on Cordova 3.0.
After hours of investigating I've managed to get it to work:
My div, that is pushed up and never get's down again,
had the css attribute
position:fixed;
I switched this to
position:absolute;
and everything worked!
The best way I found was to put everything into a div and fix its height via javascript.
Works on modern Versions of both iOS (5, 6, 7) and Android (4.2, ...).
<style>
body {
overflow-y: scroll;
overflow-x: hidden;
webkit-overflow-scrolling: touch;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
body > .viewport{
position: absolute;
top: 0;
left: 0;
right: 0;
}
</style>
<body>
<div class='viewport'>
<!-- Put everything here -->
</div>
</body>
<script type="text/javascript">
$("body > .viewport").height($(document).height());
// WARNING: if your app works in both landscape and portrait modus, then you should reset the height of the container when the app changes orientation
</script>
I had a similar issue that drove me nuts for days. Not sure if this will help anyone else, but this is what solved it for me: (note I'm using jquery finger library to listen to tap events):
$('body').delegate("#send_feedback_button","tap", function(event){
$('textarea').blur();
event.stopImmediatePropagation();
// do my stuff
});
For me calling blur on any textarea in the view was the trick. The stopImmediatePropagation got rid of some other funkiness.
I had the same problem and I managed to track it down to dynamic content.
I had initially an empty div that was filled with text using javascript.
When I pre filled the div with static text the problem was gone.
Looks like this div's height was not counted when resizing.