I tried to use Search Widget in my Xamarin.Forms project as people doing it in Xamarin.Android but it is not working. I want the same result as you see on image below.enter image description here
Here is my code:
**Main Activity :**
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Support.V4.View;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Support.V4.App;
using Android.Support.V4.Widget;
using Android.Util;
using Android.Support.V4.Content;
namespace GitRemote.Droid
{
[Activity(Label = "GitRemote", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
FormsAppCompatActivity.ToolbarResource = Resource.Layout.toolbar;
FormsAppCompatActivity.TabLayoutResource = Resource.Layout.tabs;
base.OnCreate(bundle);
Forms.Init(this, bundle);
LoadApplication(new App());
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
Android.Widget.SearchView searchView;
MenuInflater.Inflate(Resource.Menu.menu_home, menu);
var searchItem = menu.FindItem(Resource.Id.action_search);
var provider = MenuItemCompat.GetActionView(searchItem);
searchView = provider.JavaCast<Android.Widget.SearchView>();
// searchView.SetIconifiedByDefault(false);
searchView.QueryTextSubmit += (sender, args) =>
{
Toast.MakeText(this, "You searched: " + args.Query, ToastLength.Short).Show();
};
//searchView.QueryTextSubmit += (sender, args) =>
//{
// var view = sender as Android.Support.V7.Widget.SearchView;
// if ( view != null )
// view.ClearFocus();
//};
//return base.OnCreateOptionsMenu(menu);
return true;
}
}
}
**menu_home:**
<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_search"
android:title="#string/search"
android:icon="#android:drawable/ic_menu_search"
app:showAsAction="always|withText"
app:actionViewClass="android.widget.SearchView"/>
</menu>
I had the same problem with a Xamarin.Forms Search Component.
Xamrin.Forms has a control that is called: SearchBar. Indeed... on the Emulator is shown but when you install the application on an android device(eg. Samsung S8) the SearchBar is not Visible.
I can sugest a workaround:
Set the Height of the searchbar manually. 42 is the default for SearchBar.
HeightRequest="42"
The issue was addressed here
https://bugzilla.xamarin.com/show_bug.cgi?id=43975
Related
I am making themes for a cross-platform Xamarin Forms application. I've gotten to a point where I need to style a date picker depending on light/dark modes. The picker itself and the text it displays are okay depending the mode, however the dialog pop-up appears to have white text and a white background, making it kind of useless. Is there a way for me to customise this?
Image of a picker. I want to customise the white part
Try this , added some random Colors in Android and iOS
In styles.xml
<item name="android:datePickerDialogTheme">#style/CustomDatePickerDialog</item>
</style>
<style name="CustomDatePickerDialog" parent="ThemeOverlay.AppCompat.Dialog">
<!--header background-->
<item name="colorAccent">#009933</item>
<!--header textcolor-->
<item name="android:textColorPrimaryInverse">#ff9900</item>
<!--body background-->
<item name="android:windowBackground">#000099</item>
<!--selected day-->
<item name="android:colorControlActivated">#ff8000</item>
<!--days of the month-->
<item name="android:textColorPrimary">#ffff00</item>
<!--days of the week-->
<item name="android:textColorSecondary">#ff0066</item>
<!--cancel&ok-->
<item name="android:textColor">#00ffff</item>
</style>
Add Class in iOS
using DatePickerStackO.iOS;
using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
[assembly: ExportRenderer(typeof(Xamarin.Forms.DatePicker), typeof(DateTimeRenderer))]
namespace DatePickerStackO.iOS
{
public class DateTimeRenderer : DatePickerRenderer
{
private UIDatePicker _picker;
bool _disposed;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.DatePicker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
_picker = new UIDatePicker { Mode = UIDatePickerMode.Date, TimeZone = new NSTimeZone("UTC") };
if (UIDevice.CurrentDevice.CheckSystemVersion(14, 0))
{
_picker.PreferredDatePickerStyle = UIKit.UIDatePickerStyle.Wheels;
}
_picker.BackgroundColor = Color.Red.ToUIColor(); // YOUR COLOR HERE
_picker.ValueChanged -= HandleValueChanged;
_picker.ValueChanged += HandleValueChanged;
Control.InputView = _picker;
}
}
void HandleValueChanged(object sender, EventArgs e)
{
if (Element != null && Element.OnThisPlatform().UpdateMode() == UpdateMode.Immediately)
{
UpdateElementDate();
}
}
void UpdateElementDate()
{
Element?.SetValueFromRenderer(Xamarin.Forms.DatePicker.DateProperty, _picker.Date.ToDateTime().Date);
}
protected override void Dispose(bool disposing)
{
if (_disposed)
return;
_disposed = true;
if (disposing)
{
if (_picker != null)
{
_picker.RemoveFromSuperview();
_picker.ValueChanged -= HandleValueChanged;
_picker.Dispose();
_picker = null;
}
}
base.Dispose(disposing);
}
}
}
I have used a nuget package called XamForms.Controls.Calendar which provides an easily customisable calendar:
screenshot of package
Here is a small guide on how to implement
Hopefully this is good enough for you use :)
I am currently writing a Messenger app for my Guild, currently I got as far as, I can log in and switch between different tabs, that lists currently dummy message titles (like a whisper name).
My goal later is that once you click on one of the messages you can reply / read messages in WhatsApp style (tips welcome here as well).
But my current issue is that I use the "Bottom" navigation menu. I swap the tabs currently with new activies. But whenever I click a button the screen "flickers" like, it's restarting the whole app.
Is there some way to switch "fluid" the upper part of the app, while the menu always stays nicely at the bottom?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Widget;
namespace GuildMaster
{
[Activity(Label = "Whisper")]
public class Whisper : Activity, BottomNavigationView.IOnNavigationItemSelectedListener
{
private ListView whisperlist;
private List<string> itemlist;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
BottomNavigationView navigation = FindViewById<BottomNavigationView>(Resource.Id.navigation);
navigation.SetOnNavigationItemSelectedListener(this);
whisperlist = FindViewById<ListView>(Resource.Id.whisper);
itemlist = new List<string>();
itemlist.Add("Tim");
itemlist.Add("Tom");
ArrayAdapter<string> whisper = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, itemlist);
whisperlist.Adapter = whisper;
whisperlist.ItemClick += Listnames_ItemClick;
// Create your application here
}
public void Listnames_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Toast.MakeText(this, e.Position.ToString(), ToastLength.Long).Show();
}
public bool OnNavigationItemSelected(IMenuItem item)
{
switch (item.ItemId)
{
case Resource.Id.navigation_home:
StartActivity(typeof(Whisper));
return true;
case Resource.Id.navigation_dashboard:
StartActivity(typeof(Guild));
return true;
case Resource.Id.navigation_notifications:
StartActivity(typeof(Other));
return true;
}
return false;
}
}
}
you should try working with fragments instead of activities with the bottom navigation, working with an activity means u have to start a completely new screen with a new bottom navigation, if that is what you are doing then it is completely normal to "flicker" when doing so
as a solution, use an activity with an xml that holds a fragment view and a bottom navigation view, and when u switch from the bottom navigation in your activity, switch the fragments loaded within the fragment view.
this can be done with different methods, but i would suggest checking out the Navigation Component from Google, since it will also handle the backstack for you.
I'm still fairly new to Visual Studio/Xamarin but I had a simple OpenStreetMap sample running awhile ago for Android that did display a map but that doesn't seem to display map anymore though I haven't changed the code for this sample in awhile as far as I recall. I'm not sure if some Visual Studio/Xamarin or MacOS update might have caused it to not work anymore.
I'm using Visual Studio for Mac community 8.4.4 (build 91) on macOS Mojava 10.14.6 and the following Packages:
Mapsui 1.4.8
OsmSharp 6.2.0
Xamarin.Android.Support.Core.Utils 28.0.0.1
Xamarin.Android.Support.CustomTabs 28.0.0.1
Xamarin.Android.Support.Design 28.0.0.1
Xamarin.Essentials 1.2.0
My MainActivity.cs file contains the following code:
using System;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V7.App;
using Android.Views;
using Android.Widget;
using Mapsui;
using Mapsui.Geometries;
using Mapsui.Projection;
using Mapsui.Styles;
using Mapsui.Utilities;
using Mapsui.UI.Android;
using Mapsui.Widgets.ScaleBar;
using Mapsui.Widgets.Zoom;
using Xamarin.Essentials;
namespace mvp_android
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.Main);
var mapControl = FindViewById<MapControl>(Resource.Id.mapcontrol);
var map = new Mapsui.Map();
map.Layers.Add(OpenStreetMap.CreateTileLayer());
map.Widgets.Add(
new ZoomInOutWidget(map) {
HorizontalAlignment = Mapsui.Widgets.HorizontalAlignment.Left,
VerticalAlignment = Mapsui.Widgets.VerticalAlignment.Top,
Orientation = Mapsui.Widgets.Zoom.Orientation.Horizontal,
}
);
var centerOfLondonOntario = new Point(-81.2497, 42.9837);
map.NavigateTo(SphericalMercator.FromLonLat(centerOfLondonOntario.X, centerOfLondonOntario.Y));
map.NavigateTo(map.Resolutions[9]);
mapControl.Map = map;
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.menu_main, menu);
return true;
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
int id = item.ItemId;
if (id == Resource.Id.action_settings)
{
return true;
}
return base.OnOptionsItemSelected(item);
}
private void FabOnClick(object sender, EventArgs eventArgs)
{
View view = (View)sender;
Snackbar.Make(view, "Replace with your own action", Snackbar.LengthLong)
.SetAction("Action", (Android.Views.View.IOnClickListener)null).Show();
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
And my Main.xml contains the following code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Mapsui.UI.Android.MapControl
android:id="#+id/mapcontrol"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Originally, this sample showed the OpenStreetMap's map centering on the London, Ontario location with zoom in/out buttons, but now it just shows a white where the map should be, still shows the zoom in/out buttons and does display the (c)OpenStreetMap watermark.
What am I missing here?
Update 2021-03-23: Since last week the "BruTile Tile Library" user agent is blocked by OpenStreetMap. This is the default of BruTile's KnownTileSource.Create. This method has a parameter to pass in your own user agent. The fix is to provide a string that is specific to your app.
The version of BruTile used in Mapsui 1.4.8 did not send the user-agent as part of it's request and at some point the openstreetmap server started blocking requests for this reason.
As a workaround you could create a custom ITileSource as described here by Matt Schneeberger:
https://github.com/Mapsui/Mapsui/issues/668#issuecomment-497947690
I have a DialogFragment that is working and need to return the selected item from a spinner. I've tried many methods that I've found on Stack Overflow and other places but they are all using java which doesn't (apparently) translate well to c# in Xamarin for Visual Studio 2017. To date, nothing has worked My DialogFragment layout is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="300dp"
android:minHeight="75dp">
<TextView
android:text="Select the department you are registering for."
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textStyle="bold"
android:id="#+id/textView2" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:id="#+id/department_spinner" />
<Button
android:text="Ok"
android:layout_width="200px"
android:layout_gravity="center"
android:layout_height="34.5dp"
android:id="#+id/button_ok" />
</LinearLayout>
The class code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace MyProject
{
class selectDepartment : DialogFragment
{
static Spinner department;
public string selection = "";
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
View view = inflater.Inflate(Resource.Layout.selectDepartment, container, false);
Button ok = view.FindViewById<Button>(Resource.Id.button_ok);
department = view.FindViewById<Spinner>(Resource.Id.department_spinner);
List<string> list = new List<string>();
list.Add("Select Department");
list.Add("Dept. A");
list.Add("Dept. B");
var adapter = new ArrayAdapter<string>(this.Activity, Android.Resource.Layout.SimpleSpinnerItem, list.ToArray());
department.Adapter = adapter;
ok.Click += (sender, args) =>
{
selection = string.Format("{0}", department.GetItemAtPosition(department.SelectedItemPosition));
};
return view;
}
}
}
This is the code that shows the dialog:
FragmentTransaction getdepartment = FragmentManager.BeginTransaction();
selectDepartment getDept = new selectDepartment();
getDept.Show(getdepartment , "Select Department");
// Here I attempt to read a property which contains the selection
string selection = getDept.selection;
In my last attempt, I assigned the spinner selection to a property and I attempt to read that property to get the value selected, but the dialog is (apparently) displayed on a different thread and the selection isn't chosen when that line of code is executed. I tried making my method async and await the dialog, but that just made matters worse. What am I missing?
use a custom event
public class DialogEventArgs : EventArgs
{
public string Selection { get; set; }
}
and then in selectDepartment add:
public delegate void DialogEventHandler(object sender, DialogEventArgs args);
public event DialogEventHandler Dismissed;
Finally in the button's click handler add:
if (null != Dismissed)
Dismissed(this, new DialogEventArgs { Selection = selection });
when you create the dialog, attach an event handler
selectDepartment getDept = new selectDepartment();
getDept.Dismissed += (s, e) => { /* do something with e.Selection here */ };
This is the code in my class i have:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing.Imaging;
namespace Magnifier20070401
{
public partial class MagnifierForm : Form
{
public MagnifierForm(Configuration configuration, Point startPoint)
{
InitializeComponent();
//--- My Init ---
mConfiguration = configuration;
FormBorderStyle = FormBorderStyle.None;
ShowInTaskbar = mConfiguration.ShowInTaskbar;
TopMost = mConfiguration.TopMostWindow;
Width = mConfiguration.MagnifierWidth;
Height = mConfiguration.MagnifierHeight;
// Make the window (the form) circular
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(ClientRectangle);
Region = new Region(gp);
mImageMagnifier = Properties.Resources.magnifierGlass;
On the Properties im getting: Error 1 The name 'Properties' does not exist in the current context
I added this Form as Existing item to my project and im getting an error on this Properties.
And i have the magnifierGlass image in the Resources.
Found it needed to add my project name before the properties:
mImageMagnifier = ScreenVideoRecorder.Properties.Resources.magnifierGlass;
Now it's working thanks.