How can I change style of the original tabbed page bar (android with xamarin.forms)? - c#

good morning,
I'm designing my first app in xamarin.forms, but I ran into a problem that is the style of the tabbedpage bar in android.
On iOS it works great, but on Android it has a different display, but I would like to make the homogeneous thing on both operating systems know how to do it?
Screen Android https://ibb.co/cYRLvc4
Screen iOS https://ibb.co/ysnxBr8

You should use a custom effect, first update your android target to 9.0 (and support libraries)
then, create the Routing Effect in your Forms solution:
using Xamarin.Forms;
namespace YourApp
{
public class NoShiftEffect : RoutingEffect
{
public NoShiftEffect() : base("MyEffect.NoShiftEffect")
{
}
}
}
Then, in Android, create a custom renderer:
using Android.Support.Design.BottomNavigation;
using Android.Support.Design.Widget;
using Android.Views;
using yournamespace.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly:ResolutionGroupName ("MyEffect")]
[assembly:ExportEffect (typeof(NoShiftEffect), "NoShiftEffect")]
namespace yournamespace.Droid
{
public class NoShiftEffect : PlatformEffect
{
protected override void OnAttached ()
{
if (!(Container.GetChildAt(0) is ViewGroup layout))
return;
if (!(layout.GetChildAt(1) is BottomNavigationView bottomNavigationView))
return;
// This is what we set to adjust if the shifting happens
bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityLabeled;
}
protected override void OnDetached ()
{
}
}
}
finally, in your tabbde page:
<TabbedPage.Effects>
<local:NoShiftEffect />
</TabbedPage.Effects>

Related

How to change Shell Tabbar height

My Problem:
I use Shell with bottom Tabbar and I simply want to change it height on Android and maybe on iOS.
My Search Results:
I know that the Tabbar is an Android/iOS build in feature with solid specified height.
There seems to be a way to achieve that using a "Custom-Renderer". All projects I have found with this approach don't work with my visual studio (>100 Errors or simply does nothing).
I find it hard to believe that i need >100 rows of code to "only" adjust a height. Could someone provide a working solution to change the Shell Tabbar (bottom tabs) height ?
Edit
Unfourtounately you need to create a custom renderer on each platform project:
Android
MyShellRenderer class
[assembly: ExportRenderer(typeof(App.AppShell), typeof(App.Droid.MyShellRenderer))]
namespace App.Droid
{
public class MyShellRenderer : ShellRenderer
{
public MyShellRenderer(Context context) : base(context)
{
}
protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
return new MyBottomNavViewAppearanceTracker(this, shellItem);
}
}
}
MyBottomNavViewAppearanceTracker class
class MyBottomNavViewAppearanceTracker : ShellBottomNavViewAppearanceTracker
{
public MyBottomNavViewAppearanceTracker(IShellContext shellContext, ShellItem shellItem) : base(shellContext, shellItem)
{
}
public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
bottomView.LayoutParameters.Height = 400;
base.SetAppearance(bottomView, appearance);
}
}
Edit:
iOS part credit goes to https://forums.xamarin.com/discussion/169894/how-to-change-shell-height-of-flyout-items-at-the-bottom-of-the-page
iOS
MyShellRenderer class
[assembly: ExportRenderer(typeof(App.AppShell), typeof(App.iOS.MyShellRenderer))]
namespace App.iOS
{
public class MyShellRenderer : ShellRenderer
{
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new MyCreateTabBarAppearanceTracker();
}
}
}
CreateTabBarAppearanceTracker class
class CreateTabBarAppearanceTracker : ShellTabBarAppearanceTracker
{
public override void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
UITabBar tabBar = controller.TabBar;
int tabBarHeight = 100;
if (tabBar.Frame.Height != tabBarHeight)
{
tabBar.Frame = new CGRect(tabBar.Frame.X, tabBar.Frame.Y + (tabBar.Frame.Height - tabBarHeight), tabBar.Frame.Width, tabBarHeight);
}
}
}
Extras
You were probably missing some namespaces that would explains the abnormal big number of errors.
could not be found are you missing a using directive or an assembly reference
Usually people don't include namespaces (using statements) in answers because most of the time namespaces are obvious and are handled easily by visual studio intellisense.
Just put or hover the cursor on the red underlined statement and a small tooltip appears
Then click on "Show potential fix" or one of the keyboard shortcuts, select the appropriate fix (usually the first one of the suggested list), in this case intelisense will add the required namespace automatically.
Every Code example i have found has excluded the using directives. in my case i needed those following 3 which i wasnt able to find. Thanks to the answer of #Cfun the code above work with adding:
using Google.Android.Material.BottomNavigation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

Xamarin AndroidX.Preferences - Cannot convert from 'SettingsFragment' to 'Android.Support.V4.App.Fragment'

I'm trying to update the settings/preferences screen of my Xamarin Android app, which was using the PreferenceManager class. Since I'm targeting Android 10, this class is deprecated and I'd like to use the AndroidX.Preference library instead.
I followed Google's guide for making a settings screen with AndroidX. Here's the code I'm using
namespace SmartLyrics
{
[Activity(Label = "Settings", ConfigurationChanges = Android.Content.PM.ConfigChanges.ScreenSize | Android.Content.PM.ConfigChanges.Orientation, ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]
public class SettingsFragment : PreferenceFragmentCompat
{
public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey)
{
AddPreferencesFromResource(Resource.Xml.perfs);
}
}
public class SettingsActivity : AppCompatActivity
{
protected override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.main_settings);
SupportFragmentManager
.BeginTransaction()
.Replace(Resource.Id.settingsContainer, new SettingsFragment()) //<--error here
.Commit();
}
}
}
I'm getting the error Cannot convert from 'SmartLyrics.SettingsFragment' to 'Android.Support.V4.App.Fragment'. I looked around online and couldn't find a workaround or anything about this error. I'd really like to use the AndroidX library to prevent any problems with unsupported code later on.
Any help is appreciated. Thanks!
Check which package AppCompatActivity refers to ?
If it:
using Android.Support.V7.App;
change it to :
using AndroidX.AppCompat.App;

How to switch off/on network in xamarin android/iOS app from xamarin uitest in C#

I am writing xamarin uitest in c# to automate xamarin mobile app.I have apk and ipa file with me.I want to toggle network connection after launching the app.How to switch on/off the network using uitest.
In appium we can use togglewifi() to change state.Is there any method available in xamarin?
We could not open/close wifi in code behind in Xamarin for iOS . But you can open the setting page after launch the app.
You can use DependencyService if you call it in Forms
in iOS
using xxx.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
[assembly: Dependency(typeof(OpenSettingsImplement))]
namespace xxx.iOS
{
public class OpenSettingsImplement : ISettingsService
{
public void OpenSettings()
{
var url = new NSUrl($"App-Prefs:");
UIApplication.SharedApplication.OpenUrl(url);
}
}
}
in Android
using Android.Content;
using xxx;
using xxx.Droid;
using Xamarin.Forms;
[assembly: Dependency(typeof(OpenSettingsImplement))]
namespace xxx.Droid
{
public class OpenSettingsImplement : ISettingsService
{
public void OpenSettings()
{
Intent intentOpenSettings = new Intent();
intentOpenSettings.SetAction(Android.Provider.Settings.ActionAirplaneModeSettings);
Android.App.Application.Context.StartActivity(intentOpenSettings);
}
}
}
in Forms,add a new interface
public interface ISettingsService
{
void OpenSettings();
}

How to turn on/off airplane mode in Xamarin.Forms?

How to turn on/off airplane mode in Xamarin.Forms for android and ios?
As #Patrick Hofman and #DavidG said.You could not turn on/off airplane mode by code in your project . However , you can open the setting page of system in Forms by using Dependency Service and let user turn on/off airplane mode manual.
in Forms,add a new interface
public interface ISettingsService
{
void OpenSettings();
}
in iOS
using xxx.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
[assembly: Dependency(typeof(OpenSettingsImplement))]
namespace xxx.iOS
{
public class OpenSettingsImplement : ISettingsService
{
public void OpenSettings()
{
var url = new NSUrl($"App-Prefs:");
UIApplication.SharedApplication.OpenUrl(url);
}
}
}
Note:
App-Prefs: is private api in iOS. So if you want to upload it to app store , it will may been rejected by the store .
in Android
using Android.Content;
using xxx;
using xxx.Droid;
using Xamarin.Forms;
[assembly: Dependency(typeof(OpenSettingsImplement))]
namespace xxx.Droid
{
public class OpenSettingsImplement : ISettingsService
{
public void OpenSettings()
{
Intent intentOpenSettings = new Intent();
intentOpenSettings.SetAction(Android.Provider.Settings.ActionAirplaneModeSettings);
Android.App.Application.Context.StartActivity(intentOpenSettings);
}
}
}

Not able to call Sanitize method from javascript in Android 4.4 where as same is working in Android 4.1

Not able to call Sanitize method from javascript in Android 4.4 where as same is working in Android 4.1. we can call Sanitize method from android 4.1 like Foo.sanitize('test message') where as same is not working in 4.4. Can someone please try to resolve how to call sanitize method.
if we add [Export] & [JavascriptInterface] again its working but ideally no need to these annotations to call sanitize.
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Webkit;
using Java.Interop;
using Android.Net;
namespace WebViewJavaScriptInterface
{
[Activity (Label = "Mono WebView ScriptInterface", MainLauncher = true)]
public class JavaScriptInterfaceActivity : Activity
{
const string html = #"<html><body><p>This is a paragraph.</p><button type=""button"" onClick=""Foo.sanitize('test message')"">Click Me!</button></body></html>";
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
WebView view = FindViewById<WebView> (Resource.Id.web);
view.Settings.JavaScriptEnabled = true;
view.SetWebChromeClient (new WebChromeClient ());
view.AddJavascriptInterface ((Java.Lang.Object)new Foo (this), "Foo");
view.LoadData (html, "text/html", null);
}
}
class Foo : Java.Lang.Object, UrlQuerySanitizer.IValueSanitizer
{
public Foo (Context context)
{
this.context = context;
}
Context context;
[Export]
[JavascriptInterface]
public void Bar (string message)
{
Console.WriteLine ("Foo.Bar invoked!");
Toast.MakeText (context, "This is a Toast from C#! " + message.ToString(), ToastLength.Short).Show ();
}
public string Sanitize(string value)
{
Console.WriteLine("Santizie.Bar invoked!");
return string.Empty;
}
}
}
Can someone please try to resolve how to call sanitize method. if we add [Export] & [JavascriptInterface] again its working but ideally no need to these annotations to call sanitize.
As said in official documentation, you must add JavascriptInterface annotation to the method, if the targetSdkVersion is 17(Android 4.2) or higher.
Caution: If you've set your targetSdkVersion to 17 or higher, you must add the #JavascriptInterface annotation to any method that you want available to your JavaScript (the method must also be public). If you do not provide the annotation, the method is not accessible by your web page when running on Android 4.2 or higher.

Categories

Resources