2016-04-11 2 views
4

Я использую WebView для отображения содержимого html в своем приложении для чтения электронных книг, но при разработке его я столкнулся со следующей проблемой.
Я просматриваю электронную книгу и завершаю анализируемый контент в строке html, после того как webview загружает эту html-строку.
Размещение HTML-содержимого в двух столбцах внутри WebView

myView.setVerticalScrollBarEnabled(false); 
    myView.setHorizontalScrollBarEnabled(false); 
    myView.getSettings().setDisplayZoomControls(false); 

    myView.getSettings().setJavaScriptEnabled(true); 
    if (Build.VERSION.SDK_INT >= 11) myView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null); 

    myView.loadDataWithBaseURL("file:///android_asset/Text/", ebookContent, "text/html", "UTF-8", null); 

Я перемещаться по страницам по горизонтали «myView.scrollTo (ширина MyView * countPages, 0)» и горизонтальное размещение контента достигается за счет использования HTML форматирования/добавления стилей предложен Uday Sravan K , Спасибо ему:

myView.setWebViewClient(new WebViewClient() { 
    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
     view.loadUrl(url); 
     return true; 
    } 
    @Override 
    public void onPageFinished(WebView view, String url) { 
     super.onPageFinished(view, url); 
     final String varMySheet = "var mySheet = document.styleSheets[0];"; 
     final String varCSSIndex = "var ruleIndex = mySheet.cssRules.length;"; 

     final float widthPage = view.getMeasuredWidth(); 
     final float heightPage = view.getMeasuredHeight(); 
     final float density_ = getResources().getDisplayMetrics().density; 
     final float gap = (int) (widthPage * .012f) * 2; 

     view.loadUrl("javascript:" + varMySheet); 
     view.loadUrl("javascript:" + varCSSIndex); 

     if (areThereTwoColumns) { 
      view.loadUrl("javascript:(function(){mySheet.insertRule('html { height: " + 
      heightPage/density_ + "px; -webkit-column-count: 2; -webkit-column-gap: " + 
      gap/density_ + "px;" + 
      " font-size: " + textSize + 
      "; }', ruleIndex)})()"); 
      } else { 
      view.loadUrl("javascript:(function(){mySheet.insertRule('html { height: " + 
      heightPage/density_ + 
      "px; -webkit-column-gap: 0px; -webkit-column-width: " + 
      widthPage/density_ + "px;" + " font-size: " + textSize + 
      "; }', ruleIndex)})()"); 
     } 
     } 
    }); 

Я дробить содержимое внутри vebview на куски шириной размером в WebView ('.getMeasuredWidth()'). Когда html-контент помещается в один столбец, он хорошо выглядит в любых эмуляторах для любой ориентации страницы. Однако, когда я размещаю html в двух столбцах, ширина результирующей страницы может немного отличаться от ширины WebView. Это происходит, когда плотность устройства не является целым числом.

перелистывание страниц в случае двух столбцов «myWebView.scrollTo ((ширина зазора myWebView +) * countPages, 0)» и бит за битом это отличается накоплением в то время как некоторое смещение становится показано, как артефакты из одной из сторон страницы. Это связано с тем, что ширина страницы отображения больше не совпадает с шириной WebView. Край соседней страницы не должен быть видимым, но он попадает в отображаемую область.

я взять, например, Nexus 7 имеет 1280x800pxs, 7 дюймов, tvdpi (Genymotion эмулятор): в ландшафтном режиме мой нагруженных в WebView веб-контента имеет длину, равную 360276px (возвращаемый 'computeHorizontalScrollRange()' из WebView) и отображение макета имеет ширину равную 1238px.

примечание: рх = (INT) (дп * плотность + .5f)

XML-макет:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    xmlns:tools="http://schemas.android.com/tools" 
    tools:context=".MainActivity" 
    android:background="@color/colorBackgroundView" 
    android:id="@+id/container"> 

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:tools="http://schemas.android.com/tools" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical" 
     android:layout_alignParentTop="true" 
     android:layout_marginLeft="16dp" 
     android:layout_marginTop="10dp" 
     android:layout_marginRight="16dp"> 

     <com.o....www.android.reader.MyWebView 
      android:id="@+id/webView" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:layout_weight="1" /> 

     <com.o....www.android.reader.PageCountShow 
      android:id="@+id/pager" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" /> 
    </LinearLayout> 

</RelativeLayout> 

Html-контент вернулся по 'document.body.scrollWidth' равно 270630px. Плотность 1,33. В этом устройстве ориентации все страницы показаны точно, хотя фракция 'вся длина webview/макета ширины webview' не является круглой.
При размещении в двух столбцах это выглядит намного хуже. Веб-контент WebView имеет длину равную 267453px, а html-контент имеет один равный 200904px (пропорция сохраняется), отображающая ширину webview составляет 1238px, а разрыв - 28px (расстояние прокрутки webview составляет 1266px).
В этом случае граница соседней страницы становится видимой, эта область увеличивается, когда я просматриваю страницы. Я попытался изменить размер html-содержимого, перезагрузив html-контент, добавив стиль свойства body-tag 'zoom', но он дает неожиданный результат: как следствие, может измениться размер шрифта дисплея, как если бы весь контент масштабировался , и желаемый размер страницы не может быть получен снова.

Есть ли способ точно разместить html-страницу в макете просмотра веб-страниц? Может быть, я должен разделить страницу в двух столбцах любым другим способом?

ответ

0

Css Specification определяет, что размеры элементов могут быть выражены в дробных числах, но кажется, что для webkit требуется только целое число.
Если WebView прокручивается на расстоянии, определенном ниже, страницы выглядят аккуратно.

if (areThereTwoColumns) { 
    view.loadUrl("javascript:(function(){mySheet.insertRule('html{ " + 
       "height: " + heightPage/density_ + "px;" + 
       " -webkit-column-width: "+ (widthPage - gap)/2/density_ + "px; " + 
       "-webkit-column-gap: " + gap/density_ + "px;" + 
       " font-size: " + textSize + ";}', ruleIndex)})()"); 
    // distance of scrolling: 
    scrollDistance = 2 * ((int)((widthPage - gap)/2/density_) * density_ + 
         (int)(gap/density_) * density_); 

} else { ...... } 


// myView.scrollTo((int)(scrollDistance * countPages), 0) etc 

Я не уверен, что найденное решение является лучшим, но это работает для меня. Буду признателен, если кто-то предложит что-то лучшее.


это хорошо работает только для SDK 16 (tvdpi):

areThereTwoColumns = areThereTwoColumns && getApplicationContext() 
     .getResources().getConfiguration() 
      .orientation == Configuration.ORIENTATION_LANDSCAPE; 
// ............omitted 
if (Build.VERSION.SDK_INT == 16 && getResources().getDisplayMetrics() 
           .densityDpi == DisplayMetrics.DENSITY_TV) 
    { 
     scrollDistance = 2 * ((int)((widthPage - gap)/2/density_ +.5f) * density_ + 
          (int)(gap/density_+.5f) * density_); 
    } 
// .............omitted 

, В других случаях необходимо использовать что-нибудь еще, потому что, даже в случае одного столбца, отображение страницы может искажаться (tvdpi!) пример:

int countGates = Math.round((float)myView.computeHorizontalScrollRange()/(widthPage + ((areThereTwoColumns)?gap:0))); 
scrollDistance = (float) lengthMyView/countGates; 
Смежные вопросы