The DialogFragment has a webview.
Everytime show the DialogFragment,the webview will take some time to load the webview, and before the webpage finished loading, the webview will show the background color. This will affect the user experience. So i want to use some method to preload webview. But really get me there is that m_webviewDialog.show will start two function onCreateDialog and onCreateView. So is there anyway make the webview preload and then add in the onCreateView fucnion?
main activity show code:
public void showWebviewDialog()
{
FragmentManager fragmentManager=getFragmentManager();
if(m_webviewDialog!=null&&m_webviewDialog.isAdded())
{
m_webviewDialog.getDialog().show();
}
else {
m_webviewDialog=mcWebViewDialog.newInstance();
m_webviewDialog.set_loadurl("file:///android_asset/input.html");
m_webviewDialog.show(fragmentManager,"mcWebDialog");
}
}
DialogFragment code:
WebView m_webView;//WebView component
String m_loadurl;
static mcWebViewDialog newInstance()
{
mcWebViewDialog f=new mcWebViewDialog();
return f;
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// other code
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
m_webView = new WebView(getActivity());
//other code
return m_webview;
}
I had an issue, that webview (in DialogFragment) is minimized to zero height althogh it has data. so I used relaod. you must be sure that WebView has data, or you will go to non-ending loop becouse reload leads to onPageFinished and vise versa.
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (view.getContentHeight() == 0){
view.reload();
}
}
...
}
Related
I am using fragment with WebView. Webview opens up correctly. My intention is as follows: Visitor clicks on any of the links within WebView inside the Fragment. Clicked link opens up in new WebView within new Activity. Tricky part - all links are from the same web site, there are no external links. Tricky for me, at least. Many thanks for your help in advance! :)
Here is my WebView code from Fragment:
public class HomeFragment extends Fragment {
#SuppressLint("SetJavaScriptEnabled")
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_naslovna, container, false);
WebView webView = view.findViewById(R.id.webView1);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("https://mywebpage.com/");
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
return view;
}
}
Please try this:
WebViewClient webClient = new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
if( url.equals("http://test.com") ){
// do whatever you want e.g. open up activity with web view and pass the url
}
return true;
}
}
It took 6 more hours u puzzle work, but this is how it got fixed at the end.
public class HomeFragment extends Fragment {
WebView webView;
SwipeRefreshLayout swipeToRefreshLayout;
#SuppressLint("SetJavaScriptEnabled")
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_naslovna, container, false);
webView = view.findViewById(R.id.webView1);
final String pageUrl = "https://mywebpage.com/";
swipeToRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.swiperefresh);
swipeToRefreshLayout.setOnRefreshListener(new RtvTkSwipeToRefreshListener(webView, swipeToRefreshLayout));
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url != pageUrl) {
startNewActivity(url);
}
return true;
}
});
webView.loadUrl(pageUrl);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
return view;
}
private void startNewActivity(String url) {
Intent myIntent = new Intent(getActivity(), NewActivity.class);
myIntent.putExtra("url", url);
getActivity().startActivity(myIntent);
}
}
In my application i am using some fragments, in a viewpager.
I want to show a dialog in a fragment like this:
final Dialog dialog = new Dialog(activity, R.style.DialogTheme);
dialog.show();
The activity is set in the onCreateView like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
activity = getActivity();
}
This is working perfectly, but in some cases like if the app goes in background, and the user comes back to the app, i got an error "Fragment not attached to activity" in the line "dialog.show()".
So to prevent this error i use this:
if(!activity.isFinishing())
dialog.show();
else
Toast.makeText(activity, "Error", Toast.LENGTH_SHORT).show();
I think this is definitly not the best way...
Is there maybe a solution like reloading the app if the activity isFinishing or even a better solution?
override onAttach method
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof YourActiivty) {
//here is your code
} else {
}
}
public class MyFragment extends Fragment
#Override
public void setMenuVisibility(final boolean visible) {
super.setMenuVisibility(visible);
if (visible) {
...
}
}
Try to use DialogFragment rather than showing dialog by Dialog class, it will give you more stable view ,just extend your class by "DialogFragment"
public class DemoDialogFragment extends DialogFragment{
public DemoDialogFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_demo_dialog, container, false);
-----------
return rootView;
}
and make function in you activity for calling it
public void showDialogFrag(DialogFragment dialogFragment, String tag) {
dialogFragment.show(getSupportFragmentManager(), tag);
}
Then call this function by this from any fragment
((MainActivity) getActivity()).showDialogFrag(new DemoDialogFragment(), Constant.FragmentTags.DemoDialogFragment);
I am loading local htmls in webview using Viewpager. This works fine and the right page is loaded from the WebViewFragment into viewpager activity. Scroll or swipe works fine, but I added a menu button to get the title of the current webview, and to toast it. This menu button returns the webview title of the next 2 webview pages in the viewpager.
Reducing the setOfScreenLimit to 1 toasts the webview title of the next webview page in the viewpager. I cant setOfScreenLimit to 0. What is the most probable way to get the current item's webview title when the menu button is clicked. I need to get this and save to a DB.
Code:
ViewPager
ViewPager pager = (ViewPager) findViewById(R.id.pager);
TabsPagerAdapterEnglish pageAdapter = new TabsPagerAdapterEnglish(getSupportFragmentManager());
Bundle extras = getIntent().getExtras();
int value = 0;
if (extras != null) {
value = extras.getInt("keyHTML");
}
pager.setAdapter(pageAdapter);
pager.setCurrentItem(value);
pager.setOffscreenPageLimit(1);
Adapter
public class TabsPagerAdapterEnglish extends FragmentPagerAdapter {
private static int NUM_ITEMS = 3
public TabsPagerAdapterEnglish(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Returns total number of pages
#Override
public int getCount() {
return NUM_ITEMS;
}
// Returns the fragment to display for that page
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return WebFragmentEnglish.newInstance(0, "file:///android_asset/page1.html");
case 1:
return WebFragmentEnglish.newInstance(1, "file:///android_asset/page2.html");
case 2:
return WebFragmentEnglish.newInstance(2, "file:///android_asset/page3.html");
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position) {
}
}
WebFragment
public class WebFragmentEnglish extends Fragment {
// newInstance constructor for creating fragment with arguments
public static WebFragmentEnglish newInstance(int position, String url) {
WebFragmentEnglish fragmentFirst = new WebFragmentEnglish();
Bundle args = new Bundle();
args.putInt("page_position", position);
args.putString("keyHTML", url);
fragmentFirst.setArguments(args);
return fragmentFirst;
}
// Store instance variables based on arguments passed
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
if (null != toolbar) {
toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
}
position = getArguments().getInt("page_position", 0);
url = getArguments().getString("keyHTML");
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getActivity().finish();
case R.id.action_addtofav:
webView = (WebView) getActivity().findViewById(R.id.webView1);
htitle = webView.getTitle();
saveData();
Toast.makeText(getActivity(), htitle + " added to favorite",
Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
}
// Inflate the view for the fragment based on layout XML
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.webview, container, false);
webView = (WebView) view.findViewById(R.id.webView1);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
progressBar.setMax(100);
webView.setWebViewClient(new WebViewClientDemo());
webView.setWebChromeClient(new WebChromeClientDemo());
webView.setInitialScale(1);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
webView.setScrollbarFadingEnabled(false);
webView.getSettings().setBuiltInZoomControls(true);
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View arg0) {
// TODO Auto-generated method stub
return true;
}
});
webView.setLongClickable(false);
webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressBar.setProgress(progress);
}
});
webView.loadUrl(url);
return view;
}
ViewPager will load the current page and the next page(s) up to the offScreenLimit. To get the name of the current page you need to get the current position of the adapter.
It's hard to give more specific help without having code posted. But you can use the ViewPager getCurrentItem method to get the visible index. From there you can either compare it to the index of the page you're displaying (this works if the view pager is static and pages are known in advance), or you can use that index to get the Fragment from the PagerAdapter and call a method on it to save the name.
I was able to solve the problem with the ViewPager.
I removed the toolbar instance from the fragment to use the one in the viewpager's activity. Then in my options menu, you would notice I used
webView = (WebView) **getActivity().**findViewById(R.id.webView1);
I removed the this completely, since i have already defined it in the onCreateView, I think maybe its because of the getActivity field I added to locate the webview ID.
I was updating an old code, I'm glad I was able to solve this. Thank you #Chisko and #Ben
How can I go back one page while in webview? For example: I am on my app in activity and browsing pages in webview, but once I press back button it will exit the app or just goes back in activity instead of the page..
I have done my research and overriding onBackPressed function doesnt work.
#Override
public void onBackPressed() {
if (myWebView.canGoBack()) {
myWebView.goBack();
} else {
super.onBackPressed();
}
}
Whole fragment code:
public class FragmentTwo extends Fragment {
public FragmentTwo() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment2, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState){
WebView webView = (WebView) getActivity().findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webView.setScrollbarFadingEnabled(false);
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://myapp.com");
}
}
Any suggestions of how to achieve it?
onBackPressed() is method of Activity, not of a Fragment, so this code will never be invoked. If you want to do something on back press, your parent activity must let your fragment know about it - you must implement onBackPressed() in parent activity and in that method you should call fragments' method (or fire event on event bus, or use listeners, callback, whatever).
Also right method name is onCreateView(), not onViewCreated() - this one won't be called either.
Inside of the your OnCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.your_layout, container, false);
webView = (WebView) view.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new MyWebViewClient());
webView.loadUrl(expertsUrl);
return view;
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
Ok! In your MainActivity you will write it:
#Override
public void onBackPressed() {
if(yourname_Fragment.webView!=null){
if (yourname_Fragment.webView.canGoBack()) {
yourname_Fragment.webView.goBack();
}
}
}
yourname_Fragmen.java= This is your nameFragment that content the Webview
webView= The name of your WebView (id)
Now. Inside of your Fragment you have to declare static global variable
public static Webview webView;
NOTE: If you have more than one fragment you have to check if this instance is different of NULL;
And that's it! Good luck!
Given two initialized and added in the backstack fragments (one of them i see on the screen). Each fragment has CordovaWebView as view. In one web view i have loaded "www.google.com" in another "www.bing.com". Now, if I press a back button - i am awaiting, that the fragment with "www.bing.com" will be poped from the stack and I will see google site on my device screen. Instead of this, the app immediately exits (for a very short time I can see google.com, but then app completly exits)
small part of Activity:
cordova.getActivity().getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, webViewFragmentGoogle)
.addToBackStack(null)
.commit();
cordova.getActivity().getFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, webViewFragmentBing)
.addToBackStack(null)
.commit();
Fragment:
public class WebViewFragment extends Fragment {
private String mUrl = "file:///android_asset/www/main.html";
private CordovaWebView mWebView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.webview_fragment,container, false);
if (view != null)
mWebView = (CordovaWebView)view;
Bundle bundle=getArguments();
String iframeUrl = bundle.getString("iframeUrl");
if (!mUrl.isEmpty())
{
mWebView.loadUrl(iframeUrl);
}
return view;
}
public void goToUrl(String url) {
mWebView.loadUrl(url);
}
#Override
public void onResume() {
super.onResume();
if (mWebView!= null) {
mWebView.handleResume(true, false);
}
}
#Override
public void onPause() {
if (mWebView != null)
{
mWebView.handlePause(true);
}
super.onPause();
}
#Override
public void onDestroy() {
if (mWebView != null)
{
mWebView.handlePause(true);
mWebView.handleDestroy();
}
super.onDestroy();
}
}
This happens because of CordovaWebView.onKeyUp() logic - it intercepts your key strokes and hooks some actions on them: in this case action is:
this.cordova.getActivity().finish();
Personally I also find killing my activity a bit intrusive, especially in case, when I cannot configure it in any way. Please check CordovaWebView messes up with onBackPressed method in android for some details.