저는 주로 HTML 파일을 사용하는 e- 리더로 문서를 표시하기 위해 KitKat 수준의 WebView를 사용하는 Android 앱이 있습니다. 사용자가 앱 내에서 문서를 열면 (따라서 웹보기가 해당 문서에 대해 새로 인스턴스화 됨) 문서 내에서 마지막으로 알려진 커서 위치로 스크롤하여 사용자가 중단 한 곳에서 읽을 수 있도록합니다. 분명히 나는 문서를 열 때 그러한 스크롤을 허용하기 위해 웹 뷰의 커서 위치를 indepedently 유지하고 유지한다.안드로이드 webview는 마지막 스크롤 위치에서 일관되게 열리지 않습니다.
문제점 : 문서가 처음 열리면 내 javascript 문서에서 마지막으로 알려진 위치 (커서)의 초기 강조 표시를 볼 수 있지만 그 중 50 %는 문서를 어떻게 든 본 뒤로 스크롤합니다. 커서 위치가 더 이상 표시되지 않습니다. 어떻게 그리고 왜 이런 경우에 맨 위로 스크롤 하는가는 나에게 수수께끼이다 (나는 프로그래밍 방식으로 어떤 식 으로든 맨 위로 스크롤하도록 만든다.)
NOTES : webview에서 스크롤을 수행하려면 webview가로드되고 사용할 준비가되었음을 알리면 webview 조각 (webview.loadUrl을 통해)에서 호출되는 javascript 함수를 사용하고 있습니다.
\t @TargetApi(Build.VERSION_CODES.KITKAT) @SuppressLint("ClickableViewAccessibility") @Override
\t public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
\t { \t \t
\t \t View mainView = inflater.inflate(R.layout.document_webview_reader, container, false);
\t \t getReaderActivity().setFooterLocationBarValues(mainView);
\t \t
\t \t mWebviewLoading = true;
\t \t final WebView webview = (WebView) mainView.findViewById(R.id.document_webReader_webView);
\t \t webview.getSettings().setJavaScriptEnabled(true);
\t \t webview.getSettings().setAllowFileAccessFromFileURLs(true);
\t \t webview.getSettings().setAllowUniversalAccessFromFileURLs(true);
\t \t webview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
\t \t webview.setBackgroundColor(0);
\t \t webview.setBackgroundColor(Color.LTGRAY);
\t \t
\t \t if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
\t \t {
\t \t WebView.setWebContentsDebuggingEnabled(true);
\t \t }
\t \t
\t \t mJsInterface = new JsCall();
\t \t webview.addJavascriptInterface(mJsInterface, mJsInterface.getInterfaceName());
\t \t
\t \t webview.setWebViewClient(new WebViewClient()
\t \t { \t \t \t
\t \t \t public void onPageFinished(WebView view, String url)
\t \t \t {
\t \t \t \t drawInitialCursor(getDocument().getCursorRange()); \t \t \t \t \t \t
\t \t \t }
\t \t });
\t \t
\t private void drawInitialCursor(final WordRange range)
\t {
\t \t if(getReaderActivity().activityIsPaused()) return;
\t
\t \t getActivity().runOnUiThread(new Runnable()
\t \t {
\t \t \t
\t \t \t @Override
\t \t \t public void run()
\t \t \t {
\t \t \t \t Log.d(ReaderApplication.VDREADER_TAG,"highlighting initial range");
\t \t \t \t WordRange currentFragmentRange = mTextFragmentRanges.get(mCurrentTextFragmentIndex);
\t \t \t \t int relativeLocation = range.getLocation() - currentFragmentRange.getStartRange();
\t \t \t \t WordRange rangeInCurrentFragment = new WordRange(relativeLocation, range.getLength());
\t \t \t \t \t \t
\t \t \t \t WebView webview = (WebView) getActivity().findViewById(R.id.document_webReader_webView);
\t \t \t \t
\t \t \t \t String applyString = String.format("javascript:highlightInitialRange(%d,%d,%d,%d)",
\t \t \t \t \t \t rangeInCurrentFragment.getStartRange(),rangeInCurrentFragment.getEndRange(),
\t \t \t \t \t \t mCurrentTextFragmentIndex,
\t \t \t \t \t \t mCursorPositionSetting.ordinal());
\t \t \t \t webview.loadUrl(applyString);
\t \t \t }
\t \t });
\t }
'highlightInitialRange'의 자바 스크립트는 :
function highlightInitialRange(start, end, elementIndex, cursorPagePositionSetting)
{
if(wordHighlightApplier == null) {
wordHighlightApplier = rangy.createClassApplier("voice-dream-spoken-word",
{ elementTagName: "vdword"}
);
}
if(selRange == null) {
selRange = rangy.createRange();
}
wordHighlightApplier.undoToRange(selRange);
var \t myNodelist = document.querySelectorAll(VD_cssSelector);
selRange.selectCharacters(myNodelist[elementIndex], start, end);
wordHighlightApplier.applyToRange(selRange);
var wordCursor = document.getElementsByTagName("vdword");
wordCursor[0].scrollIntoView(true);
}
상기 스크립트 이것은 웹보기에 문서 뷰 단편에서 콜백이고 기본적으로 문서에서 관련 범위를 찾습니다 (해당 요소 내에서 요소 색인과 오프셋의 조합)을 사용하여 강조 표시 한 다음 (강조 표시를 통해) 강조 표시된 요소를보기로 스크롤합니다.
제가 말했듯이이 전략은 일반적으로 문서가로드되고 웹보기를 사용할 준비가되었을 때 올바른 위치를 강조 표시 할 수 있기 때문에 일반적으로 작동합니다. 하지만 이것을 실행하는 시간의 50 %에서 커서가 잠깐 강조 표시되고 문서가 맨 위로 스크롤 될 때 사라집니다 (커서 범위가 문서의 처음 페이지를 넘었다 고 가정).
** 나는 정확한 커서 하이라이트 이미지를 여기에 올릴 것이나 분명히 나는 그런 사소한 일을 허용 할만큼 평판이 나쁘다. **
질문 : 여기 webview 문서 렌더링에 관한 것이 누락 되었습니까? 하이라이팅과 하이라이트 된 요소에 대한 초기 scroll-into-view의 관점에서 모든 것이 올바르게 작동한다는 것을 알고 있으며 일단 웹뷰가 완전히로드되면 강조 표시 코드를 실행합니다 (webview 클라이언트에서 onPageFinished를 통해 통지 됨). 문서가 맨 위의 스크롤 위치에 표시되도록 문서가 완전히로드 될 때 비 결정적으로 실행되는 무언가가 webview 자체에 있습니까? 나는 다양한 JS 라이브러리를로드하는 '래퍼'HTML 문서 사용되었다 - 등 JSQuery, 돌아 다니기에 알맞은를, 그리고 내 :
***
이 지나고 나서이 문제에 대한 해결은 매우 명백했다소유자에 의해 해결 JSext를 사용하여 문서 본문을로드/읽기를 원하는 '실제'html 문서로 대체했습니다.그래서보기의 HTML 문서 지점에서 로딩이 두 단계에서 발생했다 :
- 로드 래퍼
- 래퍼로드 실제 HTML 문서를 $ ("몸")를 통해 부하 ("")
이 2 단계 로딩 때문에 내 앱에서 Webview.onPageFinished 이벤트가 발생하는 것을보고 있었지만 이는 전체 본문이 아닌 래퍼 HTML의로드를 알리는 신호였습니다.
<body>
<script>
$("body").load("%s", function(response, status, xhr)
{
if (status == "error")
{
var msg = "Sorry but there was an error: ";
$("#error").html(msg + xhr.status + " " + xhr.statusText);
}
else
{
// append our line highlight div, floating
var newDiv = $("<div id='vd-spoken-line' class='voice-dream-spoken-line'/>");
$("body").append(newDiv);
notifyDocumentBodyLoaded(); <-- new callback to android app here
}
});
</script>
</body>
그래서 다음 'notifyDocumentBodyLoaded'안드로이드를 실행하십시오 JSQuery의 .load 방법이 성공적으로 완료 한 후 그래서 내가 할하는 데 필요한 모든 앱에 내 웹보기/자바 스크립트에서 명시 적으로 호출을 추가했다/자바 코드는 이전에 onPageFinished 메소드에서 실행되었지만 JSQuery에 의해 실제 문서 본문이로드 된 후에 만 가능합니다. 이렇게하면로드 순서 -> 커서 그리기 순서가 올바른 순서로 발생합니다. 해결 됐어.
(이 대답을 추가하는 것은 그래서 나는이 문제를 해결할 수) 업데이트 된 질문에서 언급 한 바와 같이
내 자신의 문제를 해결했습니다. 업데이트 된 질문 텍스트를 참조하십시오. – Scotty
커뮤니티를 위해 실제 답변을 게시하고 해결하십시오. – Ercan