WebViewFragment webView имеет значение null после выполнения FragmentTransaction
В настоящее время у меня установлено мое приложение с ListFragment
слева и DetailsFragment
справа (похоже на макет на планшете ниже).
![layout]()
В фрагменте детали (фрагмент рядом с списком) у меня есть кнопка для перехода на сделку, которая при нажатии должна заменять деталифрагмент на WebViewFragment
.
Проблема, с которой я столкнулась, заключается в том, что при попытке загрузить URL-адрес в webviewfragment WebView
имеет значение null.
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: [email protected]/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: [email protected]/deal_details_fragment -->
</fragment>
</LinearLayout>
Кажется, что webViewFragment не создается полностью, поскольку WebView
не был инициализирован. Я посмотрел онлайн, но информации о WebViewFragment
очень мало.
Любые идеи о том, как обеспечить WebView
, инициализируются в WebViewFragment
?
Ответы
Ответ 1
С большой помощью от 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;
}
}
Надеюсь, это полезно кому-то в будущем.
Ответ 2
EDIT: Я немного поиграл с этим, и кажется, что WVF немного мусор и предназначен для переопределения. Тем не менее, нет документации по этому поводу вообще! Проблема связана с тем фактом, что вы можете вызвать getWebView() перед загрузкой представления Fragment
, следовательно, ваш NullPointerException
. Кроме того, нет способа обнаружить, когда изображение фрагмента загружено, поэтому вы как бы застряли!
Вместо этого я перепробовал класс, добавляя бит и меняя биты, так что теперь он будет работать нормально.
Проверьте эту ссылку для кода. Затем вместо использования:
WebViewFragment webViewFragment = new WebViewFragment();
чтобы загрузить ваш фрагмент, используйте:
ImprovedWebViewFragment wvf = new ImprovedWebViewFragment("www.google.com");
Этот класс также включает удобный метод для загрузки URL-адреса, который не будет бросать Exception
, если нет WebView
.
Итак, нет, я не думаю, что есть особенно простой способ использования встроенного WebViewFragment, но довольно легко сделать что-то, что работает вместо этого. Надеюсь, это поможет!
Ответ 3
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;
}
}
Вызовите, где вам нужно использовать метод factory:
WebViewFragment fragment = UrlWebViewFragment.newInstance("http://ur-url.com");
Ответ 4
Фрагменты могут быть заменены только в том случае, если они были инициализированы в 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: [email protected]/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
из вашего вопроса должен работать.:)