Android Webview Anchor Link (Jump Link) Not Working

Android Webview Anchor Link (Jump link) not working

It looks like the problem is that I had a WebView within a ScrollView. The WebView isn't able to scroll to an anchor link when configured like this. After refactoring my layout to eliminate the ScrollView, the anchor links work correctly.

Android: Make anchor links work in WebView inside ScrollView

Since it frustrates me when I stumble upon a question without answers, I will answer my own question, so others will know how I resolved this issue.

Bad news is, this particular issue cannot be resolved. At least, not yet in 2021.

What the company I am working at and the client decided to do is change the entire implementation of this screen. The entire screen is now a WebView, instead of just a part of the screen being a WebView.

named anchor not working webview android

Where does your program fail - with the loading or when you click the anchor? It sounds like the problem is with your HTML file, so you should probably show the code from that instead. :) Also, the full LogCat output is handy too. The more info the merrier.

I recently implemented a WebView, the HTML code is extremely straight-forward (since I know close to no HTML and just wanted an easy way to display documentation). A simple anchor is just this for example:

<a href="#q1">Navigating the application</a>

...

<a name="q1"></a>
<p><b>Navigating the application</b></p>
<p>...sliding motion (to the left or to the right) with your finger...</p>

If your program is failing at the actual loading part, then ensure that you have placed the topics.html file correctly in the /assets/ folder in your project folder. It has to be at the very root of your project folder - ie. workspace\<projectname>\assets\topics.html

Your code for loading the webpage looks fine.

Android : Html Anchor Link works only once in webview

The problem was to Reload the Page again after Anchor link Click.

I have used the following code,

chapters.xml in Assets folder

<html>
<body>
<p><a href="#C4">See also Chapter 4</a></p>
<p><h2><a name='C1'>Chapter 1<a></h2><p>This chapter explains ba bla bla</p>
<h2>Chapter 2</h2><p>This chapter explains ba bla bla</p>
<h2>Chapter 3</h2><p>This chapter explains ba bla bla</p>
<h2><a name='C4'>Chapter 4</a></h2><p>This chapter explains ba bla bla</p>
<h2>Chapter 5</h2><p>This chapter explains ba bla bla</p>
<h2>Chapter 6</h2><p>This chapter explains ba bla bla</p>
<h2>Chapter 7</h2><p>This chapter explains ba bla bla</p>
<a href="#C1">See also Chapter 1</a>
</body>
</html>

JAVA code : First Way

public class MainActivity extends Activity {
WebView myWebView;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myWebView = new WebView(this);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/chapters.html");

setContentView(myWebView);

final GestureDetector gestureDetector = new GestureDetector(
new MyGestureDetector());
View.OnTouchListener gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
myWebView.setOnTouchListener(gestureListener);
}

class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
myWebView.reload();
Log.i("", "Reload");
return super.onSingleTapConfirmed(e);

}
}
}

EDIT JAVA CODE : Second Way - I have tried this thing insted onTouchListener and that working fine for me.

public class MainActivity extends Activity {
WebView myWebView;
public static boolean flag = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myWebView = new WebView(this);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/chapters.html");
setContentView(myWebView);
myWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
if (url.contains("#") && flag == false) {
myWebView.loadUrl(url);
flag = true;
} else {
flag = false;
}
}

});
}
}

To Open Another HTML File's Anchor Tag from One file

        myWebView = new WebView(this);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/1.htm");
myWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
try{
chapter = url.substring(url.indexOf("#"),url.length());
url = url.substring(0,url.indexOf("#"));
}catch (Exception e) {
chapter = "";
}
myWebView.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
if (!chapter.equalsIgnoreCase("") && flag == false) {
myWebView.loadUrl(url+chapter);
flag = true;
} else {
flag = false;
}
}
});
setContentView(myWebView);

WebView jump to anchor using loadDataWithBaseUrl

How about control it by JavaScript? I didn't try it but maybe this is a clue.

builder.append(getThreadBody());
builder.append("<script>window.location.hash="949823";</script>");
builder.append("</body></html>");

Remember enable javascript for WebView.

----Additional Answer----

I saw that you use TimerTask to load the javascript, That works but I think there is another better way. WebView have a callback named onPageFinished and it will be trigger when WebView finish loading webpage. You could inject your JS there.

webContents.setWebViewClient(new WebViewClient(){

@Override
public void onPageFinished(WebView view, String url) {
String id = "895884";
webContents.loadUrl("javascript:scrollAnchor(" + id + ");");
}

});

Hope this is useful!

Android WebView does not work with Wordpress menu based on Anchor Link (Jump Link)

I finally figure that out, problem was that my webview was not fully support html5:

mWebView.setFocusable(true);
mWebView.setFocusableInTouchMode(true);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setDatabaseEnabled(true);
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

JavaFX WebView: link to anchor in document doesn't work using loadContent()

It's probably another WebEngine bug. A lot of that code is just a native libraries wrapped in api, so we can't modify it in runtime to fix some disabilities.

If you are able to change the structure of generated file you can implement scrolling to element in js:

<script>
function scrollTo(elementId) {
document.getElementById(elementId).scrollIntoView();
}
</script>

<a href='#' onclick=scrollTo('CX')>Jump to Chapter X</a>
<h2 id="CX">Chapter X</h2>

If you can't change the structure, there is some steps that I've made to try to fix it and some suggestions - at first I've set value of location by reflections after loadContent for sure:

Field locationField = WebEngine.class.getDeclaredField("location");
locationField.setAccessible(true);

ReadOnlyStringWrapper location = (ReadOnlyStringWrapper) locationField.get(engine);
location.set("local");

But in fact, keeping state of actual location is just an information for you and manipulating this changes nothing. I've also found a way to set url from js (just a long shot, we don't have any specific details why it's not working):

window.history.pushState("generated", "generated", '/generated');

Of course we can't because of:

SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.

I think you should forget about loadContent(). You said that you didn't want to write generated content to file. A little dirty hack but really helpful for you could be wrapped http server on random and unused port in your application. You don't even need external libraries because Java has simple utilities like that:

HttpServer server = HttpServer.create(new InetSocketAddress(25000), 0);
server.createContext("/generated", httpExchange -> {
String content = getContent();
httpExchange.sendResponseHeaders(200, content.length());
OutputStream os = httpExchange.getResponseBody();
os.write(content.getBytes());
os.close();
});

server.setExecutor(null);
server.start();

You can also use another browser to display your page, e.g. JCEF (Java Chromium Embedded Framework).

Android Webview, working with Anchors

Try using valid URL as a base URL in loadDataWithBaseURL(), such as app://myhtml.

Also, to make sure the data was loaded implement WebViewCLient.onPageFinished().



Related Topics



Leave a reply



Submit