WebViewFragment webView имеет значение null после выполнения FragmentTransaction
в настоящее время у меня есть мое приложение с ListFragment
слева и a DetailsFragment
справа (аналогично макету на планшете ниже).
на фрагменте деталей (фрагмент рядом со списком) у меня есть кнопка сделки goto, которая при нажатии должна заменить detailsFragment на WebViewFragment
.
проблема, с которой я сталкиваюсь, заключается в том, что при попытке загрузить url-адрес в webviewfragment WebView
is ноль.
WebViewFragment webViewFragment = new WebViewFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.deal_details_fragment, webViewFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
// Set the url
if (webViewFragment.getWebView()==null)
Log.d("webviewfragment", "is null");
webViewFragment.getWebView().loadUrl("http://www.google.com");
ниже приведен мой основной макет,который имеет исходные два фрагмента.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_activity_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:name="com.bencallis.dealpad.DealListFragment"
android:id="@+id/deal_list_fragment"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" >
<!-- Preview: layout=@layout/deal_list_fragment -->
</fragment>
<fragment
android:name="com.bencallis.dealpad.DealDetailsFragment"
android:id="@+id/deal_details_fragment"
android:layout_weight="2"
android:layout_width="0px"
android:layout_height="match_parent" >
<!-- Preview: layout=@layout/deal_details_fragment -->
</fragment>
</LinearLayout>
кажется, что webViewFragment не создается полностью как WebView
не был инициализирован. Я посмотрел онлайн, но есть очень мало информации о WebViewFragment
.
любые идеи, как обеспечить WebView
инициализируется в WebViewFragment
?
4 ответов
С большой помощью Espiandev мне удалось получить рабочий WebView. Чтобы убедиться, что ссылки открыты во фрагменте, а не в приложении веб-браузера, я создал простой клиент InnerWebView, который расширяет WebViewClinet.
public class DealWebViewFragment extends Fragment {
private WebView mWebView;
private boolean mIsWebViewAvailable;
private String mUrl = null;
/**
* Creates a new fragment which loads the supplied url as soon as it can
* @param url the url to load once initialised
*/
public DealWebViewFragment(String url) {
super();
mUrl = url;
}
/**
* Called to instantiate the view. Creates and returns the WebView.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mWebView != null) {
mWebView.destroy();
}
mWebView = new WebView(getActivity());
mWebView.setOnKeyListener(new OnKeyListener(){
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return false;
}
});
mWebView.setWebViewClient(new InnerWebViewClient()); // forces it to open in app
mWebView.loadUrl(mUrl);
mIsWebViewAvailable = true;
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
return mWebView;
}
/**
* Convenience method for loading a url. Will fail if {@link View} is not initialised (but won't throw an {@link Exception})
* @param url
*/
public void loadUrl(String url) {
if (mIsWebViewAvailable) getWebView().loadUrl(mUrl = url);
else Log.w("ImprovedWebViewFragment", "WebView cannot be found. Check the view and fragment have been loaded.");
}
/**
* Called when the fragment is visible to the user and actively running. Resumes the WebView.
*/
@Override
public void onPause() {
super.onPause();
mWebView.onPause();
}
/**
* Called when the fragment is no longer resumed. Pauses the WebView.
*/
@Override
public void onResume() {
mWebView.onResume();
super.onResume();
}
/**
* Called when the WebView has been detached from the fragment.
* The WebView is no longer available after this time.
*/
@Override
public void onDestroyView() {
mIsWebViewAvailable = false;
super.onDestroyView();
}
/**
* Called when the fragment is no longer in use. Destroys the internal state of the WebView.
*/
@Override
public void onDestroy() {
if (mWebView != null) {
mWebView.destroy();
mWebView = null;
}
super.onDestroy();
}
/**
* Gets the WebView.
*/
public WebView getWebView() {
return mIsWebViewAvailable ? mWebView : null;
}
/* To ensure links open within the application */
private class InnerWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
надеюсь, это полезно для кого-то в будущем.
EDIT: поэтому я некоторое время играл с этим, и кажется, что WVF немного мусор и предназначен для переопределения. Тем не менее, нет никакой документации об этом вообще! Проблема связана с тем, что вы можете вызвать getWebView() перед Fragment
s view загружен, следовательно, ваш NullPointerException
. За исключением того, что нет никакого способа определить, когда вид фрагмента был загружен, так что вы застряли!
вместо этого я перешел класс, добавляя биты и изменяя биты, так что теперь он будет работать отлично. Проверка этой ссылке для кода. Тогда вместо использования:
WebViewFragment webViewFragment = new WebViewFragment();
чтобы загрузить фрагмент, используйте:
ImprovedWebViewFragment wvf = new ImprovedWebViewFragment("www.google.com");
этот класс также включает в себя удобный способ Загрузки url-адреса, который не бросить Exception
если нет WebView
.
итак, нет, я не думаю, что есть особенно простой способ использовать встроенный WebViewFragment, но довольно легко сделать что-то, что работает вместо этого. Надеюсь, это поможет!
WebViewFragment как есть не так просто использовать. Попробуйте это простое расширение (вы можете скопировать/вставить):
public class UrlWebViewFragment extends WebViewFragment{
private String url;
public static UrlWebViewFragment newInstance(String url) {
UrlWebViewFragment fragment = new UrlWebViewFragment();
fragment.url = url;
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
WebView webView = (WebView) super.onCreateView(inflater, container, savedInstanceState);
webView.loadUrl(url);
return webView;
}
}
звонок, где вам нужно, используя метод фабрики:
WebViewFragment fragment = UrlWebViewFragment.newInstance("http://ur-url.com");
фрагменты могут быть заменены, только если они были initiallized в Java, а не в XML. Я так думаю, у меня была такая же проблема и ее решили. Измените свой XML на это:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_activity_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<fragment
android:name="com.bencallis.dealpad.DealListFragment"
android:id="@+id/deal_list_fragment"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" >
<!-- Preview: layout=@layout/deal_list_fragment -->
</fragment>
<View
android:id="@+id/my_container"
android:layout_weight="2"
android:layout_width="0px"
android:layout_height="match_parent" >
</View>
</LinearLayout>
а затем в Java, ваш метод onCreate:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.my_container, new DealDetailsFragment());
transaction.commit();
или даже лучше создать весь метод, чтобы просто иметь дело с Transaction
s.
теперь Transaction
из вашего вопроса следует работать. :)