You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用WebView点击_blank链接无法显示新WebView的问题求助

Android WebView点击target="_blank"链接创建的新WebView不显示内容(日志正常输出)

问题描述

我开发了一款加载adcpc.funwithpasswords.com站点的Android应用,需求是当点击网页中带有target="_blank"属性的链接(比如<a href="https://www.google.com" target="_blank">Go to Google</a>)时,创建一个新的小型WebView并加载目标站点。但实际操作时,Logcat能正常输出Opening URL: https://www.google.com/和Loaded URL: https://www.google.com/的日志,却看不到新WebView的任何内容。

原MainActivity.java代码

package com.flamenzaapps.adbits;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    WebView mainWebView;
    LinearLayout layout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize main WebView
        mainWebView = findViewById(R.id.webview);
        layout = findViewById(R.id.layout);

        // Enable JavaScript for main WebView
        WebSettings mainWebSettings = mainWebView.getSettings();
        mainWebSettings.setJavaScriptEnabled(true);
        mainWebView.setWebViewClient(new WebViewClient());
        mainWebView.loadUrl("https://www.adcpc.funwithpasswords.com");

        // Set up a WebViewClient with URL loading handler
        mainWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // When a link is clicked, open it in a new smaller WebView
                openNewWebView(url);
                return true;  // Prevent the default browser to open the link
            }
        });
    }

    // Function to create and display a new smaller WebView on the same page
    private void openNewWebView(String url) {
        // Log the URL for debugging
        Log.d("WebView", "Opening URL: " + url);

        // Create a new WebView
        WebView newWebView = new WebView(this);

        // Set up WebSettings for the new WebView
        WebSettings webSettings = newWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);  // Enable JavaScript
        newWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                Log.e("WebView", "Error loading URL: " + description);
            }
        });

        // Load the clicked URL in the new WebView
        newWebView.loadUrl(url);

        // Set layout parameters for the new WebView (make it smaller and position it)
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                600 // Fixed height for the smaller WebView
        );
        params.topMargin = 20;  // Optional: Add margin or positioning logic if needed
        newWebView.setLayoutParams(params);

        // Optionally set a background color for debugging visibility
        newWebView.setBackgroundColor(Color.parseColor("#000000"));

        // Ensure the parent layout is properly initialized
        LinearLayout layout = findViewById(R.id.layout);  // Make sure this ID is correct
        if (layout != null) {
            // Add the new WebView to the layout on the main UI thread
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    layout.addView(newWebView);
                    Log.d("WebView", "Loaded URL: " + url);
                }
            });
        } else {
            Log.e("WebView", "Layout not found. Make sure layout is initialized.");
        }
    }
}

解决方案

核心问题分析

WebView对带有target="_blank"的链接,默认会通过WebChromeClient的createWindow方法请求创建新窗口,而不是触发WebViewClient的shouldOverrideUrlLoading。原代码只处理了普通链接的跳转,没处理_blank链接的新窗口请求,导致逻辑不生效。另外还有布局和WebView配置的小问题需要优化。

修复步骤及代码

  1. 添加WebChromeClient处理_blank链接的新窗口请求
  2. 优化WebView配置,确保内容可见
  3. 避免重复查找布局控件

修复后的完整代码:

package com.flamenzaapps.adbits;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    WebView mainWebView;
    LinearLayout layout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize main WebView and layout
        mainWebView = findViewById(R.id.webview);
        layout = findViewById(R.id.layout);

        // Configure main WebView settings
        WebSettings mainWebSettings = mainWebView.getSettings();
        mainWebSettings.setJavaScriptEnabled(true);
        // 允许WebView支持多窗口(处理_blank链接)
        mainWebSettings.setSupportMultipleWindows(true);

        // 设置WebViewClient处理普通链接跳转
        mainWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                openNewWebView(url);
                return true;
            }
        });

        // 设置WebChromeClient处理_blank链接的新窗口请求
        mainWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, android.os.Message resultMsg) {
                // 创建新WebView并加载目标URL
                WebView newWebView = new WebView(MainActivity.this);
                // 配置新WebView的settings
                WebSettings webSettings = newWebView.getSettings();
                webSettings.setJavaScriptEnabled(true);
                webSettings.setSupportMultipleWindows(true);

                // 设置WebViewClient处理页面错误和跳转
                newWebView.setWebViewClient(new WebViewClient() {
                    @Override
                    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                        Log.e("WebView", "Error loading URL: " + description);
                    }

                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        view.loadUrl(url);
                        return true;
                    }
                });

                // 传递新WebView的结果消息
                WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
                transport.setWebView(newWebView);
                resultMsg.sendToTarget();

                // 将新WebView添加到布局
                openNewWebViewLayout(newWebView);
                return true;
            }
        });

        // 加载初始页面
        mainWebView.loadUrl("https://www.adcpc.funwithpasswords.com");
    }

    // 处理普通链接的新WebView创建
    private void openNewWebView(String url) {
        WebView newWebView = new WebView(this);
        WebSettings webSettings = newWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        newWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                Log.e("WebView", "Error loading URL: " + description);
            }
        });

        newWebView.loadUrl(url);
        openNewWebViewLayout(newWebView);
    }

    // 统一处理新WebView的布局添加
    private void openNewWebViewLayout(WebView webView) {
        Log.d("WebView", "Adding new WebView to layout");
        // 设置布局参数
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                600
        );
        params.topMargin = 20;
        webView.setLayoutParams(params);

        // 设置背景色确保可见(可根据需求调整)
        webView.setBackgroundColor(Color.parseColor("#FFFFFF"));
        // 开启硬件加速避免渲染问题
        webView.setLayerType(WebView.LAYER_TYPE_HARDWARE, null);

        // 添加到布局(已在主线程,无需额外调用runOnUiThread)
        if (layout != null) {
            layout.addView(webView);
            Log.d("WebView", "New WebView added successfully");
        } else {
            Log.e("WebView", "Layout reference is null");
        }
    }
}

关键修改说明

  • setSupportMultipleWindows(true):开启WebView的多窗口支持,这是处理_blank链接的前提
  • WebChromeClient.onCreateWindow:专门处理新窗口请求,创建并配置新WebView,同时传递结果消息给系统
  • 统一布局添加逻辑:把新WebView的布局配置和添加抽成单独方法,避免重复代码
  • 开启硬件加速:解决部分设备上WebView内容不渲染的问题
  • 移除重复的findViewById:直接使用成员变量layout,避免空指针风险

内容的提问来源于stack exchange,提问作者M.Riyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:58:11