Я пробовал решение sirFunkenstine, которое прекрасно работает.Только клиенту, для которого я создаю это приложение, не понравилось исполнение.И я должен был признать, что это было не так гладко.
Казалось, что добавление и удаление предварительно загруженных WebViews, где проблема.Пользовательский интерфейс зависал на долю секунды каждый раз, когда приложение добавляло / удаляло новый WebView для следующей строки.
Решение
Поэтому я подумал, что будет лучшенастраивайте только содержимое и высоту WebView вместо добавления / удаления.Таким образом, у нас есть только количество веб-представлений, которые в данный момент видны в памяти.И мы можем использовать функцию повторного использования ListView / Adapter.
Поэтому я добавил один WebView за ListView, который постоянно вычисляет высоту WebView следующих элементов.Вы можете получить высоту с помощью метода WebView getContentHeight.Вам нужно будет сделать это в методе onPageFinished, чтобы получить окончательную высоту.Это подняло еще одну проблему, потому что метод возвращает ноль, когда содержимое загружается методами loadDataWithBaseURL или loadData.Кажется, что значение устанавливается в конце концов, но еще не во время вызова onPageFinished.Чтобы преодолеть это, вы можете добавить поток, который постоянно проверяет, является ли getContentHeight больше не равным нулю.Если оно не равно нулю, тогда значение установлено, и вы можете загрузить следующее.
Это решение выглядит несколько странно, но оно дало мне приятный и плавный ListView, включая WebViews с разной высотой.
Пример кода:
1: поставить в очередь позиции строк, которые вы хотите предварительно загрузить:
private SparseArray<Integer> mWebViewHeights = new SparseArray<Integer>();
private LinkedBlockingQueue mQueue;
{
mQueue = new LinkedBlockingQueue();
try {
mQueue.put(position);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2: запустить Runnableчтобы постоянно загружать новые элементы из очереди и проверять / добавлять высоту в массив:
Handler h;
Runnable rowHeightCalculator = new Runnable() {
h = new Handler();
rowHeightCalculator.run();
}
3: загрузить новое содержимое HTML и проверить высоту:
Handler h;
Runnable rowHeightCalculator = new Runnable() {
int mCurrentIndex = -1;
boolean mLoading = false;
// Read the webview height this way, cause oncomplete only returns 0 for local HTML data
@Override
public void run() {
if(Thread.interrupted())
return;
if (mCurrentIndex == -1 && mQueue.size() > 0) {
try {
mCurrentIndex = (Integer)mQueue.take();
String html = mItems.get(mCurrentIndex).getPart().getText();
mDummyWebView.clearView();
mDummyWebView.loadDataWithBaseURL("file:///android_asset/reader/", "THE HTML HERE", "text/html", "UTF-8", null);
mLoading = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(mDummyWebView.getContentHeight() != 0 && mCurrentIndex >= 0) {
int contentHeight = mDummyWebView.getContentHeight();
mWebViewHeights.append(mCurrentIndex, contentHeight);
mCurrentIndex = -1;
mLoading = false;
}
// Reload view if we loaded 20 items
if ((mQueue.size() == 0 && (mItemsCount - mQueue.size()) < 20) || (mItemsCount - mQueue.size()) == 20) {
notifyDataSetChanged();
}
if (mQueue.size() > 0 || mLoading) {
h.postDelayed(this, 1);
}
}
};