Swipe between tabbar pages in Xamarin Shell - c#

I use bottom menu and disable flyout.
For IOS I needed to add swipe gesture to shell. I used custom render.
How to add swipe animation?
On Android for tabbed page it works out of box.
I need something similar for Xamarin Shell tabbar menu.
I thought Xamarin Forms is pretty easy to use without any problems. It’s basic thing it should be implemented
[assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
namespace ShellDemo.iOS
{
public class CustomShellRenderer : ShellRenderer
{
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new CustomTabbarAppearance();
}
}
public class CustomTabbarAppearance : IShellTabBarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(UITabBarController controller)
{
}
public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
UISwipeGestureRecognizer swipeRight = new UISwipeGestureRecognizer((gesture) =>
{
if (controller.SelectedIndex > 0)
{
controller.SelectedIndex--;
}
});
swipeRight.Direction = UISwipeGestureRecognizerDirection.Right;
controller.View.AddGestureRecognizer(swipeRight);
UISwipeGestureRecognizer swipeLeft = new UISwipeGestureRecognizer((gesture) =>
{
if (controller.SelectedIndex < controller.ViewControllers.Count() - 1)
{
controller.SelectedIndex++;
}
});
swipeLeft.Direction = UISwipeGestureRecognizerDirection.Left;
controller.View.AddGestureRecognizer(swipeLeft);
}
public void UpdateLayout(UITabBarController controller)
{
}
}
}```
![enter image description here](https://i.stack.imgur.com/dXNMJ.gif)

Related

How to increase the space between the bottom of the screen and Tab titles on Android using Xamarin Forms Shell?

I have used ShellRenderer but I am unable to get the code working to add an extra space between the bottom of the screen and the icons. Here is an image:
I need to increase the space between the bottom of the screen and the tab item titles.
Here is the code that I have tried:-
namespace MyProject.Droid.CustomRenderers
{
public class CustomShellRenderer : ShellRenderer
{
public CustomShellRenderer(Context context) : base(context)
{
}
protected override IShellTabLayoutAppearanceTracker CreateTabLayoutAppearanceTracker(ShellSection shellSection)
{
return new CustomBottomNavAppearance();
}
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
return base.CreateShellSectionRenderer(shellSection);
}
protected override IShellItemRenderer CreateShellItemRenderer(ShellItem shellItem)
{
return base.CreateShellItemRenderer(shellItem);
}
}
public class CustomBottomNavAppearance : IShellTabLayoutAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(TabLayout tabLayout)
{
}
public void SetAppearance(TabLayout tabLayout, ShellAppearance appearance)
{
for (int i = 0; i < tabLayout.ChildCount; i++)
{
var child = tabLayout.GetChildAt(i);
child.SetPadding(0, 0, 0, 20);
}
}
}
}
Let me know how can I fix this. Thanks!

How to prevent Xamarin forms, a custom menu and WebView renderer with EvaluateJavascript from freezing?

I have created a custom menu item which appears in the default menu which pops up when selecting text on my custom WebView.
On clicking on the menu item it calls EvaluateJavascript to get the selected WebView text, and then passes the text to another page.
However after performing this action once or twice, some text on certain areas of the screen start to become unresponsive to clicks eg. text on the parts of the WebView become unselectable, clicks on that part of the screen on other pages becomes unresponsive and even the soft keyboard becomes unclickable in some spots. If this continues for a while sometimes my app will then suddenly freeze the entire operating system and I have to soft reset my phone. It appears that there maybe some serious memory leakage going on.
I create my custom menu item in the MainActivity class:
public override void OnActionModeStarted(ActionMode mode)
{
if (Root.IsCurrentPageType<DictPage>() && DictP.IsWebViewFocused())
{
IMenu menu = mode.Menu;
menu.Add("To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this, mode));
}
base.OnActionModeStarted(mode);
}
It is then handled in the Listener class...
public class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
{
private MainActivity mContext;
ActionMode _mode;
public MyMenuItemOnMenuItemClickListener(MainActivity activity, ActionMode mode)
{
this.mContext = activity;
_mode = mode;
}
public bool OnMenuItemClick(IMenuItem item)
{
WEB.CopyToMainNotes();
Device.BeginInvokeOnMainThread(() =>
{
//close menu if clicked
_mode?.Finish();
});
return true;
}
}
...which calls CopyToMainNotes on my derived WebView class and its associated Renderer and EventHandler classes:
public class WebViewEx : Xamarin.Forms.WebView
{
public static WebViewEx WEB;
//Namespace
//YourClass
public event WebViewExEventHandler CallNativeMethodEvent;
public void CallNativeMethod(WebViewExEventType type)
{
WebViewExEventArgs e = new WebViewExEventArgs();
e.EventType = type;
CallNativeMethodEvent?.Invoke(this, e);
}
public WebViewEx()
{
WEB = this;
}
public void CopyToMainNotes()
{
Device.BeginInvokeOnMainThread(() =>
{
CallNativeMethod(WebViewExEventType.copyToMainNotes);
});
}
}
public delegate void WebViewExEventHandler(object sender, WebViewExEventArgs e);
public class WebViewExEventArgs : EventArgs
{
public enum WebViewExEventType { copyToMainNotes };
public WebViewExEventType EventType = WebViewExEventType.copyToMainNotes;
public WebViewExEventArgs() : base()
{
}
}
public class WebViewExRenderer : WebViewRenderer
{
public WebViewExRenderer(Android.Content.Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
WebViewEx ex = e.NewElement as WebViewEx;
ex.CallNativeMethodEvent += WebViewEx_CallNativeMethodEvent;
}
}
internal class JavascriptCallback : Java.Lang.Object, IValueCallback
{
public JavascriptCallback(Action<string> callback)
{
_callback = callback;
}
private Action<string> _callback;
public void OnReceiveValue(Java.Lang.Object value)
{
_callback?.Invoke(Convert.ToString(value));
}
}
private void WebViewEx_CallNativeMethodEvent(object sender, WebViewExEventArgs e)
{
switch (e.EventType)
{
case WebViewExEventType.copyToMainNotes:
{
CopyToMainNotes();
break;
}
}
}
public void CopyToMainNotes()
{
string script = "(function(){ return window.getSelection().toString()})()";
var response = string.Empty;
Control?.EvaluateJavascript(script, new JavascriptCallback((r) =>
{
response = r;
Device.BeginInvokeOnMainThread(() =>
{
DPage.CopyThisTextToAnotherPage(response.ToString().Trim('\"'));
});
}));
}
}
The CopyToMainNotes method above is where the EvaluateJavascript takes place and the selected text finally gets sent to another page.
Any ideas where I might be going wrong here? Thanks in advance!

How to change the toolbar back icon in xamarin forms android

I am working on xamarin forms. I wanted to change the Toolbar back icon how to do it. I searched lot about it. I didn't get proper solution. Any help would be appreciated.
Thanks
praveen
Try this
LoadApplication(new App());
var upArrow = Resources.GetDrawable(Resource.Drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.SetColorFilter(Resources.GetColor(Resource.Color.white), PorterDuff.Mode.SrcIn);
ActionBar.SetHomeAsUpIndicator(upArrow);
References
https://forums.xamarin.com/discussion/57791/cant-change-android-back-button-in-xamarin-forms
https://forums.xamarin.com/discussion/103317/change-navigation-bar-back-button-color-in-xamarin-android
How to change the toolbar back icon in xamarin forms android
You could refer to my answer: How to change navigation page back button in xamarin forms.
I write it here again:
We need to custom a NavigationPageRenderer, override the OnPushAsync method to set the Toolbar's navigation icon.
using AToolbar = Android.Support.V7.Widget.Toolbar;
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(NavigationPageRendererDroid))] // APPCOMP
...
public class NavigationPageRendererDroid : Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer // APPCOMP
{
public AToolbar toolbar;
public Activity context;
protected override Task<bool> OnPushAsync(Page view, bool animated)
{
var retVal = base.OnPushAsync(view, animated);
context = (Activity)Xamarin.Forms.Forms.Context;
toolbar = context.FindViewById<Android.Support.V7.Widget.Toolbar>(Droid.Resource.Id.toolbar);
if (toolbar != null)
{
if (toolbar.NavigationIcon != null)
{
toolbar.NavigationIcon = Android.Support.V4.Content.ContextCompat.GetDrawable(context, Resource.Drawable.Back);
//toolbar.SetNavigationIcon(Resource.Drawable.Back);
}
}
return retVal;
}
}
The CustomNavigationPage are defined in PCL :
public class CustomNavigationPage : NavigationPage
{
public CustomNavigationPage(Page startupPage) : base(startupPage)
{
}
}
Usage :
public App()
{
InitializeComponent();
MainPage = new CustomNavigationPage(new MainPage());
}
...
// In MainPage
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new TestPage());
}
[Effect].

How to use Dependency Injection to implement Flyoutnavigation in Xamarin.Forms

how would I use Dependency Injection to use the Flyoutnavigation for my iOS project.
I have decided to stick with the default MasterDetailPage for Android as it doesn't look as bad as iOS.
This is what I have done so far:
In PCL
IMainPage.cs:
public interface IMainPage
{
Page GetMainPage();
}
App.cs:
public partial class App : Application
{
public App()
{
MainPage = DependencyService.Get<IMainPage>().GetMainPage();
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
In Android
MainPage_Android.cs:
[assembly: Xamarin.Forms.Dependency(typeof(MainPage_Android))]
namespace ProjectName.Droid
{
public class MainPage_Android : MasterDetailPage, IMainPage
{
private NavigationPage detail;
private MasterPage master;
public Page GetMainPage()
{
MasterDetailPage mdp = new MasterDetailPage();
//Master
master = new MasterPage();
MasterBehavior = MasterBehavior.Popover;
mdp.Master = master;
//Detail
detail = new NavigationPage(new Home())
{
BarBackgroundColor = Color.FromHex("#01A0E1"),
BarTextColor = Color.White
};
mdp.Detail = detail;
return mdp;
}
}
}
In iOS
I am stuck here.. How do I return a page using the Flyoutnavigation?
If you want to use default style on Android and custom style on iOS, you can try to make a custom renderer for MasterDetailPage on iOS. Then embed your Flyoutnavigation.
This is my iPad renderer:
[assembly: ExportRenderer(typeof(MainPage), typeof(MainPageRenderer))]
namespace FlyoutNavigationDemo.iOS
{
public class MainPageRenderer : TabletMasterDetailRenderer
{
//put your Flyoutnavigation's code here
}
}
Since Flyoutnavigation has too much code. I make a small sample for you, you can refer to here for more details.

UISearchBar SearchButtonClicked never called?

I am new to iOS, and I am using Xamarin Studio on MacOS (I already have my Xamarin.Droid app and now making it on iOS).
I am struggling using an UISearchBar, I want a really basic usage tho .. I tried to follow this recipes (https://developer.xamarin.com/recipes/ios/content_controls/search-controller/) but still can't manage to make it work.
What I am trying to get is a SearchBar, in which the user should type text then press the "search" button on the keyboard. Pressing the search button should call code that will populate an UITableView with data retrieved on my webservice.
Here's my Storyboard structure, a ViewController which contains an UITableView with a name
I tried the following code, everything seems to work fine, but when I press search on the keyboard, SearchButtonClicked event is never fired ... And I can't figure out why
public partial class SearchViewController : UIViewController
{
public SearchViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
var searchController = new UISearchController(this);
searchController.SearchBar.SizeToFit();
searchController.SearchBar.ShowsCancelButton = true;
searchController.SearchBar.SearchButtonClicked += delegate {
Console.WriteLine("Hello ????");
this.Title = "This code is never called";
};
RunnersSearchTableView.TableHeaderView = searchController.SearchBar;
base.ViewDidLoad();
}
}
Also tried
public partial class SearchViewController : UIViewController
{
public SearchViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
var searchController = new UISearchController(this);
searchController.SearchBar.SizeToFit();
searchController.HidesNavigationBarDuringPresentation = true;
searchController.SearchBar.ShowsCancelButton = true;
searchController.SearchBar.Delegate = new MySearchBarDelegate();
RunnersSearchTableView.TableHeaderView = searchController.SearchBar;
base.ViewDidLoad();
}
}
public class MySearchBarDelegate : UISearchBarDelegate
{
public MySearchBarDelegate()
{
}
public override void SearchButtonClicked(UISearchBar searchBar)
{
Console.WriteLine("TEST");
searchBar.ResignFirstResponder();
base.SearchButtonClicked(searchBar);
}
}
And also tried
public partial class SearchViewController : UIViewController
{
public SearchViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
var searchController = new UISearchController(this);
searchController.SearchBar.SizeToFit();
searchController.HidesNavigationBarDuringPresentation = true;
searchController.SearchBar.ShowsCancelButton = true;
searchController.SearchBar.WeakDelegate = this;
RunnersSearchTableView.TableHeaderView = searchController.SearchBar;
base.ViewDidLoad();
}
[Export("searchBarSearchButtonClicked:")]
public virtual void SearchButtonClicked(UISearchBar searchBar)
{
Console.WriteLine("hello??");
searchBar.ResignFirstResponder();
}
}
None of them seems to work
You need to register delegate for searchbar .
[Foundation.Register("UISearchBar", true)]
for more : https://developer.xamarin.com/api/type/UIKit.UISearchBar/

Categories

Resources