तुम क्यों स्वीकार किए जाते हैं जवाब में इस सवाल का जवाब पर विचार करना चाहिए:
स्वीकृत जवाब सभ्य प्रदान करता है और सरल तरह से स्थिति स्क्रॉल को बचाने के लिए, लेकिन यह सही से दूर है। उस दृष्टिकोण के साथ समस्या यह है कि कभी-कभी घूर्णन के दौरान आप घूर्णन से पहले स्क्रीन पर देखे गए किसी भी तत्व को भी नहीं देख पाएंगे। स्क्रीन के शीर्ष पर मौजूद तत्व अब घूर्णन के बाद नीचे हो सकता है। स्क्रॉल के प्रतिशत के माध्यम से स्थिति को सहेजना बहुत सटीक नहीं है और बड़े दस्तावेजों पर यह गलतता बढ़ सकती है।
तो यहां एक और तरीका है: यह तरीका अधिक जटिल है, लेकिन यह लगभग गारंटी देता है कि घूर्णन से पहले आपने घूर्णन के बाद बिल्कुल वही तत्व दिखाई देगा। मेरी राय में, यह विशेष रूप से एक बड़े दस्तावेज़ों पर, एक बेहतर उपयोगकर्ता अनुभव की ओर जाता है।
======
सबसे पहले, हम जावास्क्रिप्ट के माध्यम से वर्तमान पुस्तक स्थिति को ट्रैक करेगा। यह हमें यह जानने की अनुमति देगा कि वर्तमान में स्क्रीन के शीर्ष पर कौन सा तत्व मौजूद है और यह कितना स्क्रॉल किया गया है।
सबसे पहले, यह सुनिश्चित करें कि जावास्क्रिप्ट अपने WebView के लिए सक्षम किया गया है:
public class WebScrollListener {
private String element;
private int margin;
@JavascriptInterface
public void onScrollPositionChange(String topElementCssSelector, int topElementTopMargin) {
Log.d("WebScrollListener", "Scroll position changed: " + topElementCssSelector + " " + topElementTopMargin);
element = topElementCssSelector;
margin = topElementTopMargin;
}
}
फिर हम इस वर्ग जोड़ें:
webView.getSettings().setJavaScriptEnabled(true);
इसके बाद, हम जावा वर्ग है कि जावास्क्रिप्ट के भीतर से जानकारी को स्वीकार करेंगे बनाने की जरूरत वेबव्यू पर:
scrollListener = new WebScrollListener(); // save this in an instance variable
webView.addJavascriptInterface(scrollListener, "WebScrollListener");
अब हमें HTML पृष्ठ में जावास्क्रिप्ट कोड डालने की आवश्यकता है। यह स्क्रिप्ट जावा के लिए स्क्रॉल डेटा भेज देंगे (यदि आप पीढ़ी एचटीएमएल हैं, बस इस स्क्रिप्ट संलग्न हैं अन्यथा आपको webView.loadUrl("javascript:document.write(" + script + ")");
के माध्यम से document.write()
बुला का सहारा की जरूरत हो सकती):
<script>
// We will find first visible element on the screen
// by probing document with the document.elementFromPoint function;
// we need to make sure that we dont just return
// body element or any element that is very large;
// best case scenario is if we get any element that
// doesn't contain other elements, but any small element is good enough;
var findSmallElementOnScreen = function() {
var SIZE_LIMIT = 1024;
var elem = undefined;
var offsetY = 0;
while (!elem) {
var e = document.elementFromPoint(100, offsetY);
if (e.getBoundingClientRect().height < SIZE_LIMIT) {
elem = e;
} else {
offsetY += 50;
}
}
return elem;
};
// Convert dom element to css selector for later use
var getCssSelector = function(el) {
if (!(el instanceof Element))
return;
var path = [];
while (el.nodeType === Node.ELEMENT_NODE) {
var selector = el.nodeName.toLowerCase();
if (el.id) {
selector += '#' + el.id;
path.unshift(selector);
break;
} else {
var sib = el, nth = 1;
while (sib = sib.previousElementSibling) {
if (sib.nodeName.toLowerCase() == selector)
nth++;
}
if (nth != 1)
selector += ':nth-of-type('+nth+')';
}
path.unshift(selector);
el = el.parentNode;
}
return path.join(' > ');
};
// Send topmost element and its top offset to java
var reportScrollPosition = function() {
var elem = findSmallElementOnScreen();
if (elem) {
var selector = getCssSelector(elem);
var offset = elem.getBoundingClientRect().top;
WebScrollListener.onScrollPositionChange(selector, offset);
}
}
// We will report scroll position every time when scroll position changes,
// but timer will ensure that this doesn't happen more often than needed
// (scroll event fires way too rapidly)
var previousTimeout = undefined;
window.addEventListener('scroll', function() {
clearTimeout(previousTimeout);
previousTimeout = setTimeout(reportScrollPosition, 200);
});
</script>
आप इस बिंदु पर अपने अनुप्रयोग चलाते हैं, आपको पहले से ही लॉगकैट में संदेश दिखाना चाहिए जो आपको बता रहा है कि नई स्क्रॉल स्थिति प्राप्त हुई है।
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
webView.saveState(outState);
outState.putString("scrollElement", scrollListener.element);
outState.putInt("scrollMargin", scrollListener.margin);
}
फिर हम onCreate में इसे पढ़ा (गतिविधि के लिए) या onCreateView (टुकड़ा के लिए) विधि:
if (savedInstanceState != null) {
webView.restoreState(savedInstanceState);
initialScrollElement = savedInstanceState.getString("scrollElement");
initialScrollMargin = savedInstanceState.getInt("scrollMargin");
}
हम भी जोड़ने की जरूरत है
अब हम WebView राज्य को बचाने की जरूरत हमारे WebView को WebViewClient
और ओवरराइड onPageFinished
विधि:
@Override
public void onPageFinished(final WebView view, String url) {
if (initialScrollElement != null) {
// It's very hard to detect when web page actually finished loading;
// At the time onPageFinished is called, page might still not be parsed
// Any javascript inside <script>...</script> tags might still not be executed;
// Dom tree might still be incomplete;
// So we are gonna use a combination of delays and checks to ensure
// that scroll position is only restored after page has actually finished loading
webView.postDelayed(new Runnable() {
@Override
public void run() {
String javascript = "(function (selectorToRestore, positionToRestore) {\n" +
" var previousTop = 0;\n" +
" var check = function() {\n" +
" var elem = document.querySelector(selectorToRestore);\n" +
" if (!elem) {\n" +
" setTimeout(check, 100);\n" +
" return;\n" +
" }\n" +
" var currentTop = elem.getBoundingClientRect().top;\n" +
" if (currentTop !== previousTop) {\n" +
" previousTop = currentTop;\n" +
" setTimeout(check, 100);\n" +
" } else {\n" +
" window.scrollBy(0, currentTop - positionToRestore);\n" +
" }\n" +
" };\n" +
" check();\n" +
"}('" + initialScrollElement + "', " + initialScrollMargin + "));";
webView.loadUrl("javascript:" + javascript);
initialScrollElement = null;
}
}, 300);
}
}
यह है। स्क्रीन रोटेशन के बाद, आपकी स्क्रीन के शीर्ष पर मौजूद तत्व अब वहां रहना चाहिए।
@ ol_v-er जानकारी के लिए धन्यवाद। मैं देरी को शुरू करने का प्रयास करने में रूचि रखता हूं क्योंकि आप 'स्क्रॉल टू' काम देखने के लिए वर्णन करते हैं (मुझे आश्चर्य है कि देरी की आवश्यकता है लेकिन वैसे भी ...)। अंततः एक जावास्क्रिप्ट समाधान (जिसे मैं जल्द ही पोस्ट करूंगा) के माध्यम से काम करने के लिए स्क्रॉलिंग प्राप्त कर रहा हूं, मुझे प्रतिशत स्क्रॉलिंग का विचार था जो मुझे परिणाम देखने के लिए अभी तक प्रयास करने के लिए नहीं मिला है। – PJL
वास्तव में जब ऑनपेजफिश किए गए कॉलबैक को कॉल किया जाता है, तो वेबव्यू बस ड्राइंग शुरू कर देता है। देरी यह सुनिश्चित करना है कि वेबव्यू ने ड्राइंग समाप्त कर दी है (और सही ऊंचाई है)। अपने जावास्क्रिप्ट समाधान के लिए तत्पर हैं। –
धन्यवाद, मेरे जावास्क्रिप्ट समाधान जोड़ा गया। – PJL