I have a PhoneGap app that displays a quite long text with headers, tables and images which I am testing on Android.
Everything works fine except for the elements with style position:relative
These elements "lag" behind when scrolling, meaning if I scroll the page then those elements start and end scrolling about a quarter of a second later.
The bug happens when combining an absolute div with relative children and a child with overflow:auto. Removing any of those things fixes the bug but I'd prefer do leave it in. Although I'd be willing to remove the table and show it separately (like in a dialog) if I have to.
The bug only presents on the standard Android Browser (and of course my PhoneGap app).
So far I've tested it with the following devices:
Samsung Galaxy Nexus (4.1.1)
Samsung Galaxy S III (4.1.2)
Any help is appreciated but I'd prefer a solution where the HTML and functionality are not changed (or not too much).
I created a minimal example showing the bug. Simply open it on your Android and start scrolling and you should see the problem immediately:
<!doctype html>
<html>
<head><meta name="viewport" content="initial-scale=1.0"></head>
<body style="margin:0">
<div style="position:absolute;overflow:auto;top:100px;bottom:100px;width:100%">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam a quam arcu. Duis ultrices mollis nibh ut hendrerit. Etiam a interdum metus. Integer volutpat, nibh laoreet euismod suscipit, libero sem iaculis lorem, ut hendrerit magna orci eu elit. Nulla eu ultricies libero. Nulla facilisi. Maecenas nec turpis vitae magna lobortis ornare sit amet ut lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc vestibulum lobortis orci, sit amet ornare dui congue nec. Morbi id magna at turpis auctor ultricies. Ut rhoncus quam augue, ut consectetur risus.</p>
<div style="position:relative;background:red;">relative box<br>moves slower than the other text</div>
<p>Fusce congue orci a nunc gravida sed pretium lorem convallis. Etiam hendrerit, ligula eget lobortis vestibulum, arcu sapien pharetra magna, auctor suscipit nisl tellus quis lacus. Cras id elit at ante mollis venenatis. Donec eu sollicitudin odio. Aliquam erat volutpat. Cras et tortor sed mi faucibus sagittis non quis metus. Morbi mauris ante, posuere vel rutrum id, mattis id enim. Morbi purus quam, euismod facilisis blandit quis, commodo at justo. Aliquam in fermentum nibh. Curabitur pharetra blandit risus sit amet tristique. Suspendisse potenti. Curabitur interdum eleifend justo, et dapibus justo volutpat sed.</p>
<div style="overflow:auto">
<table>
<tr><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th></tr>
<tr><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td></tr>
</table>
</div>
</div>
</body>
</html>
In short, the ills you are suffering are common and documented. Elements with overflow:auto or overflow:scroll suffer from paint/reflow/render issues in both desktop and mobile browsers. To compound upon that there are issues in mobile browsers (webkit both on iOS and Android) with regards to not rendering relative and absolute elements if they are "off screen". This can lead to a lag when they are scrolled on screen.
There are a few "hack" shims that you can apply:
element {
-webkit-overflow-scrolling: touch;
}
element > * {
-webkit-transform: translateZ(0px);
}
element > * {
-webkit-transform: translate3d(0,0,0);
}
Some reading for you:
http://cantina.co/2012/03/06/ios-5-native-scrolling-grins-and-gothcas/
http://developersday.wordpress.com/2012/08/07/scrollable-divs-rendering-issues-with-css-overflow-auto-or-scroll-iosandroid/
And a snippet I copied from somewhere into my notes and now can't find the source:
Especially on sites that rely heavily on scroll, you might discover
that your main content is relying on overflow:scroll. This is a real
challenge as this scrolling isn’t GPU accelerated in any way so the
content is repainted whenever your user scrolls. You can work around
such issues using normal page scroll (overflow:visible) and
position:fixed.
I think you have two issues you're trying to fix. The text that slips down below and the lagging scroll speed?
I'm not sure what you're trying to do with the copyright symbol but I wouldn't have a line-height less than 1 or 1em. Try to use a parent element and style the span off of that. You can probably use display:inline-block; vertical-align: middle; on the span to get the desired effect.
<p><span>©</span>Some text</p>
For scrolling it depends on what you're doing. Mobile browsers wait 300ms for <a> tags to see if you are scrolling or clicking a link. It could be related to that. If so, I'd checkout Google FastClick.
Mobile browsers accelerate page scrolling on the body. So using nested divs or position:absolute could keep you from getting the faster scroll speed. In newer versions of Android and iOS you can use -webkit-overflow-scrolling: touch to help but that won't do anything for older phones. I would try not to use position absolute because based on your example it doesn't look like its required, also using nested divs that scroll require some users to use two fingers inside the div to scroll content. I would try to avoid that as well and replace the design with more mobile friendly design patterns like a link that expands content down.
A lot of the scrolling issues have came to light while trying to support position:fixed on mobile if think that might be causing it and you'd like to read about it: http://bradfrostweb.com/blog/mobile/fixed-position/
Remove position:absolute and position:relative , they are absolutely NOT needed for this layout and are causing all your problems.
You can add some margin-top to your body if you wish.
PhoneGap produces some html garbage like that, I hope that you have a fine control of the CSS.
Actually there's a simple CSS fix for it, adding position:relative to your paragraphs solve the problem.
Try this:
<!doctype html>
<html>
<head><meta name="viewport" content="initial-scale=1.0">
<style>
p{ position:relative;}
</style>
</head>
<body style="margin:0">
<div style="position:absolute;overflow:auto;top:100px;bottom:100px;width:100%">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam a quam arcu. Duis ultrices mollis nibh ut hendrerit. Etiam a interdum metus. Integer volutpat, nibh laoreet euismod suscipit, libero sem iaculis lorem, ut hendrerit magna orci eu elit. Nulla eu ultricies libero. Nulla facilisi. Maecenas nec turpis vitae magna lobortis ornare sit amet ut lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc vestibulum lobortis orci, sit amet ornare dui congue nec. Morbi id magna at turpis auctor ultricies. Ut rhoncus quam augue, ut consectetur risus.</p>
<div style="position:relative;background:red;">relative box<br>moves slower than the other text</div>
<p>Fusce congue orci a nunc gravida sed pretium lorem convallis. Etiam hendrerit, ligula eget lobortis vestibulum, arcu sapien pharetra magna, auctor suscipit nisl tellus quis lacus. Cras id elit at ante mollis venenatis. Donec eu sollicitudin odio. Aliquam erat volutpat. Cras et tortor sed mi faucibus sagittis non quis metus. Morbi mauris ante, posuere vel rutrum id, mattis id enim. Morbi purus quam, euismod facilisis blandit quis, commodo at justo. Aliquam in fermentum nibh. Curabitur pharetra blandit risus sit amet tristique. Suspendisse potenti. Curabitur interdum eleifend justo, et dapibus justo volutpat sed.</p>
<div style="overflow:auto">
<table>
<tr><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th> <th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th><th>test</th> <th>test</th><th>test</th><th>test</th><th>test</th><th>test</th></tr>
<tr><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td> <td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td><td>test</td> <td>test</td><td>test</td><td>test</td><td>test</td><td>test</td></tr>
</table>
</div>
</div>
</body>
</html>
Related
I have the text has HTML tags to give each of them a specific style.
I saw these two questions Programmatically highlight String matches in Flutter Richtext and How to write a Reg Expression of a string that contains two tilde ~ , or two underscore and I tried to replace my RegExp pattern but no result.
final regex = RegExp(r"(?<=\<header>)(.*?)(?=\</header>)");
final rx = RegExp(r"(?=\<[^>]*>)");
My text with tags:
<header>Lorem ipsum dolor sit amet</header>
<title>consectetur adipiscing elit</title>
Cras nisl justo, hendrerit accumsan fringilla et, vehicula non elit. Nam dapibus, ex
consequat tincidunt malesuada, tellus nisi faucibus neque, ac ultricies neque ligula
sed sem. <poetry>Nulla non diam non diam faucibus sodales.<footnote>(1)</footnote>
Nulla lorem risus, ornare at pellentesque at, faucibus sit amet nisl</poetry>.
Pellentesque auctor tincidunt ligula id efficitur. Duis cursus tortor tellus.
Nullam in diam eget sem maximus porttitor.<b1></b1>
Tags explain:
header: Bold text and font size 20
title: Bold text
poetry: Green Text
footnote: Superscript
b1: Icon button
How can I create a custom TextSpan and style the text between two tags and then remove the tags using the RegExp pattern?? Any help?
I have one large TextView, which is a larger amount of HTML text depending on what is being displayed.
Even though all of the content is in a single TextView, I want the paragraphs contained inside the view to be separate Talkback items. They are HTML formatted with the <p> tag
Right now, it reads everything at once
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam
consequat, magna a ornare pharetra, diam arcu rhoncus elit, at
consectetur arcu lectus nec nulla.
Ut hendrerit id ante ac lobortis. Morbi ante quam, malesuada eget
lobortis vel, porttitor ac felis. Quisque diam purus, dignissim id
eros ac, semper mollis elit.
Vivamus iaculis mollis suscipit. Vivamus vel posuere ipsum, et
accumsan lectus. Donec tincidunt justo orci, eget molestie sem tempor
sed. Duis quis lorem neque.
But I would like it to be broken up without breaking the text out of TextView into a list.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam
consequat, magna a ornare pharetra, diam arcu rhoncus elit, at
consectetur arcu lectus nec nulla.
Break
Ut hendrerit id ante ac lobortis. Morbi ante quam, malesuada eget
lobortis vel, porttitor ac felis. Quisque diam purus, dignissim id
eros ac, semper mollis elit.
Break
Vivamus iaculis mollis suscipit. Vivamus vel posuere ipsum, et
accumsan lectus. Donec tincidunt justo orci, eget molestie sem tempor
sed. Duis quis lorem neque.
Is this possible to do within one TextView?
Try this..
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mTxtBio.setText(Html.fromHtml(ProfileVal.getBio(), Html.FROM_HTML_MODE_COMPACT));
} else {
mTxtBio.setText(Html.fromHtml(ProfileVal.getBio()));
}
mTxtBio.setLineSpacing(3, 1.3f);
I'm not an android developer so this might be a stupid idea but can a TextView have nested TextViews so that the nested TextViews have each sentence separately?
I'm also a little confused about what's displayed in the TextView. Usually plain text is displayed but it sounds like you are displaying HTML? Or are you formatting the text using HTML in order to get linebreaks and such?
Screen readers usually read the entire contents of an element when it's focused. With a large chunk of text in a TextView, all of it would be read (which is what you're trying to avoid). A screen reader user has the ability to navigate sentence by sentence or paragraph by paragraph (or even character by character or word by word) so you don't really have to force things to be read separately.
i am sure that there is easy way but i searched and could not find the solution,
i get data from text column of mssql as string, and i want to show data as like shown in column.
I mean my data like
Lorem ipsum dolor sit amet,
consectetur adipiscing elit. In condimentum turpis nibh.
Vivamus scelerisque odio sit amet nisi dignissim, at pellentesque ligula dapibus. Nulla et lacinia dolor.
Aenean sed faucibus felis, in molestie tellus.
Bu when i setText to textview it is like;
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In condimentum turpis nibh. Vivamus scelerisque odio sit amet nisi dignissim, at pellentesque ligula dapibus. Nulla et lacinia dolor. Aenean sed faucibus felis, in molestie tellus.
How can i show text as i want in textviev? Thanks for help
You have to format the text with Html(like inserting paragraph tag) in your server (i.e. in your database)and then receive it in your application.
Then in the text you can set the text as:
text.setText(Html.fromHtml("your text"));
I have a TextView inside a ScrollView, the TextView is filled with a large text which only some part of its text is visible on screen at anytime.
Now I want to (programmatically) force some part of the text to be visible for user. for example, my text is:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut id ante tellus. Nulla facilisi. Sed gravida fringilla velit, non sollicitudin tellus egestas non. Cras congue, nulla id bibendum tempus, dui dui blandit elit, elementum dictum dolor eros et mi. Nullam leo tellus, aliquet vel tincidunt sed, suscipit nec dui. Nunc dapibus, odio vestibulum hendrerit vestibulum, lorem orci dictum arcu, quis porttitor lorem libero sit amet odio. Sed imperdiet viverra diam, eu porttitor ipsum fringilla et. Suspendisse consectetur sapien ac felis tincidunt dictum. Suspendisse ultrices porta dignissim. Maecenas in nibh sed nisi facilisis dignissim non ut tortor. Pellentesque eleifend tempus sem, sit amet mattis arcu auctor id. Vivamus at tortor rutrum diam vestibulum adipiscing. Suspendisse potenti. Integer sollicitudin laoreet enim ac suscipit. Quisque convallis facilisis pharetra.
I want to force the bold word (tortor in this example) to be visible to the user (maybe by scrolling the textview vertically with a correct value).
Is there any way to do this?
EDIT: I don't want to make the word bold! question updated to clarify my request.
Here is one way to scroll to a particular word:
public void scrollToWord(String string) {
TextView textView = (TextView) findViewById(R.id.text1);
String text = textView.getText().toString();
// Find the first occurrence of the word
int position = text.indexOf(string);
// Calculate how far in the word is: 30%, 40%, 73%
int percent = (int) (position / (double) text.length() * 100);
// Calculate how far to scroll
int y = textView.getHeight() * percent;
// Finally scroll
((ScrollView) textView.getParent()).scrollTo(0, y);
}
I have two notes on this:
This only scrolls to the first occurrence, but it is easy enough to change to String.indexOf(string, start) and find the second, third, etc.
If you want to scroll to this position as soon as the app has started, you must wait until after onResume() has finished. But there is no method for this... I suggest using a Handler and I can help you with that if you need it.
Hope that helps!
It would be quite an effort, but using android.graphics.Paint#measureText(...) resp. breakText(...) it should be possible to calculate how for you'd have to scroll to make the desired word visible. You'd have to take into account the font, font-size, size of the view showing the text, etc. etc.
You can use html tags with bold option to make that particular word bold.
I have been unable to understand how the width and initial-scale properties of viewport meta tag works
I have the following HTML code.
<!DOCTYPE HTML>
<html>
<head>
<title>Viewport example A</title>
<meta name="viewport" content="width=321,initial-scale=1">
<style type="text/css">
body {
background: #800000;
}
p {
background: #ffffff;
border: 1px solid gray;
margin-left: 20%;
margin-right: 20%;
}
</style>
</head>
<body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut eu massa
erat, eget bibendum tortor. Class aptent taciti sociosqu ad litora
torquent per conubia nostra, per inceptos himenaeos. Aenean lobortis,
leo et porttitor venenatis, sapien nunc sodales elit, ut condimentum
nibh lacus sed erat. Suspendisse potenti. Mauris facilisis, odio nec
commodo tempor, sem arcu dictum lacus, ac ultrices quam purus ultrices
nisl. Nullam cursus consequat nisl non sagittis. Cras convallis porta
dui eu viverra. Maecenas ultrices arcu sit amet nisi pharetra non
malesuada erat tempus.
</p>
</body>
</html>
I change the width and initial-scale properties and test the output with Samsung Galaxy SII phone with user-agent: Mozilla/5.0 (Linux; U; Android 2.3.4; en-gb; GT-I9100G Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1.
The following three images have the following three properties respectively.
width=321,initial-scale=2
width=321,initial-scale=1
width=321,initial-scale=0.5
.... ....
The output above is what I expect. With initial-scale=2, the font as well as margins have been scaled twice that of initial-scale=1 and 4 times that of initial-scale=0.5. I get similar expected output for any width > 320.
The following three images have the following three properties respectively.
width=320,initial-scale=2
width=320,initial-scale=1
width=320,initial-scale=0.5
.... ....
The output here doesn't make sense to me.
The margin seen with initial-scale=2 is same as that seen with initial-scale=1. Why?
With initial-scale=0.5 we see that the margin is twice what we see with initial-scale=1. Why has the margin doubled instead of shrinking to half? Why hasn't the font changed here at all?
I get similar output that doesn't make sense to me for any width ≤ 320.