2010-09-03 4 views
57

Как я могу разделить содержимое файла HTML в размерах экрана размером «paginate» в браузере WebKit?HTML-подобная разбивка на страницы

Каждая «страница» должна показывать полный текст. Это означает, что строка текста не должна быть разрезана пополам в верхней или нижней границе экрана.

Редактировать

Этот вопрос изначально был помечен «Android», как мой намерениях построить читателя Android EPUB. Тем не менее, похоже, что решение может быть реализовано только с помощью JavaScript и CSS, поэтому я расширил сферу применения этого вопроса, чтобы сделать его независимым от платформы.

+0

«Как я могу разделить содержимое файла XHTML на экране? -раздельные куски, чтобы «разбивать страницы» на книгу ». - Зачем это? – CommonsWare

+6

Потому что это книжный и широко используемый способ (то есть: Aldiko), чтобы представить текст, а также это интересная проблема. :) – hpique

+0

Привет, какой из нижеперечисленных решений сработал для вас. Теперь я столкнулся с такой же проблемой, как и вы - :( – DroidBot

ответ

30

Основываясь на ответе Дэна, это мое решение этой проблемы, с которой я боролся до сих пор. (Это JS работает на IOS Webkit, никаких гарантий для андроида, но, пожалуйста, дайте мне знать результаты)

var desiredHeight; 
var desiredWidth; 
var bodyID = document.getElementsByTagName('body')[0]; 
totalHeight = bodyID.offsetHeight; 
pageCount = Math.floor(totalHeight/desiredHeight) + 1; 
bodyID.style.padding = 10; //(optional) prevents clipped letters around the edges 
bodyID.style.width = desiredWidth * pageCount; 
bodyID.style.height = desiredHeight; 
bodyID.style.WebkitColumnCount = pageCount; 

Надеется, что это помогает ...

+6

Не могли бы вы посоветовать мне, как реализовать это в веб-обзоре, или вы можете опубликовать весь код для этого? Спасибо заранее. –

0

Вы можете разделить страницы в отдельных файлах XHTML и сохранить их в папке. Например: page01, page02. Затем вы можете отображать эти страницы один за другим под друг другом.

+0

И как я могу узнать, где разделить на основе размера экрана и шрифта? – hpique

21

Говоря по опыту, надейтесь на это потратить много времени, даже для бобовых зрителей. Чтение ePub было на самом деле первым крупным проектом, который я получил, когда начал изучать C#, но стандарт ePub определенно довольно сложный.

Вы можете найти последнюю версию спецификации для EPUB здесь: http://www.idpf.org/specs.htm , который включает в себя OPS (Open Publication Structure), ОБТК (Open формат упаковки) и (Формат OEBPS Container) OCF.

Кроме того, если это поможет вам на всех, вот ссылка на # исходный код C проекта я начал:

https://www.dropbox.com/sh/50kxcr29831t854/MDITIklW3I/ePub%20Test.zip

Это не конкретизированы вообще; Я не играл с этим в течение нескольких месяцев, но если я правильно помню, просто вставьте ePub в каталог отладки, и когда вы запустите программу, просто введите некоторую часть имени (например, «Под куполом» просто введите «купол») и он отобразит детали книги.

У меня было это правильно для нескольких книг, но любые электронные книги из Google Books полностью нарушили его. У них совершенно странная реализация ePub (по крайней мере, для меня) по сравнению с книгами из других источников.

В любом случае, надеюсь, что некоторые структурные коды могут помочь вам!

+0

+1 для обмена опытом и кодом. – hpique

12

Недавно я попытался что-то похожее на это и добавил стили CSS, чтобы изменить макет на горизонтальный, а не вертикальный. Это дало мне желаемый эффект без какого-либо изменения содержания Epub.

Этот код должен Работа.

mWebView.setWebViewClient(new WebViewClient() { 
    public void onPageFinished(WebView view, String url) { 

     // Column Count is just the number of 'screens' of text. Add one for partial 'screens' 
     int columnCount = Math.floor(view.getHeight()/view.getWidth())+1; 

     // Must be expressed as a percentage. If not set then the WebView will not stretch to give the desired effect. 
     int columnWidth = columnCount * 100; 

     String js = "var d = document.getElementsByTagName('body')[0];" + 
      "d.style.WebkitColumnCount=" + columnCount + ";" + 
      "d.style.WebkitColumnWidth='" + columnWidth + "%';"; 
     mWebView.loadUrl("javascript:(function(){" + js + "})()"); 
    } 
}); 

mWebView.loadUrl("file:///android_asset/chapter.xml"); 

Таким образом, в основном вы инъекционные JavaScript, чтобы изменить стиль элемента тела после того, как был загружен глава (очень важно). Единственное падение к этому подходу - когда у вас есть изображения в контенте, подсчитанное количество столбцов идет косо. Это не должно быть слишком сложно исправить. Моя попытка заключалась в том, чтобы вводить некоторый JavaScript для добавления атрибутов ширины и высоты ко всем изображениям в DOM, которые их не имеют.

Надеюсь, это поможет.

Дан

+1

+1 Не могу заставить это работать, но я думаю, что он указал мне в правильном направлении. – hpique

+1

@Dan Где я должен добавить этот код? – Atihska

+0

@ Dan вы можете поделиться мне с вашим css стиль Pagination работает для меня, но для этого нужен css. Пожалуйста, напишите свой css. Спасибо заранее. –

4

Может быть, это будет работать, чтобы использовать XSL-FO.Это кажется тяжелым для мобильного устройства, и, может быть, оно слишком велико, но оно должно работать, и вам не нужно будет реализовывать сложности хорошей разбивки на страницы (например, как вы убедитесь, что каждый экран не вырезает текст пополам) самостоятельно ,

Основная идея будет:

  • преобразования XHTML (и другие вещи EPUB) в XSL-FO с использованием XSLT.
  • использовать процессор XSL-FO для визуализации XSL-FO в страничном формат, который можно отобразить на мобильном устройстве, такие как PDF (вы можете отобразить, что?)

Я не знаю, для Android есть процессор XSL-FO. Вы можете попробовать Apache FOP. RenderX (процессор XSL-FO) имеет то преимущество, что имеет paged-HTML output option, но опять же я не знаю, может ли он работать на Android.

1

Существует несколько способов сделать это. Если каждая строка находится в своем собственном элементе, все, что вам нужно сделать, это проверить, выходит ли один из его ребер за пределы представления (либо в браузерах, либо на странице книги).

Если вы хотите знать, сколько «страниц» будет сделано заранее, просто временно переместите их в представление и получите строку, на которой заканчивается страница. Это потенциально может быть медленным из-за того, что обновление страницы необходимо для того, чтобы браузер знал, где что угодно.

В противном случае, я думаю, что вы можете использовать элемент холста HTML5 для измерения текста и/или рисования текста.

Некоторая информация о том, что здесь: https://developer.mozilla.org/en/Drawing_text_using_a_canvas http://uupaa-js-spinoff.googlecode.com/svn/trunk/uupaa-excanvas.js/demo/8_2_canvas_measureText.html

18

Я должен был закодировать что-то вроде этого тоже, и моя (работа) решение заключается в следующем:

Вы должны применять эти строки в webview ...

webView_.getSettings().setUseWideViewPort(true); 
    webView_.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS); 

Кроме того, вам необходимо ввести некоторый javascript. У меня было много проблем с разной шкалой моей деятельности и содержанием, представленным в веб-просмотре, поэтому мое решение не берет никакой ценности от «снаружи».

webView_.setWebViewClient(new WebViewClient(){ 

      public void onPageFinished(WebView view, String url) { 
       injectJavascript(); 
      } 

     }); 

[...]

public void injectJavascript() { 
     String js = "javascript:function initialize() { " + 
       "var d = document.getElementsByTagName('body')[0];" + 
       "var ourH = window.innerHeight; " + 
       "var ourW = window.innerWidth; " + 
       "var fullH = d.offsetHeight; " + 
       "var pageCount = Math.floor(fullH/ourH)+1;" + 
       "var currentPage = 0; " + 
       "var newW = pageCount*ourW; " + 
       "d.style.height = ourH+'px';" + 
       "d.style.width = newW+'px';" + 
       "d.style.webkitColumnGap = '2px'; " + 
       "d.style.margin = 0; " + 
       "d.style.webkitColumnCount = pageCount;" + 
       "}"; 
     webView_.loadUrl(js); 
     webView_.loadUrl("javascript:initialize()"); 
    } 

Наслаждайтесь :)

+0

Это работает. Как я могу перейти к следующему столбцу при нажатии кнопки? – Midhun

+0

@Midhun, '$ (" body "). Animate ({scrollLeft: window.innerWidth * });' – Jmorvan

+0

как использовать этот код для разбивки страницы на прокрутку? –

1

Если бы эта же проблема недавно, и вдохновленный ответы нашел обычный CSS решение, используя столбцам * атрибуты CSS3 в:

/* CSS */ 
.chapter { 
    width: 600px; 
    padding: 60px 10px; 
    -webkit-column-gap: 40px; 
    -webkit-column-width: 150px; 
    -webkit-column-count: 2; 
    height:400px; 
} 

/* HTML */ 
<div class="chapter"> 
    your long lorem ipsum arbitrary HTML 
</div> 

В примере выше, дает отличные результаты на сетчатке iPhone. Игра с различными атрибутами дает разные интервалы между страницами и т. Д.

Если вам необходимо поддерживать несколько разделы, например, которые необходимо начать на новых страницах, есть XCode 5 примеров на GitHub: https://github.com/dmrschmidt/ios_uiwebview_pagination

1

я был в состоянии улучшить Nacho's решения, чтобы получить горизонтальный красть пейджинг эффект с WebView. Вы можете найти решение here и пример code.

Edit:

код решения.

MainActivity.java

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
     WebView.setWebContentsDebuggingEnabled(true); 
    } 
    wv = (HorizontalWebView) findViewById(R.id.web_view); 
    wv.getSettings().setJavaScriptEnabled(true); 
    wv.setWebViewClient(new WebViewClient() { 

     public void onPageFinished(WebView view, String url) { 
      injectJavascript(); 
     } 
    }); 

    wv.setWebChromeClient(new WebChromeClient() { 
     @Override 
     public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 
      int pageCount = Integer.parseInt(message); 
      wv.setPageCount(pageCount); 
      result.confirm(); 
      return true; 
     } 
    }); 
    wv.loadUrl("file:///android_asset/ch03.html"); // now it will not fail here 
} 

private void injectJavascript() { 
    String js = "function initialize(){\n" + 
      " var d = document.getElementsByTagName('body')[0];\n" + 
      " var ourH = window.innerHeight;\n" + 
      " var ourW = window.innerWidth;\n" + 
      " var fullH = d.offsetHeight;\n" + 
      " var pageCount = Math.floor(fullH/ourH)+1;\n" + 
      " var currentPage = 0;\n" + 
      " var newW = pageCount*ourW;\n" + 
      " d.style.height = ourH+'px';\n" + 
      " d.style.width = newW+'px';\n" + 
      " d.style.margin = 0;\n" + 
      " d.style.webkitColumnCount = pageCount;\n" + 
      " return pageCount;\n" + 
      "}"; 
    wv.loadUrl("javascript:" + js); 
    wv.loadUrl("javascript:alert(initialize())"); 
} 

В onJsAlert моей WebChromeClient в получить число горизонтальных страниц, которые я прохожу к пользовательскому HorizontalWebView реализовать эффект подкачки

HorizontalWebView.java

public class HorizontalWebView extends WebView { 
    private float x1 = -1; 
    private int pageCount = 0; 

    public HorizontalWebView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       x1 = event.getX(); 
       break; 
      case MotionEvent.ACTION_UP: 
       float x2 = event.getX(); 
       float deltaX = x2 - x1; 
       if (Math.abs(deltaX) > 100) { 
        // Left to Right swipe action 
        if (x2 > x1) { 
         turnPageLeft(); 
         return true; 
        } 

        // Right to left swipe action 
        else { 
         turnPageRight(); 
         return true; 
        } 

       } 
       break; 
     } 
     return true; 
    } 

    private int current_x = 0; 

    private void turnPageLeft() { 
     if (getCurrentPage() > 0) { 
      int scrollX = getPrevPagePosition(); 
      loadAnimation(scrollX); 
      current_x = scrollX; 
      scrollTo(scrollX, 0); 
     } 
    } 

    private int getPrevPagePosition() { 
     int prevPage = getCurrentPage() - 1; 
     return (int) Math.ceil(prevPage * this.getMeasuredWidth()); 
    } 

    private void turnPageRight() { 
     if (getCurrentPage() < pageCount - 1) { 
      int scrollX = getNextPagePosition(); 
      loadAnimation(scrollX); 
      current_x = scrollX; 
      scrollTo(scrollX, 0); 
     } 
    } 

    private void loadAnimation(int scrollX) { 
     ObjectAnimator anim = ObjectAnimator.ofInt(this, "scrollX", 
       current_x, scrollX); 
     anim.setDuration(500); 
     anim.setInterpolator(new LinearInterpolator()); 
     anim.start(); 
    } 

    private int getNextPagePosition() { 
     int nextPage = getCurrentPage() + 1; 
     return (int) Math.ceil(nextPage * this.getMeasuredWidth()); 
    } 

    public int getCurrentPage() { 
     return (int) (Math.ceil((double) getScrollX()/this.getMeasuredWidth())); 
    } 

    public void setPageCount(int pageCount) { 
     this.pageCount = pageCount; 
    } 
} 
Смежные вопросы