How to set custom fonts in WebView(react-native-webview) in iOS? - ios

I want to set custom fonts in Webview. I have implemented the below code:
#font-face {
font-family: 'Poppins-Bold';
src:url('file:///android_asset/fonts/Poppins-Bold.ttf') format('truetype')
}
body{
font-family: Poppins-Bold
margin: 0;
padding: 0;
color: red;
}
It works fine in android, but it does not working in iOS. Let me know if anybody has a solution for this.
Note: I don't want to use google's CSS font

Set the following font URL based on platform:
const fontUrl = Platform.select({
ios: "Poppins-Bold.ttf",
android: "file:///android_asset/fonts/Poppins-Bold.ttf",
});
Update your CSS styles to the following:
const css = `
#font-face {
font-family: 'Poppins-Bold';
src: local('Poppins-Bold') url('${fontUrl}') format('truetype')
}
body {
font-family: Poppins-Bold
margin: 0;
padding: 0;
color: red;
}`
Note that format('truetype') is used since your font extension is ttf. If you're using an eot font you'll need to use format('opentype').
Once you do that, update your WebView component with the following props:
<WebView
source={{ html, baseUrl: '' }}
originWhitelist={["*"]}
/>
Setting baseUrl to blank will ensure fonts are loaded. Reference this post.
Without setting originWhitelist, you'll get errors on iOS that the URL cannot be found.
This worked for me on both Android & iOS and I happen to be using Poppins as well šŸ˜

I tried the solution outlined by German but this didn't work for me.
The only thing that got it working for me was by base64 encoding the font (you can use the service here), and injecting it that way, which is really annoying but it works across iOS and Android:
const pageHtml = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
#font-face {
font-family: 'Canela';
src: url('data:font/woff2;charset=utf-8;base64,${CANELA_BASE_64}') format('woff');
}
h1, h2, h3, html, body { font-family: Canela; }
</style>
</head>
<body>
${props.html}
</body>
</html>
`;
Then you can set up the WebView like this:
const webViewSource = { html: pageHtml, baseUrl: '' };
return (
<WebView
source={webViewSource}
originWhitelist={['*']}
/>
);

Related

Django App Implementing Auth0 won't render on iOS devices after logging in

I have a nice Django app that implements Auth0. It works on all browsers on pcs and on browsers on Android. When testing on iOS devices however, after the user logs in through Auth0, the device asks to download a file and then downloads it and does nothing. If I try to redirect to my english page, it downloads a file called "en", if I try to redirect to my french version of the page, it downloads a file called "fr". Not sure why - it is at the end of the url myurl.something.org/myForm/en for English for example.
At first I thought the issue had to do with Apple not allowing Same-Site cookies, so I added the CSRF_COOKIE_SAMESITE = None setting. But I see now that after logging in, in the address bar there is the url that I want the user to be redirected to. When I tried using the Web Inspector for Safari on Iphone, I see that there are no same-site cookies, so it seems that this is not the problem.
I see the document "en" in the list of resources on the Web Inspector when on the login page. It is type "document" and shows that inside of it is the following:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Sign In with Auth0</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
.bgimg {
background-image: url('pic.jpg');
}
#myVideo {
position: fixed;
right: 0;
bottom: 0;
min-width: 100%;
min-height: 100%;
z-index: 1;
}
.auth0-lock.auth0-lock.auth0-lock-opened .auth0-lock-overlay {
opacity: 0.0 !important;
-webkit-transition: opacity 0.3s ease-in 0s;
transition: opacity 0.3s ease-in 0s;
}
.video{
position:absolute;
z-index:-5 !important;
}
.overlay{
background:#333;
color: white;
position:fixed;
top: 50px;
left: 0;
width: 400px;
height: 100px;
z-index:1000;
visibility:hidden;
/*
* if you want to make it none clickable but make the
* clicks go to the video
*/
pointer-events: none;
}
</style>
</head>
<body background="https://www.nbn.org.il/wp-content/uploads/2019/04/auth0_bkg.jpg">
<div class="login-container"></div>
<!--
<div class ="video"> <video autoplay muted loop id="myVideo">
<source src="https://www.nbn.org.il/source_files/login/nbnommunitywaiting.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
</div>
-->
<!--[if IE 8]>
<script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<script src="https://cdn.auth0.com/js/base64.js"></script>
<script src="https://cdn.auth0.com/js/es5-shim.min.js"></script>
<![endif]-->
<script src="https://cdn.auth0.com/js/lock/11.3/lock.min.js"></script>
<script>
// Decode utf8 characters properly
var config = JSON.parse(decodeURIComponent(escape(window.atob('long_token'))));
config.extraParams = config.extraParams || {};
var connection = config.connection;
var prompt = config.prompt;
var languageDictionary;
var language;
if (config.dict && config.dict.signin && config.dict.signin.title) {
languageDictionary = { title: config.dict.signin.title };
} else if (typeof config.dict === 'string') {
language = config.dict;
}
var loginHint = config.extraParams.login_hint;
var lock = new Auth0LockPasswordless(config.clientID, config.auth0Domain, {
auth: {
redirectUrl: config.callbackURL,
responseType: (config.internalOptions || {}).response_type ||
(config.callbackOnLocationHash ? 'token' : 'code'),
params: config.internalOptions
},
/* additional config needed to use custom domains
configurationBaseUrl: config.clientConfigurationBaseUrl,
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: config.auth0Domain
}, */
assetsUrl: config.assetsUrl,
allowedConnections: connection ? [connection] : null,
rememberLastLogin: !prompt,
language: language,
languageDictionary: languageDictionary,
prompt: 'consent',
theme: {
logo:'pic.png',
primaryColor: "#fbaa40",
},
closable: false,
// uncomment if you want small buttons for social providers
// socialButtonStyle: 'small'
});
lock.show();
</script>
<div class="overlay">i'm a cool overlayed html block</div>
</body>
</html>
and then when I log in and go to the next page, under the Elements, section I get just a blank html body called about:blank.
Here is another image from the Web Inspector of the login page before getting to the first page of my app which may or may not be helpful:
Any insight into what might be wrong would be much appreciated!
My original thoughts about the issue posted above were completely not the problem.
At some point I realized this:
If I required login through auth0 and passed a context in the view the application downloaded html instead of rendering on iOS devices. If I didnā€™t require login, passing a context was no problem. If I didnā€™t pass in a context, requiring login through auth0 was no problem.
Even passing an empty context caused a problem.
Eventually I figured out that the problem was this:
In the Auth0 Django SDK that I was following, it shows that you should pass in what I thought was an extra dictionary parameter for auth0:
{'auth0User': auth0user,'userdata': json.dumps(userdata, indent=4) }
Since I didn't consider the other parameter to be a context, I also added my own context in the return statement of the view like this:
return render(request, 'mypage.html', context, { 'auth0User': auth0user, 'userdata': json.dumps(userdata, indent=4)} )
So for some reason this worked on pcs and androids to pass in two contexts, but iOS didn't like it.
Once I combined the two contexts
return render(request, 'mypage.html', {'contextvar1': 'data', 'contextvar2': 'moredata', 'auth0User': auth0user, 'userdata': json.dumps(userdata, indent=4)} )
everything works.
If anyone has understanding as to why this worked on other operating systems besides Apple and why this caused iOS devices to download the html, I would love to understand.

How set custom font in a Webview in xamarin Android?

webViewOfferes = FindViewById<WebView>(Resource.Id.webViewOffers);string start = "<html><head><meta http-equiv='Content-Type' content='text/html' charset='UTF-8' /><style type='text/css'> li {line-height: 2;} #font-face {font-family: 'PlayfairDisplay-Regular';src: url('file:///Assets/fonts/PlayfairDisplay-Regular.ttf');} body{font-family:PlayfairDisplay-Regular;}</style></head><body>";
string end = "</body></html>";
webViewOfferes.LoadData(start + "<h3>My Custome Font:</h3>"+ end, "text/html", UTF32Encoding.ASCII.ToString());
WebSettings Offersetting = webViewOfferes.Settings;
Offersetting.DefaultFontSize = 13;
Not getting desired output with this code someone please help
Change
file:///Assets/fonts/PlayfairDisplay-Regular.ttf
to
file:///android_asset/fonts/PlayfairDisplay-Regular.ttf
This works for both Android and iOS.
After searching for a while I found the solution. Basically it's directly the same as you would write in HTML. So I created this HTML code in a HTML file, layed the font myfont.otf in the same folder and made this work:
<html>
<head>
<style type=text/css>
#font-face {
font-family: 'CustomFont';
src: url('myfont.otf')
}
body {
font-family: 'CustomFont';
}
</style>
</head>
<body>
<p>This is some sentence with a custom font.</p>
</body>
</html>
Now everything you have to do is:
Android:
Put the font into the Android Assets folder
Ensure its build action is AndroidAsset
Pass the HTML string and the fontname (with path if in subfolder, like Fonts/myfont.otf) to the WebView
iOS:
Put the font into the iOS Resources folder
Ensure its build action is BundleResource
Pass the HTML string and the fontname (with path if in subfolder, like Fonts/myfont.otf) to the WebView
I made a helper class for this:
public static class HtmlHelper
{
public static string SurroundWithCustomFont(string htmlString, string fontPath)
{
return $#"
<html>
<head>
<style type=text/css>
#font-face {{
font-family: 'CustomFont';
src: url('{fontPath}')
}}
body {{
font-family: 'CustomFont';
}}
</style>
</head>
<body>
{htmlString}
</body>
</html>";
}
}

react native webview:when add baseRrl,then just show html string

In order to achieve the WebView display custom font
on rn 0.28:
var html = 'test';
html = `<!DOCTYPE html>
<head>
<meta charset="utf-8">
<style type="text/css">
#font-face {
font-family: "MyFont";
src: url("fonts/fzbys.ttf");
}
body{font-family: "MyFont"; font-size:28px;}
</style>
</head>
<body>`+html+`
</body>
</html>`;
return (
<View style={[{width:this.state.width, alignItems:'center'}, this.props.styles]}>
<WebView
ref={"wv"}
style={{width:this.state.width, height:100}}
source={{html:html, baseUrl:"file:///android_asset/"}}
domStorageEnabled={true}
javaScriptEnabled={true} />
</View>
);
the font file had in android/app/src/main/assets/fonts, then :
run res

html/css -- trying to center image and ignore body margins

Foo.html:
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="testStyle.css" />
</head>
<body>
The appearance of the text is good. This image should be centered, but it isn't:
<img class="centerblock" src="ice cream cone and dish.png" width="320" height="200"></img>
</body>
TestStyle.css:
body {margin-left:30px;}
body {margin-right:30px;}
.centerblock {
margin-left: auto;
margin-right: auto;
display: block;
}
Result:
Try:
.centerblock {
position:fixed;
top:10px;
left: 10px;
}
Maybe that can help, Although i don't know what can happen if you turn the phone.
I would make that main content area to fit to the edge of display and define all align properties for each element.
It's never very smart to do:
body {margin-left:30px;}
body {margin-right:30px;}
There is also option:
.main-container {
margin: 0 auto;
}
That also centers all the content but i think, also would not solve your problem.

Parts of word gets pushed to next line (sifr3-r436)

When reloading the page, sometimes <li>Dagbladet</li> is rendered with a linebreak before "t", so it looks like:
Dagblade
t
<li>DN</li> is always rendered as:
D
N
IĀ“d like to list each list element to the right for the previous one.
ItĀ“s positioned as it should when I donĀ“t activate sIFR3.
All tips on how to use sIFR3 with to achieve this is highly appreciated!
The list should look like this:
Aftenposten Dagbladet Verdens Gang DN
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>type-test</title>
<link rel="stylesheet" href="sifr/sifr.css" type="text/css">
<script src="sifr/sifr.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
var cochin = { src: '/sifr3-r436/demo/cochin.swf'}
sIFR.activate(cochin);
sIFR.replace(cochin, {
selector: 'h1, h2, h3, h4, li',
css: '.sIFR-root { }'
});
</script>
<style type="text/css" media="screen">
ul li {
list-style: none ;
display: inline ;
}
</style>
</head>
<body>
<p>
<ul>
<li>Aftenposten</li>
<li>Dagbladet</li>
<li>Verdens Gang</li>
<li>DN</li>
<ul>
</p>
</body>
</html>
sIFR uses the width of the original element to fit the Flash text into. In your case, the Flash text is wider than the original element, doesn't fit and instead breaks into a new line.
The solution is to add some letter-spacing (through a .sIFR-active selector) to make the HTML text wider just for sIFR. Then when the replacement happens there'll be enough space to fit the Flash text.
use like this
sIFR.replace(test, {
selector: 'h1',
css: '.sIFR-root { color: #cccccc; width: 100%; text-align: left; letter-spacing:1;}',
wmode: 'transparent',
forceSingleLine: true;
});
forceSingleLine: true; will solve your problem.
I really think you need to be posting this on the SIFR Support Forums. This isn't a programming issue.

Resources