Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/183.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 OnKeyDown内部WebView片段_Android_Android Fragments_Webview - Fatal编程技术网

Android OnKeyDown内部WebView片段

Android OnKeyDown内部WebView片段,android,android-fragments,webview,Android,Android Fragments,Webview,我制作了一个片段,其中包含一个WebView,我想定义一个onKeyDown(),从一个网页返回到上一个网页。我这样做了,但对我来说最奇怪的是从我的Fragment类到我的Activity类共享一个WebView变量,因为我无法在Fragment中定义onKeyDown()。所以我定义了一个get方法,并将其设置为静态。但我想知道这是否真的是一个错误,我的应用程序在某些情况下可能会严重崩溃 我的片段代码: public class BrowserFragment extends Fragment

我制作了一个
片段
,其中包含一个
WebView
,我想定义一个
onKeyDown()
,从一个网页返回到上一个网页。我这样做了,但对我来说最奇怪的是从我的
Fragment
类到我的
Activity
类共享一个
WebView
变量,因为我无法在
Fragment
中定义
onKeyDown()
。所以我定义了一个get方法,并将其设置为静态。但我想知道这是否真的是一个错误,我的应用程序在某些情况下可能会严重崩溃

我的
片段
代码:

public class BrowserFragment extends Fragment {
    private static WebView webView;

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

    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.fragment_activity, parent, false);

        getActivity().setTitle(R.string.title_rus);

        webView = (WebView) v.findViewById(R.id.webView);
        webView.setWebViewClient(new SwingBrowserClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        Uri data = Uri.parse("http://www.swinginmoscow.ru/m/");
        webView.loadUrl(data.toString());

        return v;
    }

    public static WebView getWebView() {
        return webView;
    }
}
public class MainBrowserActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new BrowserFragment();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && BrowserFragment.getWebView().canGoBack()) {
            BrowserFragment.getWebView().goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}
和我的
活动
代码:

public class BrowserFragment extends Fragment {
    private static WebView webView;

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

    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.fragment_activity, parent, false);

        getActivity().setTitle(R.string.title_rus);

        webView = (WebView) v.findViewById(R.id.webView);
        webView.setWebViewClient(new SwingBrowserClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        Uri data = Uri.parse("http://www.swinginmoscow.ru/m/");
        webView.loadUrl(data.toString());

        return v;
    }

    public static WebView getWebView() {
        return webView;
    }
}
public class MainBrowserActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new BrowserFragment();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && BrowserFragment.getWebView().canGoBack()) {
            BrowserFragment.getWebView().goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

这可能行得通,但不是个好主意。如果您没有正确处理
片段
,或者代码中的某个地方对其生命周期有点粗心,那么它很可能会导致崩溃。但是有一个简单的方法可以解决这个问题。不要使用静态方法,而是保存实例并对实例本身调用方法。通过这种方式,您可以检查实例是否为null,如果不是,则
片段可以处理对
goBack()
canGoBack()本身的调用:

public class MainBrowserActivity extends SingleFragmentActivity {

    BrowserFragment browserFragment = null;

    @Override
    protected Fragment createFragment() {
        this.browserFragment = BrowserFragment.newInstance();
        return this.browserFragment;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && this.browserFragment != null && this.browserFragment.canGoBack()) {
            this.browserFragment.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}
如您所见,
BrowserFragment
实例被保存,然后在
BrowserFragment
本身上调用
goBack()
canGoBack()
等方法。当然,您必须在
BrowserFragment
中实现这些方法,但这应该不是问题:

public class BrowserFragment extends Fragment {

    public static BrowserFragment newInstance() {
        BrowserFragment fragment = new BrowserFragment();
        return fragment;
    }

    private WebView webView;

    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.fragment_activity, parent, false);

        getActivity().setTitle(R.string.title_rus);

        webView = (WebView) v.findViewById(R.id.webView);
        webView.setWebViewClient(new SwingBrowserClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        Uri data = Uri.parse("http://www.swinginmoscow.ru/m/");
        webView.loadUrl(data.toString());
        return v;
    }

    public boolean canGoBack() {
        return this.webView != null && this.webView.canGoBack();
    }

    public void goBack() {
        if(this.webView != null) {
            this.webView.goBack();  
        }  
    }
}
我对你的代码做了一些额外的改进。首先,我添加了空检查以防止任何可能的
NullPointerException
,其次,建议始终使用静态工厂方法来创建
片段的新实例。这就是我添加到
BrowserFragment
的静态
newInstance()
方法。这样做的好处是,您可以实现一种方法,该方法负责为您设置
BrowserFragment
,而不管您在哪里使用它。您可以向
newInstance()
方法添加参数,以将一些值传递给
BrowserFragment
或添加一些必需的侦听器等,但由于您没有将任何值传递给
BrowserFragment
方法,因此
newInstance()
方法仍然是空的。尽管如此,最好始终使用此类工厂方法,即使它们只调用
newbrowserfragment()

一般来说,这种方法要好得多。尤其是从体系结构的角度来看,因为您不直接与
活动中的
WebView
交互。
WebView
Activity
无关,它是
BrowserFragment
实现的一部分,因此
Activity
不应该知道甚至存在
WebView
。对
goBack()
canGoBack()
的调用是如何实现的,或者它们到底做了什么,这与
活动
无关。
Activity
只告诉
BrowserFragment
“我想回去”,而
BrowserFragment
完成了这项工作。这将更好地分离责任,并使代码更可读、更清晰和更易于维护

编辑:

我也不知道有什么
SingleFragmentActivity
,但通常任何
活动都会实现
onBackPressed()
方法。您不必重写
onKeyDown()
来捕获回键事件。你可以这样做:

@Override
public void onBackPressed() {
    if (this.browserFragment != null && this.browserFragment.canGoBack()) {
        this.browserFragment.goBack();
    } else {  
        // The back key event only counts if we execute super.onBackPressed();
        super.onBackPressed();
    }
}

如果您有任何其他问题,请随时提问

哦!!非常感谢您的辛勤工作和解释!这正是我想要实现的,但不知道如何实现(尤其是如何使片段将工作作为一项活动)。我的SIngleFragment活动只包含创建片段、开始事务和添加到容器的代码。非常感谢。现在我将仔细考虑一下您的整个实现=),顺便说一句,您可能知道,我在片段中添加了WebView,这样活动生命周期就不会影响页面表示。例如,我从纵向模式改为横向模式,我不希望我的应用程序再次下载起始页。我应该在saveInstanceState中保存一些东西,但是我应该保存什么呢?谢谢,+1提供了清晰的代码和很好的解释。这对我来说非常有效!我只有一个问题,当我在安卓系统中有一个菜单打开我的网络视图中的链接时,我该如何处理?当我点击webview内的链接时效果很好,但当我点击菜单“配置文件”,然后点击另一个菜单并按back时,它就不起作用了。。。你知道我该怎么修吗?:)