Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在android中向具有webview的站点注入CSS_Android_Css_Webview_Webkit - Fatal编程技术网

在android中向具有webview的站点注入CSS

在android中向具有webview的站点注入CSS,android,css,webview,webkit,Android,Css,Webview,Webkit,例如,我想将www.google.com的背景色更改为红色。 我使用了webview,我的style.css文件位于assest文件夹中。我想将这个style.css文件注入www.google.com。我的代码怎么了?请给我写正确的代码。谢谢 我的maintactiviy.java文件: package com.example.mysina; import android.support.v7.app.ActionBarActivity; import android.os.Bundle;

例如,我想将
www.google.com
的背景色更改为
红色
。 我使用了
webview
,我的
style.css
文件位于
assest文件夹中。我想将这个
style.css
文件注入
www.google.com
。我的代码怎么了?请给我写正确的代码。谢谢 我的
maintactiviy.java
文件:

package com.example.mysina;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;

public class MainActivity extends ActionBarActivity {


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            WebView webView = new WebView(this);

            setContentView(webView);

                    String html = "<html><head><style> src: url('file:///android_asset/style.css')</style></head></html>";

                    webView.loadData(html, "text/html", "utf-8");
                    webView.loadUrl("https://www.google.com");
        }
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
package com.example.mysina;
导入android.support.v7.app.ActionBarActivity;
导入android.os.Bundle;
导入android.view.Menu;
导入android.view.MenuItem;
导入android.webkit.WebView;
公共类MainActivity扩展了ActionBarActivity{
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView WebView=新的WebView(此);
setContentView(网络视图);
String html=“src:url('file:///android_asset/style.css')";
加载数据(html、“文本/html”、“utf-8”);
webView.loadUrl(“https://www.google.com");
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.main,menu);
返回true;
}
@凌驾
公共布尔值onOptionsItemSelected(菜单项项){
//处理操作栏项目单击此处。操作栏将
//自动处理Home/Up按钮上的点击,只要
//在AndroidManifest.xml中指定父活动时。
int id=item.getItemId();
if(id==R.id.action\u设置){
返回true;
}
返回super.onOptionsItemSelected(项目);
}
}

您不能直接注入CSS,但可以使用Javascript操作页面dom

public class MainActivity extends ActionBarActivity {

  WebView webView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    webView = new WebView(this);
    setContentView(webView);

    // Enable Javascript
    webView.getSettings().setJavaScriptEnabled(true);

    // Add a WebViewClient
    webView.setWebViewClient(new WebViewClient() {

        @Override
        public void onPageFinished(WebView view, String url) {

            // Inject CSS when page is done loading
            injectCSS();
            super.onPageFinished(view, url);
        }
    });

    // Load a webpage
    webView.loadUrl("https://www.google.com");
}

// Inject CSS method: read style.css from assets folder
// Append stylesheet to document head
private void injectCSS() {
    try {
        InputStream inputStream = getAssets().open("style.css");
        byte[] buffer = new byte[inputStream.available()];
        inputStream.read(buffer);
        inputStream.close();
        String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
        webView.loadUrl("javascript:(function() {" +
                "var parent = document.getElementsByTagName('head').item(0);" +
                "var style = document.createElement('style');" +
                "style.type = 'text/css';" +
                // Tell the browser to BASE64-decode the string into your script !!!
                "style.innerHTML = window.atob('" + encoded + "');" +
                "parent.appendChild(style)" +
                "})()");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
  }
}
适用于Kotlin用户

导入这个

import android.util.Base64
这是onPageFinished代码

 override fun onPageFinished(view: WebView?, url: String?) {
                injectCSS()
}
这是要调用的代码

private fun injectCSS() {
            try {
                val inputStream = assets.open("style.css")
                val buffer = ByteArray(inputStream.available())
                inputStream.read(buffer)
                inputStream.close()
                val encoded = Base64.encodeToString(buffer , Base64.NO_WRAP)
                webframe.loadUrl(
                    "javascript:(function() {" +
                            "var parent = document.getElementsByTagName('head').item(0);" +
                            "var style = document.createElement('style');" +
                            "style.type = 'text/css';" +
                            // Tell the browser to BASE64-decode the string into your script !!!
                            "style.innerHTML = window.atob('" + encoded + "');" +
                            "parent.appendChild(style)" +
                            "})()"
                )
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }

实际上,您可以在API 11+上使用
WebViewClient.shouldInterceptRequest
。示例:

我能够通过使用API 19中添加到WebView的“evaluateJavascript”来注入css

科特林的例子:

private lateinit var webView: WebView

override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)

    //...

    webView = findViewById(R.id.your_webview_name)

    webView.settings.javaScriptEnabled = true

    webView.webViewClient = object : WebViewClient() {

        override fun onPageFinished(view: WebView, url: String) {

            val css = ".menu_height{height:35px;}.. etc..." //your css as String
            val js = "var style = document.createElement('style'); style.innerHTML = '$css'; document.head.appendChild(style);"
            webView.evaluateJavascript(js,null)
            super.onPageFinished(view, url)
        }
    }

    webView.loadUrl("https://mywepage.com") //webpage you want to load   
}
更新:上述代码在应用所有注入的CSS时出现问题。在咨询了我的web开发人员之后,我们决定将链接注入CSS文件,而不是CSS代码本身。我更改了css和js变量的值->

val css = "https://mywebsite.com/css/custom_app_styles.css"
val js = "var link = document.createElement('link'); link.setAttribute('href','$css'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type','text/css'); document.head.appendChild(link);"

下面是在Kotlin中使用Manish解决方案的代码片段,其中有一点UI/UX改进,以避免在注入css时webview闪烁/flash

步骤1:定义编码为Base64的css样式

    companion object {
    private const val injectCss = """
                        Your CSS Style Go HERE
                        """

    private val styleCss =
            """
            javascript:(function() {
                    var parent = document.getElementsByTagName('head').item(0);
                    var style = document.createElement('style');
                    style.type = 'text/css';
                    style.innerHTML = window.atob('${stringToBase64(hideHeaderCss)}');
                    parent.appendChild(style)
                    })()
            """

    private fun stringToBase64(input: String): String {
        val inputStream: InputStream = ByteArrayInputStream(input.toByteArray(StandardCharsets.UTF_8))
        val buffer = ByteArray(inputStream.available())
        inputStream.read(buffer)
        inputStream.close()

        return android.util.Base64.encodeToString(buffer, android.util.Base64.NO_WRAP)
    }
}
步骤2:webview初始化状态应不可见

    <WebView
        android:id="@+id/wv_content"
        android:visibility="invisible"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
步骤4:通过平滑过渡到显示webview来改进用户体验

fun View.smoothShow() {
    this.apply {
        alpha = 0f
        visibility = View.VISIBLE

        animate()
            .alpha(1f)
            .setDuration(300)
            .setListener(null)
    }
}

塔克斯。我已将这些代码复制到我的项目中。现在我可以更改页面的样式了。但有一个大问题。它无法加载页面。上面写着:网页不可用。它没有打开www.google.com。我应该更改哪些代码?这是我在这个主题上看到的最好的答案之一,但请注意,如果切换样式,会有一点页面跳转。在CSS注入完成之前不要显示内容是明智的。在webview中加载Url之前使用DOM操作。通过这样做,您可以在运行时注入任何脚本或javascript文件,然后将内容加载到webview中。我一直在我的ePub播放器中这样做,它工作起来很有魅力。@Vishal您介意在这里添加一个关于您所说内容的答案吗?为什么是base64部分?我正在做与您相同的事情。请告诉我你在android项目中添加css的位置,以及css文件包含哪些内容?我被卡住了。请帮忙。
fun View.smoothShow() {
    this.apply {
        alpha = 0f
        visibility = View.VISIBLE

        animate()
            .alpha(1f)
            .setDuration(300)
            .setListener(null)
    }
}