I'm trying to render a webview in my flutter project.
It's working perfectly for Android in debug and release modes and on iOS in debug mode as well.
However if I upload a build to Testflight, it does not work for some reason.
I've been working with the same code from the past few months and not had an issue with Flutter v1.
I'm attaching a code snippet below. Any help is appreciated.
Snippet:
return Container(
width: size.width,
height: size.height,
child: WebView(
key: UniqueKey(),
initialUrl: renderHTML(width, content!),
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: <JavascriptChannel>[
JavascriptChannel(
name: 'GetImgSrc',
onMessageReceived: (JavascriptMessage msg) {
print('Stef Method Channel ${msg.message}');
Navigator.of(context)
.pushNamed(PhotoViewer.route, arguments: msg.message);
}),
].toSet(),
navigationDelegate: (request) => NewsArticleController()
.navigationDelegate(request, content!, width),
),
);
renderHtml(width, content) {
return Uri.dataFromString(body, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString();
}
Html Snippet:
String body = '''
<html>
<head>
<meta name='viewport' content='initial-scale = 1.0, width=device-width'/>
<style>
html {
width: ${width}px;
}
body {
margin-left: 8px;
margin-right: 8px;
margin-top: 0px;
margin-bottom: 0px;
background-color: #F6F6F6;
}
em {
font-style: italic;
}
.title {
padding: 0 20px;
font-family: Georgia,Times,Times New Roman,serif;
font-size: 20px;
font-weight: 600;
letter-spacing: 1px;
line-height: 32px;
color:#3D3D3D;
}
.meta-desc {
margin: 8px 0;
font-size: 16px;
text-align: left;
color: #000000;
font-family: Georgia,Times,Times New Roman,serif;
font-weight: 400;
line-height: 24px;
letter-spacing: 1px;
}
.meta-data {
padding: 12px 0 8px 20px;
color:#818181;
font-size: 12px;
line-height: 20px;
font-family: Georgia,Times,Times New Roman,serif;
}
.hero-img img {
margin-left: -8px;
width: ${double.parse(width)}px;
height: auto;
}
.body-content {
padding: 0 20px;
}
.body-content div, .body-content p, .body-content span {
padding: 0 !important;
margin-bottom: 15px !important;
font-size: 20px;
text-align: left;
color: #000000;
font-family: Georgia,Times,Times New Roman,serif;
font-weight: 400;
line-height: 31px;
}
.body-content img {
width: 100%;
height: auto;
margin: auto;
}
a {
color: #F50057;
text-decoration: none;
font-weight: bold;
}
.yt-iframe {
width: ${double.parse(width) - 16}px;
min-height: 200px;
}
iframe.instagram-media {
margin: 0 auto 10px !important;
/* width: ${double.parse(width) - 16}px !important; */
}
iframe {
margin: 0 8px 10px -8px !important;
width: 100% !important;
}
</style>
</head>
<body>
<div class="hero-img cls-image">
<img src="${content.images?.url}">
</div>
<div style="text-align: end; padding: 16px 20px 8px 0; font-size:12px; color:#818181;">${content.postDateStr}</div>
<div class="title">
${content.title}
</div>
<!--<div class="meta-desc">
${content.metaTagDescription}
</div>-->
<div class="meta-data">
By <span>${content.user}</span>
</div>
<div class="body-content">
$body
</div>
</body>
<script>
var elements = document.getElementsByClassName("instagram-media");
setTimeout(function(){
for (var i = 0; i < elements.length; i++) {
elements[i].style.width=('0px');
console.log('initial width: ' + elements[i].style.width);
elements[i].style.width=('${double.parse(width) - 16}px');
console.log('final width: ' + elements[i].style.width);
}
console.log(elements);
}, 1000);
var images = document.getElementsByClassName("cls-image");
var myFunction = function(event) {
GetImgSrc.postMessage(event.target.src);
};
for (var i = 0; i < images.length; i++) {
images[i].addEventListener('click', myFunction, false);
}
</script>
</html>
''';
Flutter version: Channel stable, 2.2.3, on macOS 11.4 20F71 darwin-x64, locale en-US
webview_flutter version: 2.0.9
You may need to do more setup for the WebView to work with IOS build - if you're using this package I would suggest taking a look at this and adding in suggested info to your info.plist
https://inappwebview.dev/docs/get-started/setup-ios/
Related
Does anyone know why the input box might be glitching only on iOS but works fine on Android? I have attached two videos for better explanation of this problem. Basically on iOS I would have to tap the input field twice for it to go into 'active' state and afterwards when I try type it zooms in so much into the screen to type. No issues like this in the browser as well.
iOS - https://streamable.com/e622tj
Android - https://streamable.com/4zvns6
<div
id='task-writer'
onClick={() => {
inputRef.current?.focus();
}}
>
<div className='left'>
<label>
<input
type='checkbox'
defaultChecked={checked}
onChange={() => setChecked(!checked)}
/>
<div className='checkbox-div' />
</label>
<form
className='NewTodoForm'
id='task-form'
onSubmit={handleSubmit}
ref={formRef}
>
<input
value={userInput.task}
onChange={handleChange}
id='task'
type='text'
name='task'
placeholder='Add your task here...'
autoComplete='off'
ref={inputRef}
// onFocus={() => {
// console.log('focused');
// setIsFocused(true);
// }}
// onBlur={() => {
// console.log('blurred');
// inputRef.current?.focus();
// setIsFocused(false);
// }}
/>
</form>
</div>
CSS Code:
#task-writer {
display: flex;
flex-direction: row;
width: 100%;
align-items: center;
padding: 10px;
padding-left: 20px;
padding-right: 15px;
border-radius: 20px;
background-color: #f5f7fa;
.left {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
align-items: center;
gap: 20px;
padding: 10px 0;
label {
display: grid;
place-items: center;
width: 30px;
height: 30px;
cursor: pointer;
input {
display: none;
}
form {
width: 100%;
height: 100%;
overflow: hidden;
transform: translateX(-50px);
transition: 0.25s ease;
transition-property: transform;
input {
width: 100%;
height: 100%;
border: none;
outline: none;
font-family: 'Inter var', sans-serif;
font-size: clamp(12px, 1.65vw, 16px);
font-weight: 400;
color: #000;
background-color: transparent;
}
}
}
right-calendar-date {
position: relative;
display: flex;
flex-direction: row;
height: 40px;
width: fit-content;
align-items: center;
gap: 12px;
padding: 0px 12px;
margin-left: 12px;
border-radius: 10px;
padding-right: 40px;
cursor: pointer;
color: #6d6d6d;
background-color: #EAEDEE;
opacity: 0;
pointer-events: none;
transition: 0.25s ease;
transition-property: opacity;
h4 {
overflow: hidden;
white-space: nowrap;
color: #000;
}
}
.date-form {
display: grid;
place-items: center;
height: 30px;
width: 80px;
padding: 0 16px;
border-radius: 10px;
opacity: 0;
cursor: pointer;
color: #6d6d6d;
background-color: #eaedee;
transition: 0.25s ease;
transition-property: background-color;
:hover {
background-color: #d9d9d9;
}
h4 {
font-size: clamp(12px, 1.65vw, 14px);
font-weight: 500;
}
}
I just completed mimicking app creation just like I did in online lessons. I figure, I'd take a little step further by making my app look nicer.
I am trying to change my "home" link text to an image.
Surely, I have done that in HTML before but not in Rails. I am a bit confused because of "link_to" method. How do I do it, giving my current set-up?
application.html.erb
<header>
<div class="header-logo">
<%= link_to("Home", "/") %>
</div>
...
where routes.rb are
get "/" => "home#top"
home.scss
* {
box-sizing: border-box;
}
html {
font: 100%/1.5 'Avenir Next', 'Hiragino Sans', sans-serif;
line-height: 1.7;
letter-spacing: 1px;
}
ul, li {
list-style-type: none;
padding: 0;
margin: 0;
}
a {
text-decoration: none;
color: #2d3133;
font-size: 14px;
}
h1, h2, h3, h4, h5, h6, p {
margin: 0;
}
input {
background-color: transparent;
outline-width: 0;
}
form input[type="submit"] {
border: none;
cursor: pointer;
}
/* Common Layout ================================ */
body {
color: #2d3133;
background-color: white;
margin: 0;
min-height: 1vh;
background-image: url("/top.jpg");
}
.main {
position: absolute;
top: 64px;
width: 100%;
height: auto;
min-height: 100%;
background-color: #f5f8fa;
}
.container {
max-width: 600px;
margin: 60px auto;
padding-left: 15px;
padding-right: 15px;
clear: both;
}
/* Header ================================ */
header {
height: 64px;
position: absolute;
z-index: 1;
width: 100%;
}
.header-logo {
float: left;
padding-left: 20px;
color: black;
font-size: 22px;
line-height: 64px;
}
.header-logo a{
color: black;
font-size: 22px;
}
.header-menus {
float: right;
padding-right: 20px;
}
.header-menus li {
float: left;
line-height: 64px;
font-size: 13px;
color: black;
padding-left: 15px;
}
.header-menus a {
float: left;
font-size: 13px;
color: black;
padding-right: 15px;
}
.header-menus .fa {
padding-right: 5px;
}
.header-menus input[type="submit"] {
padding: 0 20px;
float: left;
line-height: 64px;
color: black;
margin: 0;
font-size: 13px;
}
/* Top ================================ */
.top-main {
padding: 200px 0 100px;
text-align: center;
position: absolute;
top: 0;
width: 100%;
height: auto;
min-height: 100%;
color: black;
background-color: white;
background-repeat: no-repeat;
background-position: center 50%;
background-size: cover;
background-image: url("/top.jpg");
}
.top-message {
position: relative;
}
.top-main h2 {
font-size: 70px;
font-weight: 500;
line-height: 1.3;
-webkit-font-smoothing: antialiased;
margin-bottom: 20px;
}
.top-main p {
font-size: 24px;
}
/* About ================================ */
.about-main {
padding: 180px 8% 0;
color: black;
}
.about-main h2 {
font-size: 64px;
font-weight: 500;
line-height: 1.4;
}
.about-main p {
font-weight: 200;
font-size: 20px;
}
.about-img {
width: 25%;
}
/* Form ================================ */
.form {
max-width: 600px;
margin: 0 auto;
background-color: black;
box-shadow: 0 2px 6px #c1ced7;
}
.form-heading {
font-weight: 300;
margin: 60px 0 20px;
font-size: 48px;
color: #bcc8d4;
}
.form-body {
padding: 30px;
}
.form-error {
color: #ff4d75;
}
.form input {
width: 100%;
border: 1px solid #ffffff;
padding: 10px;
color: #57575f;
font-size: 16px;
letter-spacing: 2px;
border-radius: 2px;
}
.form textarea {
width: 100%;
min-height: 110px;
font-size: 16px;
letter-spacing: 2px;
}
.form input[type="submit"] {
background-color: #ffffff;
color: black;
cursor: pointer;
font-weight: 300;
width: 120px;
border-radius: 2px;
margin-top: 8px;
margin-bottom: 0;
float: right;
}
.form-body:after {
content: '';
display: table;
clear: both;
}
/* Flash ================================ */
.flash {
padding: 10px 0;
color: black;
background: rgb(251, 170, 88);
text-align: center;
position: absolute;
top: 64px;
z-index: 10;
width: 100%;
border-radius: 0 0 2px 2px;
font-size: 14px;
}
Thank you for your time :)
You can try it <%= link_to image_tag('image_here'), '/' %>
I think this is what you want
<%= link_to "#{image_tag("name-of-img-here.png")}".html_safe, root_path %>
Make sure you image is in the app/assets/images/ folder for this to link correctly.
You will also likely need to add a class and then style it the image for it to look good.
I have a button being used to show a dropdown div. The button padding and text can be clicked on to show the dropdown div. The very small Material "font-icon" CANNOT be clicked to show the dropdown div. How can I ensure that you can click anywhere within the button (including directly on the Material icon) in order to show the dropdown div.
Here is a link to show you what I've done.
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
body {
margin: 0;
color: #333;
overflow-x: hidden;
padding-top: 80px;
}
:root{
var-MainColor: #4C00F9;
--main-color: #4C00F9;
}
header {
background: #f5b335;
height: 40px;
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
}
.nav-up {
top: -64px;
}
#navWrapper {
padding: 0px;
border-bottom: 1px solid #eee;
font-size: 13px;
font-family: Sans-Serif;
width: 100%;
background-color: #fff;
z-index: 1000;
height: 64px;
}
#navLeft {
float: left;
}
#navRight {
float: right;
}
/* Dropdown Button */
.dropbtn {
background-color: transparent;
color: var(--main-color);
padding: 24px;
font-size: 13px;
border: none;
cursor: pointer;
}
/* Dropdown button on hover & focus */
.dropbtn:hover, .dropbtn:focus {
background-color: var(--main-color);
color: #fff;
outline: none;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
margin-left: 10px;
margin-right: 2%;
margin-top: -8px;
border-radius: 2px;
background-color: #fff;
min-width: 260px;
border: 0px solid #eee;
box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.3);
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content a {
color: var(--main-color);
padding: 24px;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #fdfdfd;}
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {display:block;}
.material-icons.md-01 { font-size: 13px; vertical-align: middle; margin-top: -3px;}
.material-icons.md-02 { font-size: 24px; vertical-align: middle; margin-top: -5px; color: red;}
.material-icons.md-03 { font-size: 24px; vertical-align: middle; margin-top: -5px; color: #40FA35;}
.material-icons.md-04 { font-size: 21px; vertical-align: middle; margin-top: -1px;}
.material-icons.md-05 { font-size: 16px; vertical-align: middle; margin-top: -1px;margin-right: 15px;}
#main {
margin-top: 50px;
position: absolute;
}
section {
width: 100%;
border-bottom: 1px solid #eee;
padding: 50px 0px;
}
#sectionInnerText {
max-width: 700px;
padding: 0px 100px;
}
#sectionInnerImage {
max-width: 1000px;
padding: 0px 100px;
}
#sectionInnerImage-rowWrapper {
padding: 0px 100px;
}
#sectionInnerImage-3row {
width: 31%;
max-width: 400px;
display: inline-block;
margin-right: 1vw;
}
#sectionInnerImage-2row {
width: 48%;
max-width: 1000px;
display: inline-block;
margin-right: 1vw;
}
h1 {
font-size: 36px;
margin-bottom: 30px;
font-weight: 700;
font-family: Sans-Serif;
}
h2 {
font-size: 22px;
font-family: Sans-Serif;
font-weight: 700;
margin-top: 15px;
}
h3 {
font-size: 13px;
font-family: Sans-Serif;
font-weight: normal;
margin-bottom: 30px;
}
h4 {
font-size: 17px;
font-family: Sans-Serif;
font-weight: 700;
margin-top: 5px;
margin-bottom: 0;
display: inline-block;
}
p {
font-size: 19px;
line-height: 180%;
font-family: Georgia, Cambria, "Times New Roman", Times, serif;
font-weight: normal;
margin: 15px 0;
}
a.one {
display: block;
color: #fff;
background-color: var(--main-color);
padding: 16px;
text-decoration: none;
text-align: center;
border-radius: 3px;
font-family: 'Open Sans', sans-serif;
font-size: 16px;
max-width: 350px;
}
a.one:hover {
background: #4C03F1;
}
a.one:active {
background-color: var(--main-color);
}
#media only screen and (min-width: 1080px) {
section {
min-height: 30vh;
}
}
#media only screen and (max-width: 1080px) {
html, body {
margin: 0;
color: #333;
overflow-x: hidden;
}
section {
width: 100%;
border-bottom: 1px solid #eee;
padding: 0px;
}
#sectionInnerText {
padding: 2vh 5vw;
}
#sectionInnerImage {
padding: 0 5vw;
}
#sectionInnerImage-rowWrapper {
padding: 0 5vw;
}
#sectionInnerImage-3row {
width: 100%;
max-width: 1000px;
}
#sectionInnerImage-2row {
width: 100%;
max-width: 1000px;
}
p {
font-size: 21px;
}
ul li {
font-size: 21px;
}
a.one, a.two, a.three, a.four {
display: block;
margin-bottom: 25px;
max-width: 100%;
max-width: 450px;
}
.dropdown-content {
width: 100vw;
margin: 0;
margin-top: -6px;
background-color: #fff;
min-width: 260px;
border: 0px solid #eee;
border-top: 1px solid #eee;
border-bottom: 0;
z-index: 1;
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.12);
}
.dropdown-content a{
border-bottom: 1px solid #f4f4f4;
}
}
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="nav-down">
<div id="navWrapper">
<div id="navLeft">
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Menu <i class="material-icons md-01">keyboard_arrow_down</i></button>
<div id="myDropdown" class="dropdown-content">
<i class="material-icons md-05">home</i> Home & Projects List
<i class="material-icons md-05">dashboard</i> Project 01
<i class="material-icons md-05">dashboard</i> Project 02
<i class="material-icons md-05">dashboard</i> Project 03
<i class="material-icons md-05">account_circle</i> Info & Contact
<i class="material-icons md-05">picture_as_pdf</i> View & Download Resume
</div>
</div>
</div>
</div>
</header>
I can't understand why this tutorial example does not work for me:
I have external js libraries:
"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"
"http://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"
And this code on load document:
<script type="text/javascript">
$(document).ready(function () {
$('input.typeahead').typeahead({
name: 'cars',
local: ['Audi', 'BMW', 'Bugatti', 'Ferrari', 'Ford', 'Lamborghini', 'Mercedes Benz', 'Porsche', 'Rolls-Royce', 'Volkswagen']
});
});
</script>
I have css:
<style type="text/css">
.bs-example {
font-family: sans-serif;
position: relative;
margin: 100px;
}
.typeahead, .tt-query, .tt-hint {
border: 2px solid #CCCCCC;
border-radius: 8px;
font-size: 24px;
height: 30px;
line-height: 30px;
outline: medium none;
padding: 8px 12px;
width: 396px;
}
.typeahead {
background-color: #FFFFFF;
}
.typeahead:focus {
border: 2px solid #0097CF;
}
.tt-query {
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
}
.tt-hint {
color: #999999;
}
.tt-dropdown-menu {
background-color: #FFFFFF;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 8px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
margin-top: 12px;
padding: 8px 0;
width: 422px;
}
.tt-suggestion {
font-size: 24px;
line-height: 24px;
padding: 3px 20px;
}
.tt-suggestion.tt-is-under-cursor {
background-color: #0097CF;
color: #FFFFFF;
}
.tt-suggestion p {
margin: 0;
}
</style>
And html code:
<body>
<div class="bs-example">
<input type="text" class="typeahead tt-query" autocomplete="off" spellcheck="false">
</div>
</body>
Can anyone help me ?
Trying to follow this tutorial in this book, but the images supplied are not being shown on the page my /views/layouts/ads.html.erb looks like this
<!doctype HTML>
<html>
<head>
<title>Ads: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'default.css' %>
</head>
<body>
<div id="wrapper">
<div id="header">
<div>
<h1>MeBay</h1>
<ul id="nav">
<li>All Ads</li>
</ul>
</div>
</div>
<div id="content">
<%= yield %>
</div>
<div id="clearfooter"></div>
</div>
<div id="footer"></div>
</body>
</html>
CSS in /app/assets/stylesheets looks like this
html, body { height: 100%; }
body { background-color: #e6dacf; background-image: url('/images/bg.png'); background-position: top center; background-repeat: repeat-y; font-family: "Trebuchet MS", Arial, san-serif; font-size: 14px; margin: 0; padding: 0; text-align: center; }
a { color: #000; }
a:hover { background: #000; color: #e6dacf; }
div#wrapper { min-height: 100%; }
* html div#wrapper { height: 100%; }
div#header { background: url('/images/bgHeader.png'); height: 100px; padding: 8px 0 0 0; }
div#header div { margin: 0 auto; position: relative; width: 800px; }
div#header h1 { left: 0; margin: 0; position: absolute; }
div#header h1 { background: url('/images/logo.png') no-repeat; display: block; height: 0; margin: 0 auto; padding: 92px 0 0 0; overflow: hidden; width: 319px; }
ul#nav { float: right; list-style: none; margin: 0; padding: 69px 0 0 0; }
ul#nav li { background: #e6dacf; border: solid #000; border-width: 2px 2px 0 2px; float: left; margin: 0 0 0 2px; }
ul#nav a { display: block; padding: 3px 6px 0 6px; text-decoration: none; }
ul#nav a:hover { display: block; padding: 3px 6px 7px 6px; }
ul#nav a.current { padding-bottom: 8px; }
ul#nav a.current:hover { background: #e6dacf; color: #000; cursor: default; }
div#content{ margin: 0 auto; padding: 20px 0; text-align: left; width: 720px; height: 300px}
div#content img { border: 10px solid #000; float: right; margin: 18px 0 0 20px; }
div#content h2 { border: solid #999; border-width: 0 0 5px 0; font-size: 28px; margin: 0; padding: 0 0 10px 0; }
div#content p { margin: 0; padding: 4px 6px 10px 0; }
div#clearfooter { height: 110px; }
div#footer { background: url('/images/bgFooter.png'); height: 110px; margin: -110px auto 0 auto; }
and I placed the supplied images in /app/assets/images
This is how it should look, and also what it looks like for me
http://imgur.com/a/VEryr
You should debug these kinds of problems with either
Chrome Developer Tools
Firebug for Firefox
Both provide excellent support for resolving js / css related issues.
In your particular case, you need to check the Network or Net tabs in the tools to see how the CSS gets loaded. Most likely you'll see an error in loading the stylesheet.
The tool will show you the CSS path its trying to access and you can debug it from there...