Подтвердить что ты не робот

Android WebView отображает пустой/белый, просмотр не обновляется при изменениях css или изменениях в HTML, анимация изменчивая

Когда я делаю изменение класса css, изменения не всегда появляются. Это происходит, когда у меня есть событие касания, которое добавляет что-то вроде имени вниз для кнопки к кнопке. Кнопка не обновляется, и на странице ничего не происходит. Это очень непостоянно, когда оно работает. Я также заметил, что иногда мои элементы кажутся белыми без содержания или чего-то еще. Это очень расстраивает!

4b9b3361

Ответ 1

Я реализовал решение kyle и решил проблему. Howwer я заметил огромный утечка батареи на android 4.0.4, когда приложение было открыто. Также после изменения у меня были пользователи, жалующиеся на то, что клавиатура swiftKey больше не работает с моим приложением.

Каждое изменение в моем приложении запускается с помощью действия пользователя, поэтому я придумал модифицированную версию, которая вызывает только invalidate() после touchEvent:

    Handler handler = new Handler();
    public boolean onTouchEvent (MotionEvent event){
        super.onTouchEvent(event);
        handler.postDelayed(triggerInvalidate, 60);
            handler.postDelayed(triggerInvalidate, 300);
        return true;
    }

    private Runnable triggerInvalidate=new Runnable(){
        public void run(){
            invalidate();
        }
    };

Никогда не программировалось с Java, поэтому могло бы быть лучшее решение для этого.

Ответ 2

Примечание:
Там есть лучшее решение для Android 4.4+. Это замена WebView, называемая CrossWalk. Он использует новейший Chromium-kit, и это фантастика. Вы можете прочитать об этом здесь: crosswalk-project.org

Кроме того, похоже, что с Android 4.4 решение invalidate() больше не требуется, и вы можете избежать некоторых других безопасных ответов. Я бы использовал этот подход invalidate() как последнее усилие.


Я отвечаю на свой вопрос, чтобы надеяться помочь людям с теми же проблемами, что и я.

Я пробовал несколько способов сделать вещи лучше, даже все пресловутые - webkit-transform: translate3d(0,0,0); Даже это не сработало слишком хорошо.

Позвольте мне поделиться с вами тем, что работало.

Сначала используйте новейший API. Я использую API 15. В вашем AndroidManifest.xml обязательно включите аппаратное ускорение. Если ваша версия API не поддерживает это, переходите к следующему бит.

Если ваша версия поддерживает его, вы можете включить его, изменив ваш манифест:

<application
   ...
   android:hardwareAccelerated="true">

Кроме того, убедитесь, что ваш манифест имеет минимально поддерживаемый API для того, который вы используете. Поскольку я использую API 15, это то, что имеет мой манифест:

<uses-sdk
    android:minSdkVersion="15"
    android:targetSdkVersion="15" />

( Обновить: теперь вы должны изменить эти значения в build.gradle)

Теперь, в вашем основном файле CSS для того, что будет представлено в WebView, добавьте что-то вроде этого:

body div {
    -webkit-transform: translate3d(0,0,0);
}

Добавьте бит body div с любыми другими типами элементов, которые у вас есть; вы можете, вероятно, исключить изображения, ul, li и т.д. Причина применения этого стиля CSS ко всему - это просто пробная версия и ошибка, и я обнаружил, что грубое применение этого ко всему кажется лучшим. С большим деревом DOM вам может понадобиться быть более конкретным. Я не уверен, что спецификация будет, однако.

Когда вы создаете экземпляр WebView, есть некоторые настройки, которые вы хотите установить:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");
    appView.getSettings().setRenderPriority(RenderPriority.HIGH);
    appView.getSettings()
            .setPluginState(WebSettings.PluginState.ON_DEMAND);
}

Второй и последний, но решающий бит: я читал исходный код для класса WebView и нашел этот маленький крошечный комментарий о перерисовке силы. Существует static final boolean, который при установке true заставит просмотр всегда перерисовывать. Я не большой синтаксис Java, но я не думаю, что вы можете напрямую изменить статический конечный атрибут класса. Так что я закончил делать это, я расширил класс следующим образом:

import org.apache.cordova.CordovaWebView;

import android.content.Context;
import android.graphics.Canvas;

public class MyWebView extends CordovaWebView {
    public static final String TAG = "MyWebView";

    public MyWebView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // Warning! This will cause the WebView to continuously be redrawn
        // and will drain the devices battery while the view is displayed!
        invalidate();
    }

}

Имейте в виду, я использую Cordova/PhoneGap, поэтому мне пришлось перейти от CordovaWebView. Если вы видите в методе onDraw, есть вызов invalidate. Это заставит просмотр постоянно перерисовываться. Я настоятельно рекомендую добавлять логику только для перерисовки, когда вам это нужно.

Есть один последний шаг, если вы используете Кордову. Вы должны сказать PhoneGap, чтобы использовать ваш новый класс WebView вместо своего собственного класса WebView. В вашем классе MainActivity добавьте следующее:

public void init(){
    CordovaWebView webView = new MyWebView(MainActivity.this);
    super.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}

Что это! Попробуйте запустить приложение и посмотрите, все ли намного более гладко. Прежде чем делать все эти изменения, страницы выглядели бы белыми, никаких изменений CSS не было бы применено до тех пор, пока после повторного нажатия на экран анимации не были бы чересчурными или даже не заметными. Я должен упомянуть, что анимация по-прежнему изменчивая, но гораздо менее прерывистая, чем раньше.

Если кому-то есть что добавить, просто прокомментируйте это. Я всегда открыт для оптимизации; и я полностью понимаю, что могут быть лучшие способы делать то, что я только что рекомендовал.

Если мое выше решение не сработало для вас, не могли бы вы описать свою конкретную ситуацию и какие результаты вы видите с андроидами WebView?

Наконец, я включил этот ответ в качестве "вики сообщества", поэтому всем и всем, не стесняйтесь вносить коррективы.

Спасибо!


Edit:

С самым последним PhoneGap вам понадобится, чтобы ваш метод init() выглядел следующим образом:

public void init(){
    CordovaWebView webView = new MyWebView(MainActivity.this);
    super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}

Ответ 3

re: проблема с перерисованием, вы можете принудительно выполнить перерисовку, прочитав свойство из элемента

так скажите, что вы это делаете:

$('#myElement').addClass('foo'); // youre not seeing this take effect

если вы сделаете это позже:

$('#myElement').width();

он заставит перерисовать.

Таким образом, вы можете быть выборочным, а не перерисовывать всю страницу все время, что дорого

Ответ 4

Для меня эта проблема произошла только на устройствах Samsung. Я смог исправить это, отключив аппаратное ускорение для WebViews:

webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

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

Ответ 5

Как указано выше и в другом месте - переопределение View.onDraw() и вызов View.invalidate приведет к снижению производительности батареи/приложения. Вы также можете выполнить ручной вызов invalidate когда-либо x ms как это

/**
 * Due to bug in 4.2.2 sometimes the webView will not draw its contents after the data has loaded. 
 * Triggers redraw. Does not work in webView onPageFinished callback for some reason
 */
private void forceWebViewRedraw()
{
    mWebView.post(new Runnable() {
        @Override
        public void run()
        {
            mWebView.invalidate();
            if(!isFinishing())
                mWebView.postDelayed(this, 1000);
        }
    });
}

Я попробовал поставить недействительный вызов в WebViewClient.onPageLoaded(), но это, похоже, не работает. Хотя мое решение может быть лучше его простым, и оно работает для меня (im, просто показывающий вход в twitter)

Ответ 7

У меня была эта проблема, потому что onPageStared и onPageFinished Я показываю и скрываю анимацию загрузки.

Так как я вводил JS, делаю мои меню и прочее с исходного сайта, и заметил, что инъекция JS on onPageFinished заставляет веб-просмотр рисовать содержимое. Вот пример того, что вы можете добавить в конце onPageFinished

view.loadUrl("javascript:(function() { var select = document.getElementsByClassName('something')[0]\r\n" + 
                            "                     if(select)" +
                            "                       select.style.display = 'none';})()");

Ответ 8

Просто очистите кеш webView в oncreate(), и он работает для меня.

webView.clearCache(true);