css クラスを変更しても、常に変更が反映されるとは限りません。これは、ダウン クラス名のようなものをボタンに追加するタッチ イベントがある場合に発生するようです。ボタンは更新されず、ページの他の操作も行われません。いつ機能するかは非常に不安定です。また、要素が白く表示され、コンテンツも何も表示されない場合があることにも気付きました。これは非常にイライラします!
9 に答える
注:
Android 4.4 以降では、より良い解決策があります。CrossWalkWebView
と呼ばれるドロップイン代替品です。最新の Chromium キットを使用しており、素晴らしいです。ここでそれについて読むことができます: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 があることを確認してください。API 15 を使用しているため、これが私のマニフェストの内容です。
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
(更新: でその値を変更する必要がありますbuild.gradle
)
ここで、WebView に表示される内容のプライマリ CSS ファイルに、次のようなものを追加します。
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);
}
最後から 2 番目ですが、重要な点: クラスのソース コードを読んでいて、WebView
強制再描画に関する小さなコメントを見つけました。がstatic final boolean
設定されているtrue
と、ビューが常に再描画されます。私は Java 構文に詳しくありませんが、クラスの static final 属性を直接変更できるとは思いません。だから私がやったことは、クラスを次のように拡張することでした:
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
。これにより、ビューが絶えず再描画されます。ただし、必要な場合にのみ再描画するロジックを追加することを強くお勧めします。
Cordova を使用している場合は、最後の手順が 1 つあります。WebView
独自のクラスの代わりに新しいクラスを使用するように PhoneGap に指示する必要がありますWebView
。MainActivity
クラスで、これを追加します。
public void init(){
CordovaWebView webView = new MyWebView(MainActivity.this);
super.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
それでおしまい!アプリを試して実行し、すべてがスムーズになるかどうかを確認してください。これらの変更をすべて行う前は、ページが白く表示され、CSS の変更が適用されず、画面をもう一度タップすると、アニメーションが非常に途切れたり、目立たなくなったりしました。アニメーションはまだ途切れ途切れですが、以前よりはるかに途切れが少なくなったことに言及する必要があります。
これに追加するものがある場合は、下にコメントしてください。私は常に最適化を受け入れています。そして、私が今推奨したことを行うためのより良い方法があるかもしれないことを十分に認識しています.
上記の解決策がうまくいかなかった場合は、具体的な状況と、Android でどのような結果が得られたかを説明していただけWebView
ますか?
最後に、この回答を「コミュニティ ウィキ」として有効にしたので、誰でも自由に調整できます。
ありがとう!
編集:
最新の PhoneGap では、init() メソッドを次のようにする必要があります。
public void init(){
CordovaWebView webView = new MyWebView(MainActivity.this);
super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
私にとって、この問題は Samsung デバイスでのみ発生していました。WebView のハードウェア アクセラレーションを無効にすることで修正できました。
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
それが役に立てば幸い。
上記および他の場所で指摘されているように、オーバーライド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's 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()
たが、うまくいかないようです。私のソリューションはシンプルであるほうが良いかもしれませんが、私にとってはうまくいきます(Twitterのログインを表示しているだけです)
マニフェストを変更して、ハードウェアを有効にする必要があります。
<application
...
android:hardwareAccelerated="true">
そしてあなたの活動で onResume()
webView.postDelayed(() -> {
if (!isFinishing() && webView != null) {
webView.setLayerType(View.LAYER_TYPE_NONE, null);
}
}, 1000);
そしてあなたの onPause() で
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
WebView fails to render until touched Android 4.2.2での私の回答も参照してください。アイデアは、@ Olivier の関数を JavaScript にエクスポートして、JS からの無効化を適切な部分でトリガーできるようにすることです...私の神、さらに別のハック !! :)