Xamarin: How to Display a Small Part of Webpage in [Android] WebView? - c#

I'm trying to display only a small part of a webpage in Xamarin Android Webkit WebView. I've seen a lot of answers how to do this in android studio but I've not seen many recent answers for how to do it in xamarin for android. What method would you recommend for this task? I could also settle for loading a WebView and then scrolling down to a certain section of a page.
Here's the code I'm using to generate tab and WebView
//Discover new content
[Activity]
//define class discover content
public class SessionsActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.discover);
//declare webview and tell our code where to find the XAML resource
WebView discoverWebView = FindViewById<WebView>(Resource.Id.webViewDiscover);
//set the webview client
discoverWebView.SetWebViewClient(new WebViewClient());
//load the subscription url
discoverWebView.LoadUrl("https://www.bitchute.com/");
//enable javascript in our webview
discoverWebView.Settings.JavaScriptEnabled = true;
//zoom control on? This should perhaps be disabled for consistency?
//we will leave it on for now
discoverWebView.Settings.BuiltInZoomControls = true;
discoverWebView.Settings.SetSupportZoom(true);
//scrollbarsdisabled
// subWebView.ScrollBarStyle = ScrollbarStyles.OutsideOverlay;
discoverWebView.ScrollbarFadingEnabled = false;
}
}
thanks, in advance! =]

if you look at the Xamarin docs for WebView, you'll see that it has a LoadURL method with the same signature as the Java method. The only difference is the casing of the method - Xamarin usually uses C# casing, but otherwise the method names are the same, and the argument you pass will also be identical
discoverWebView.LoadUrl("javascript:(function() { " +
"document.getElementsByTagName('header'[0].style.display="none"; " +
"})()");

Here's how I did it, #Jason was helpful but a more complete answer is as follows, this loads duckduckgo.com then hides the content_homepage, scroll to mid-bottom:
using Android.Graphics.Drawables;
using Android.OS;
using Android.Support.V4.App;
using Android.Views;
using Android.Webkit;
using Android.Widget;
namespace BottomNavigationViewPager.Fragments
{
public class TheFragment1 : Fragment
{
string _title;
string _icon;
protected static WebView _wv;
public static TheFragment1 NewInstance(string title, string icon) {
var fragment = new TheFragment1();
fragment.Arguments = new Bundle();
fragment.Arguments.PutString("title", title);
fragment.Arguments.PutString("icon", icon);
return fragment;
}
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (Arguments != null)
{
if(Arguments.ContainsKey("title"))
_title = (string)Arguments.Get("title");
if (Arguments.ContainsKey("icon"))
_icon = (string)Arguments.Get("icon");
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = inflater.Inflate(Resource.Layout.TheFragmentLayout1, container, false);
_wv = view.FindViewById<WebView>(Resource.Id.webView1);
var _wvc = new MyWebViewClient();
_wv.SetWebViewClient(_wvc);
//string _wtf = "header";
_wv.Settings.JavaScriptEnabled = true;
_wv.Settings.AllowFileAccess = true;
_wv.Settings.AllowContentAccess = true;
//_wvc.OnPageFinished(_wv, _jsHideBannerC);
_wv.LoadUrl("https://www.duckduckgo.com/");
return view;
}
private class MyWebViewClient : WebViewClient
{
public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon)
{
base.OnPageStarted(view, url, favicon);
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
string _jsHideBanner = "javascript:(function() { " +
"document.getElementById('content_homepage').style.display='none'; " + "})()";
string _jsHideBannerC = "javascript:(function() { " +
"document.getElementsByClassName('logo-wrap--home').style.display='none'; " + "})()";
_wv.LoadUrl(_jsHideBanner);
}
}
}
}

Related

The name 'SupportFragmentManager' does not exist in the current context

I am trying to create a tabbed Swipe navigation system in my xamarin android I am facing The name 'SupportFragmentManager' does not exist in the current context, error I have no idea how to clear this I am new to xamarin android please help me
MainActivity.cs
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.GalleryPage);
// Create your application here
txtView = FindViewById<TextView>(Resource.Id.txtView);
_imageView = FindViewById<ImageView>(Resource.Id.imageView1);
Button button = FindViewById<Button>(Resource.Id.MyButton);
TabLayout tabLayout = (TabLayout)FindViewById(Resource.Id.tablayout_navigation);
ViewPager viewPager = (ViewPager)FindViewById(Resource.Id.pager);
SetupviewPager(viewPager);
tabLayout.SetupWithViewPager(viewPager);
button.Click += delegate
{
Intent = new Intent();
Intent.SetType("image/*");
Intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), PickImageId);
};
}
private void SetupviewPager(ViewPager viewPager)
{
viewPager.OffscreenPageLimit = 3;
var adapter = new PageAdapter1(SupportFragmentManager);
adapter.AddFragment(new Fragment1(), "Title1");
adapter.AddFragment(new Fragment2(), "Title2");
adapter.AddFragment(new Fragment3(), "Title3");
viewPager.Adapter = adapter;
}
PageAdapter1.cs
using System.Collections.Generic;
using Android.Support.V4.App;
using Java.Lang;
using Fragment = Android.Support.V4.App.Fragment;
using FragmentManager = Android.Support.V4.App.FragmentManager;
namespace OCR_Pro
{
public class PageAdapter1: FragmentPagerAdapter
{
private readonly List<Fragment> _fragments;
private readonly List<string> _fragmentnames;
public PageAdapter1(FragmentManager fm) : base(fm)
{
_fragments = new List<Fragment>();
_fragmentnames = new List<string>();
}
public override int Count
{
get { return _fragments.Count; }
}
public override Fragment GetItem(int position)
{
return _fragments[position];
}
public void AddFragment(Fragment fragment, string name)
{
if (fragment == null) return;
_fragments.Add(fragment);
_fragmentnames.Add(name);
}
public override ICharSequence GetPageTitleFormatted(int position)
{
return new Java.Lang.String(_fragmentnames[position]);
}
}
}
Fragment1.cs
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
namespace OCR_Pro
{
public class Fragment1 : Android.Support.V4.App.Fragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
// return inflater.Inflate(Resource.Layout.YourFragment, container, false);
var v = inflater.Inflate(Resource.Layout.Fragment1, container, false);
return v;
}
}
}
Errror : The name 'SupportFragmentManager' does not exist in the current context
It looks like you are trying to pass in the class SupportFragmentManagerinstead of an instance of the class. Try instantiating an instance of SupportFragmentManager and then passing it in.
Please check if installing Xamarin.Android.Support.v4 by nuget package. SupportFragmentManager type is Android.Support.V4.App.FragmentManager.
If you want to get sample, please take a look:
https://learn.microsoft.com/en-us/xamarin/android/user-interface/controls/view-pager/viewpager-and-fragments

networkInfo.IsConnected wont work in Xamarin android fragment

ConnectivityManager connMgr = (ConnectivityManager)this.Activity.GetSystemService(Android.Content.Context.ConnectivityService);
NetworkInfo networkInfo = connMgr.ActiveNetworkInfo;
bool isConnected = networkInfo.IsConnected;
this code is in the onCreateView method in my fragment and when i run the app i get the error:
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object. occurred
it would be great if someone would explain to me what "not set to an instance of an object means" as i dont quite understand. still a little new to xamarin and c# in general.
heres the fragament1.cs file:
using Android.OS;
using Android.Support.V4.App;
using Android.Views;
using Android.Webkit;
namespace TabsApp.Fragments
{
public class Fragment1 : Fragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public static Fragment1 NewInstance()
{
var frag1 = new Fragment1 { Arguments = new Bundle() };
return frag1;
}
WebView webView;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
View v = inflater.Inflate(Resource.Layout.fragment1, container, false);
webView = v.FindViewById<WebView>(Resource.Id.webView);
webView.LoadUrl("https://google.com");
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new WebViewClient());
return v;
}
public void OnBackPressed()
{
webView.GoBack();
}
}
}
and heres the MainActivity.cs file:
using Android.App;
using Android.OS;
using TabsApp.Fragments;
using Android.Content.PM;
using Android.Support.Design.Widget;
using Android.Support.V7.App;
namespace TabsApp
{
[Activity(Label = "#string/app_name", MainLauncher = true, LaunchMode = Android.Content.PM.LaunchMode.SingleTop, Icon = "#drawable/icon",
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : AppCompatActivity
{
BottomNavigationView bottomNavigation;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.main);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
if (toolbar != null)
{
SetSupportActionBar(toolbar);
SupportActionBar.SetDisplayHomeAsUpEnabled(false);
SupportActionBar.SetHomeButtonEnabled(false);
}
bottomNavigation = FindViewById<BottomNavigationView>(Resource.Id.bottom_navigation);
bottomNavigation.NavigationItemSelected += BottomNavigation_NavigationItemSelected;
LoadFragment(Resource.Id.menu_home);
}
private void BottomNavigation_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
LoadFragment(e.Item.ItemId);
}
void LoadFragment(int id)
{
Android.Support.V4.App.Fragment fragment = null;
switch (id)
{
case Resource.Id.menu_home:
fragment = Fragment1.NewInstance();
break;
case Resource.Id.menu_audio:
fragment = Fragment2.NewInstance();
break;
case Resource.Id.menu_video:
fragment = Fragment3.NewInstance();
break;
}
if (fragment == null)
return;
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.content_frame, fragment)
.Commit();
}
}
}
Well its pretty simple this looks to me like you do not have your activity context here and for that reason you are unable to get the connMgr
What you need to do is when you call your fragment from your activity pass the current activity to your ~Fragment~ something like this on your fragment call:
Fragment1 newInstance(this);
Receive it in your fragment with something like this in your constructor:
public static AppCompatActivity _activity
public static Fragment1 newInstance(AppCompatActivity activity )
{
_activity =activity ;
//Lines of code }
And in your onCreateView use it like this :
ConnectivityManager connMgr = (ConnectivityManager)_activity.GetSystemService(Android.Content.Context.ConnectivityService);
NetworkInfo networkInfo = connMgr.ActiveNetworkInfo;
bool isConnected = networkInfo.IsConnected;
If it doesn't work lemme know! Goodluck

Show a pdf into a webview from a link inside that Website Xamarin android

In my app I have implemented a webview to show a website link into that webview. Now that website has a button that contains a pdf file link. If I click on that button on website it shows a pdf file on the web. But if I try to open it into the webview in my app, nothing happens. I am very new in Xamarin android. I could not find any suitable way to that. Here is my code to show the website into the webview.
I want to relod the pdf when click on link from the website. But the result is same as before
Modified Code
namespace Xamarin.PDFView
{
[Activity (Label = "PDFView", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
private string _documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
private string _pdfPath;
private string _pdfFileName = "thePDFDocument.pdf";
private string _pdfFilePath;
private WebView _webView;
private string _webUrl = "https://Link of thewebsite";
private string _pdfURL = "https://Link of thewebsite/25052016.pdf";
private WebClient _webClient = new WebClient();
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
_webView = FindViewById<WebView> (Resource.Id.webView1);
var settings = _webView.Settings;
settings.JavaScriptEnabled = true;
settings.AllowFileAccessFromFileURLs = true;
settings.AllowUniversalAccessFromFileURLs = true;
settings.BuiltInZoomControls = true;
_webView.SetWebViewClient(new WebViewClient());
_webView.SetWebChromeClient(new WebChromeClient());
_webView.LoadUrl(_webUrl);
}
public override bool OnTouchEvent(MotionEvent e)
{
if (_webUrl.Contains(".pdf"))
{
DownloadPDFDocument();
}
return base.OnTouchEvent(e);
}
protected override void OnResume ()
{
base.OnResume ();
_webView.LoadUrl( "javascript:window.location.reload( true )" );
}
protected override void OnPause ()
{
base.OnPause ();
_webView.ClearCache(true);
}
private void DownloadPDFDocument()
{
AndHUD.Shared.Show(this, "Downloading PDF\nPlease Wait ..", -1, MaskType.Clear);
_pdfPath = _documentsPath + "/PDFView";
_pdfFilePath = Path.Combine(_pdfPath, _pdfFileName);
// Check if the PDFDirectory Exists
if(!Directory.Exists(_pdfPath)){
Directory.CreateDirectory(_pdfPath);
}
else{
// Check if the pdf is there, If Yes Delete It. Because we will download the fresh one just in a moment
if (File.Exists(_pdfFilePath)){
File.Delete(_pdfFilePath);
}
}
// This will be executed when the pdf download is completed
_webClient.DownloadDataCompleted += OnPDFDownloadCompleted;
// Lets downlaod the PDF Document
var url = new Uri(_pdfURL);
_webClient.DownloadDataAsync(url);
}
private void OnPDFDownloadCompleted (object sender, DownloadDataCompletedEventArgs e)
{
// Okay the download's done, Lets now save the data and reload the webview.
var pdfBytes = e.Result;
File.WriteAllBytes (_pdfFilePath, pdfBytes);
if(File.Exists(_pdfFilePath))
{
var bytes = File.ReadAllBytes(_pdfFilePath);
}
_webView.LoadUrl("file:///android_asset/pdfviewer/index.html?file=" + _pdfFilePath);
AndHUD.Shared.Dismiss();
}
public class HelloWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return false;
}
}
}
}
Mentioned in the link below:
Read this link
You will need to implement following code using WebViewRenderer
namespace DisplayPDF.Droid
{
public class CustomWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged (e);
if (e.NewElement != null) {
var customWebView = Element as CustomWebView;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.LoadUrl (string.Format ("file:///android_asset/pdfjs/web/viewer.html?file={0}", string.Format ("file:///android_asset/Content/{0}", WebUtility.UrlEncode (customWebView.Uri))));
}
}
}
}
is there any way to show pdf file from a link
As discussed android webview doesn't support pdf files. As a workaround, you can use Google Docs in android webview:
Create a custom webview client and override ShouldOverrideUrlLoading like this:
public class MyWebViewClient: WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
//if PDF file then use google client to show it
if (url.ToLower().EndsWith(".pdf"))
{
var newUrl = "https://docs.google.com/viewer?url=" + url;
view.LoadUrl(newUrl);
}
return true;
}
}
Use your custom webview client:
mWebview.SetWebViewClient(new MyWebViewClient());
Notes: If you use android:layout_height="wrap_content" for your webview, you need to change it to a fixed dp like android:layout_height="400dp", otherwise the webview won't show pdf correctly.

nativeOnDraw failed - Xamarin Android Webview

Im using xamarin for android and i have looked into this issue but nothing seems to work.
Im trying to get a webview to work with a button but it keeps saying whenever i click on the button.
nativeOnDraw failed; clearing to background color.
I will include image of my layout and my code here.
MainActivity
namespace Application
{
[Activity(Label = "Application", MainLauncher = true, Icon = "#drawable/icon", Theme = "#android:style/Theme.NoTitleBar")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
WebPage webPage = new WebPage();
Button btn_MySchedule = FindViewById<Button>(Resource.Id.btnSchedule);
Button btn_MyCareer = FindViewById<Button>(Resource.Id.btnCareer);
Button btn_MySocial = FindViewById<Button>(Resource.Id.btnSocial);
Button btn_Feedback = FindViewById<Button>(Resource.Id.btnFeedback);
Button btn_MyDetails = FindViewById<Button>(Resource.Id.btnDetails);
btn_MySchedule.Click += delegate
{
webPage.isSchedule = true;
//wPage.SetUrl("https://www.google.com");
StartActivity(typeof(WebPage));
};
}
}
}
WebPage
namespace Application
{
[Activity(Label = "WebPage", Theme = "#android:style/Theme.NoTitleBar")]
public class WebPage : Activity
{
public bool isSchedule;
private WebView _webView;
private string _url;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.WebPage);
_webView = FindViewById<WebView>(Resource.Id.webView);
new DisplayWebPage(_webView, GetUrl());
}
public string GetUrl()
{
return _url;
}
public void SetUrl(string sUrl)
{
_url = sUrl;
}
private void ButtonCLicked()
{
if (isSchedule == true)
{
SetUrl("https://www.google.com");
Toast.MakeText(this, "isSchedule is true", ToastLength.Short).Show();
}
}
}
}
I have found the issue. It was due to me calling an empty string via the GetUrl() methods.
The Solution I used is:
[Export("MyScheduleClicked")]
public void MyScheduleClicked(View v)
{
var activity2 = new Intent(this, typeof(WebPage));
activity2.PutExtra("MyURL", "https://www.google.com");
StartActivity(activity2);
}

RegisterForContextMenu seems to have no effect

From what I've been able to gather from google, calling RegisterForContextMenu on a view should be all I have to do if I want OnCreateContextMenu to be called when I long click on said view. This does not happen.
The funny thing is, if I pass in View instead of gameList in the code below, the context menu appears if I long click at an empty portion of the main view. Long clicking on the list (which is a subview) still has no result.
I also tried registering a ItemLongClick event listener on the ListView, this does not get called either :/
The GameList fragment is run inside a viewpager.
using Android.Views;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Android.Support.V4.App;
using Models = Boardwar.Common.Models;
using Boardwar.AndroidClient.Adapters;
namespace Boardwar.AndroidClient.Fragments {
public class GameList : Fragment {
GamesAdapter GamesAdapter;
public GameList () {
}
public GameList (IntPtr handle, JniHandleOwnership jni) : base(handle, jni) {
}
public override View OnCreateView (LayoutInflater inflater, ViewGroup parent, Bundle bundle) {
return inflater.Inflate(Resource.Layout.GameList, parent, false);
}
public override void OnActivityCreated (Bundle p0) {
base.OnActivityCreated(p0);
var mainActivity = Activity as MainActivity;
var gameList = View.FindViewById<ListView>(Resource.Id.game_list);
GamesAdapter = new GamesAdapter(mainActivity);
gameList.Adapter = GamesAdapter;
mainActivity.GamesAdapter = GamesAdapter;
RegisterForContextMenu(gameList);
View.FindViewById(Resource.Id.new_game_button).Click += (sender, e) => {
mainActivity.ReplaceChildFragments(typeof(NewGame));
};
}
public override void OnCreateContextMenu (IContextMenu menu, View view, IContextMenuContextMenuInfo menuInfo) {
base.OnCreateContextMenu(menu, view, menuInfo);
menu.Add(Resource.String.remove_finished_games);
}
public override bool OnContextItemSelected (IMenuItem item) {
MainActivity.Client.RemoveFinishedGames();
return true;
}
public override void OnResume () {
base.OnResume();
GamesAdapter.UpdateList();
}
public override void OnDestroyView () {
base.OnDestroyView();
(Activity as MainActivity).GamesAdapter = null;
}
}
}
My problem was that I was registering ClickHandlers on the actual list-items, instead of a global ClickHandler on the actual list-view. This would block the click event from propegating to the list-view, which is why the context menu wouldn't appear.

Categories