When I scroll up in my webview app, it triggers a Swipe-to-Refresh refresh-
How can I make the refresh to trigger only when reaching the top of the page?
I saw this post about this exact problem, but I couldn't understand where to insert the code
If you answer please be specific about how I implement the code and where
Thank you
If you're using WebView only,
you may have to use these layout in the provided order,
SwipeRefreshLayout
1.1 NestedScrollView
1.1.1 WebView
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/webview1"
android:layout_width="598dp"
android:layout_height="1022dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
And in your Activity
public class WebView1 extends AppCompatActivity {
SwipeRefreshLayout swipeRefreshLayout;
WebView browser;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
browser = (WebView) findViewById(R.id.webview1);
swipeRefreshLayout = (SwipeRefreshLayout)this.findViewById(R.id.swipeContainer);
browser.setWebViewClient(new WebViewClient());browser.getSettings().setJavaScriptEnabled(true);
browser.loadUrl("http://www.google.com");
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
browser.reload();
swipeRefreshLayout.setRefreshing(false);
}
});
}
}
If you're copying this code, please note that I'm importing androidx libraries
To make it to support libraries, consider the following
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout/>
<androidx.nesv4.widget.NestedScrollView/>
to
<android.support.v4.widget.SwipeRefreshLayout/>
<android.support.v4.widget.NestedScrollView/>
Related
I have created a project of type "Android App (Xamarin)" in VS2019 which has the following activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<WebView
android:id="#+id/web"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
I have code that uses the pipes a value from the built in NFC reader on Samsung tablet to the web page loaded into the WebView, and all is working well.
However, if a page load stalls or the user gets an error in the web page for some reason, there is no way to refresh the page. I wanted to add a pull down to refresh, and also a pull from left to right to go back would be pretty cool as well, but will focus on pull to refresh in this post.
I found a Xamarin Forms example of how to use the RefreshView to achieve this, but it doesn't seem to work in the Android only project.
How can I use the RefreshView in my "Android App (Xamarin)" project, or is there a better way to do this?
I am targeting Android 9.0.
Thanks for your time.
A simple sample like below:
public class RefreshWebView : Activity,SwipeRefreshLayout.IOnRefreshListener,SwipeRefreshLayout.IOnChildScrollUpCallback
{
private WebView webView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.refresh_webview);
SwipeRefreshLayout swipeRefreshLayout = FindViewById<SwipeRefreshLayout>(Resource.Id.swipe_fresh);
webView = FindViewById<WebView>(Resource.Id.web);
webView.LoadUrl("https://www.google.com");
webView.SetWebViewClient(new MyWebClient(swipeRefreshLayout));
swipeRefreshLayout.SetOnRefreshListener(this);
swipeRefreshLayout.SetOnChildScrollUpCallback(this);
}
public void OnRefresh()
{
webView.LoadUrl(webView.Url.ToString());
}
public bool CanChildScrollUp(SwipeRefreshLayout parent, View child)
{
return webView.ScrollY > 0;
}
class MyWebClient : WebViewClient
{
SwipeRefreshLayout swipeRefresh;
public MyWebClient(SwipeRefreshLayout swipeRefreshLayout)
{
swipeRefresh = swipeRefreshLayout;
}
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return true;
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
if (swipeRefresh.Refreshing)
{
swipeRefresh.Refreshing = false;
}
}
}
}
xaml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_fresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<WebView
android:id="#+id/web"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
So I am developing a project with view pager that has 2 tabs with 2 different fragments. There's a card view in both of the fragments. When I click on one of the item in the card view, it should go to another fragment to load the web view with URLs that are passed from the recycler view adapter. I tried to pass the URLs from the adapter to the fragment to load the web view but the app keep on crashing in the emulator. I might be using the wrong method for this or there's something I didn't include in the program. I really need help!
main_activty.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<androidx.viewpager.widget.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CYBERSECURITY" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AI" />
</com.google.android.material.tabs.TabLayout>
</androidx.viewpager.widget.ViewPager>
</LinearLayout>
fragment_web.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/webView_Frame"
tools:context=".FragmentWeb">
<!-- TODO: Update blank fragment layout -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</WebView>
<ProgressBar
android:id="#+id/progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.view_pager);
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
}
MyRecyclerViewAdapter.java
final String URLs = news.getURLs();
Log.d("here",URLs);
myViewHolder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putString(KEY, URLs);
FragmentWeb fragmentWeb = new FragmentWeb();
fragmentWeb.setArguments(bundle);
fragmentWeb.getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.webView_Frame, fragmentWeb)
.commit();
}
});
Above are the codes I tried to pass the URLs to the FragmentWeb class. I tried with log.d to check and the URLs variable already contain all the URLs. I've also tried with fragmentWeb.getChildFragmentManager or even fragmentWeb.getFragmentManager but neither of them work and keep giving me different errors.
FragmentWeb.java
public class FragmentWeb extends Fragment{
private static final String KEY = "URLS";
private String URLs;
private ProgressBar progressBar;
private WebView webView;
public FragmentWeb() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
URLs = getArguments().getString(KEY);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_web, container, false);
progressBar = view.findViewById(R.id.progress_bar);
webView = view.findViewById(R.id.web_view);
return view;
}
public void loadWebPage()
{
webView.loadUrl(URLs);
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageStarted(WebView view, String URLs, Bitmap favicon) {
progressBar.setVisibility(View.VISIBLE);
webView.setVisibility(View.GONE);
}
#Override
public void onPageFinished(WebView view, String URLs) {
progressBar.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
}
});
}
#Override
public void onStart() {
super.onStart();
loadWebPage();
}
}
Above are the codes to load the web page with the URLs passed from the adapter.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.assignment4_task1, PID: 6803
java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.fragment.app.FragmentManager androidx.fragment.app.FragmentActivity.getSupportFragmentManager()' on a null object reference at com.example.assignment4_task1.MyRecyclerViewAdapter$1.onClick(MyRecyclerViewAdapter.java:66)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Here:
FragmentWeb fragmentWeb = new FragmentWeb();
fragmentWeb.setArguments(bundle);
fragmentWeb.getActivity().getSupportFragmentManager()
You're calling 'getActivity()' on fragmentWeb, but you've just created fragmentWeb above. That fragment is not loaded in any activity yet, so getActivity() returns null.
Get the current activity from the surrounding context, such as the RecyclerView's context or, if you declare the Adapter as an inner class of your Fragment, by using Fragment's getActivity().
In my WebView application SwipeRefreshLayout doesn't work because when I scroll down it triggers page reload function.
One solution I think would be limit the pull-to-refresh layout. I tried this and it doesn't seem to work.
Here is my implementation:
Java file
SwipeRefreshLayout mySwipeRefreshLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySwipeRefreshLayout = (SwipeRefreshLayout)this.findViewById(R.id.swipeContainer);
String URL = "my_url";
mWebView = (WebView) findViewById(R.id.enyakin);
WebSettings webSettings = mWebView.getSettings();
mWebView.loadUrl(URL);
webSettings.setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
// Phone call function if this matters
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("tel:"))
{
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
return true;
}
view.loadUrl(url);
return true;
}
});
mySwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mWebView.reload();
if (null != mySwipeRefreshLayout) {
mySwipeRefreshLayout.setRefreshing(false);
}
}
}
);
XML file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.google.firebase.quickstart.fcm.MainActivity"
tools:showIn="#layout/activity_main">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:fillViewport="true">
<WebView
android:id="#+id/enyakin"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
Can you help me to understand how can I seperate those two scrolling features?
Edit:
Looked here this doesn't answer my question
use setOnChildScrollUpCallback to control when a refresh should be triggered.
Here is the sample code in kotlin.
mySwipeRefreshLayout.apply {
setOnRefreshListener {
// Handle refresh
}
setOnChildScrollUpCallback {parent, child ->
// Return true to disable swiping to refresh.
// You can get scrolling position of nested scroll view and only return true when it is larger than 0.
}
}
I am using webview in android i have implemented pull to refresh in webview. Also i have created a class that handles the external links inside the website to open the links within the app only but the problem is reloader keeps on loading like this
xml file of webview fragment
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe2"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<WebView
android:id="#+id/Zomato"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
/>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
SwipeLayout in the Desc.java
SwipeRefreshLayout swipe;
static WebView webView;
#Override
public void onViewCreated(#NonNull final View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
webView=view.findViewById(R.id.Zomato);
swipe=view.findViewById(R.id.swipe2);
}
swipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
String url = "https://www.zomato.com/";
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
swipe.setRefreshing(false);
}
});
}
webView.setWebViewClient(new Fragment2.GeoWebViewClient());
Hi Actually you are doing wrong because here you are setting web view client tow time means it will override first one so please set only first time and put logic in that onPageFinished it will work. Referer bellow answer
https://stackoverflow.com/a/6720004/3894930
I'm working in a WebView App.
In my last change, i added a function to hide the app bar when i scroll down in webview. Nice !!!
But i have noticed a problem. I will try explain.
Let's suposse that i'm in a News Site, and i'm openning the last news. The most recent news are in the start of the page, and the last news are close to the ends of the page, so i open the last news, and my webview load the url. When the url is loaded, my webview is in the end of the site, and not in the start. It started after i added my "webview" inside of "NestedScrollView". Looks like NestedScrollView is saving my position, and it's affecting my position in the web page. How to fix this ?
Edit: My webview is load inside Framelayout, my webview is a fragment.
WebView Layout
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/swipelayout">
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
>
<WebView
android:id="#+id/inicio_pagina"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"></WebView>
</android.support.v4.widget.NestedScrollView>
FrameLayout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</android.support.design.widget.CoordinatorLayout>
App_Bar_Main
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main"
android:id="#+id/include" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/face"
android:scaleType="center"/>
Edit 2: WebView Fragment
public class InicioPagina extends Fragment {
private ProgressBar prg;
SwipeRefreshLayout mySwipeRefreshLayout;
NestedScrollView NestedScrollView;
public WebView myWebView;
public static InicioPagina newInstance() {
InicioPagina fragment = new InicioPagina();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.iniciopagina, container, false);
prg = (ProgressBar)rootView.findViewById(R.id.progressBar2);
NestedScrollView = (NestedScrollView) rootView.findViewById(R.id.nested_scroll_view);
mySwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipelayout);
myWebView = (WebView) rootView.findViewById(R.id.inicio_pagina);
myWebView.loadUrl("http://google.com.br/");
//*Ativar JavaScript
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
//*Forçar links para abrir no WebView ao invés do navegador
myWebView.setWebViewClient(new WebViewClient());
NestedScrollView.scrollTo(0, 0);
myWebView.setVerticalScrollBarEnabled(false);
mySwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
myWebView.reload();
mySwipeRefreshLayout.setRefreshing(false);
}
});
myWebView.setOnKeyListener(new View.OnKeyListener()
{
#Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if(event.getAction() == KeyEvent.ACTION_DOWN)
{
WebView webView = (WebView) v;
switch(keyCode)
{
case KeyEvent.KEYCODE_BACK:
if(webView.canGoBack())
{
webView.goBack();
return true;
}
break;
}
}
return false;
}
});
return rootView;
}
public class WebViewClient extends android.webkit.WebViewClient{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
prg.setVisibility(View.VISIBLE);
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
prg.setVisibility(View.GONE);
super.onPageFinished(view, url);
}
}
1) Make id for the NestedScrollView
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/nested_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical">
2) Create NestedScrollView object
3) When the new URL is loaded, set the scroll property of the nestedScrollViewobject to 0,0.
nestedScrollViewObj.scrollTo(0, 0);