I am using Mono For Android MapsAndLocationDemo and have a question.
Can I please have some help to place some 'markers' on the current map at certain longitude and latitude points? Also, be able to execute some code when each of these 'markers' are clicked on?
thanks
You need to add a map overlay. Here is a tutorial
You can implement ItemizedOverlay
class MonkeyItemizedOverlay: ItemizedOverlay
{
List<OverlayItem> _items;
Context context;
public MonkeyItemizedOverlay (Drawable monkey, Context context) : base(monkey)
{
this.context = context;
// populate some sample location data for the overlay items
_items = new List<OverlayItem>{
new OverlayItem (new GeoPoint ((int)40.741773E6,
(int)-74.004986E6), null, null),
new OverlayItem (new GeoPoint ((int)41.051696E6,
(int)-73.545667E6), null, null),
new OverlayItem (new GeoPoint ((int)41.311197E6,
(int)-72.902646E6), null, null)
};
BoundCenterBottom(monkey);
Populate();
}
}
Then use it like this
var monkey = Resources.GetDrawable (Resource.Drawable.monkey);
var monkeyOverlay = new MonkeyItemizedOverlay (monkey, Context);
map.Overlays.Add (monkeyOverlay);
If you wish to add click functionality override OnTap(int)
protected override bool OnTap(int index)
{
var item = _items[index];
Toast.MakeText(context, index.ToString(), ToastLength.Short).Show();
return true;
}
Related
I spent so much time for discover how to implement TreeView in Android Xamarin, but unlucky seem not have any example say about that.
I tried to use ExpandableListView but it only support to level 2 category. I need someone will have any guide to through this content or some example say about that.
The purpose is explore the folders on server!
Thanks you so much.
The purpose is explore the folders on server!
You can use Binding Library to import some java library for example like AndroidTreeView.
For example, I created an .aar lib from this project. And then code for example like this:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
//create root
TreeNode root = TreeNode.InvokeRoot();
TreeNode parent = new TreeNode("parent");
TreeNode child0 = new TreeNode("ChildNode0");
TreeNode child1 = new TreeNode("ChildNode1");
TreeItem item = new TreeItem() { text = "abc" };
TreeNode child10 = new TreeNode(item).SetViewHolder(new MyHolder(this));
child1.AddChild(child10);
parent.AddChildren(child0, child1);
root.AddChild(parent);
AndroidTreeView atv = new AndroidTreeView(this, root);
LinearLayout rootlayout = FindViewById<LinearLayout>(Resource.Id.rootlayout);
rootlayout.AddView(atv.View);
rootlayout.Invalidate();
}
The TreeItem is created like this:
public class TreeItem : Java.Lang.Object
{
public string text;
}
And MyHolder is like this:
public class MyHolder : TreeNode.BaseNodeViewHolder
{
private Context mcontext;
public MyHolder(Context context) : base(context)
{
mcontext = context;
}
public override View CreateNodeView(TreeNode p0, Java.Lang.Object p1)
{
var inflater = LayoutInflater.FromContext(mcontext);
var view = inflater.Inflate(Resource.Layout.itemview, null, false);
TextView tv = view.FindViewById<TextView>(Resource.Id.itemtv);
var item = p1 as TreeItem;
tv.Text = item.text;
return view;
}
}
Here is the demo, you can find the .aar lib there.
I am trying to implement context actions on my list in Xamarin Forms but can't get it to work.
I am not using XAML, but instead creating my layout in code.
I am trying to follow the steps in https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/interactivity/#Context_Actions and I want to push a new page when "Edit" is clicked.
I cleaned up my code and removed my feeble attempts to make things work.
So this is my custom list cell:
public class PickerListCell : TextCell
{
public PickerListCell ()
{
var moreAction = new MenuItem { Text = App.Translate ("Edit") };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
var option = (PickerListPage.OptionListItem)mi.CommandParameter;
var recId = new Guid (option.Value);
// This is where I want to call a method declared in my page to be able to push a page to the Navigation stack
};
ContextActions.Add (moreAction);
}
}
And here is my model:
public class OptionListItem
{
public string Caption { get; set; }
public string Value { get; set; }
}
And this is the page:
public class PickerPage : ContentPage
{
ListView listView { get; set; }
public PickerPage (OptionListItem [] items)
{
listView = new ListView () ;
Content = new StackLayout {
Children = { listView }
};
var cell = new DataTemplate (typeof (PickerListCell));
cell.SetBinding (PickerListCell.TextProperty, "Caption");
cell.SetBinding (PickerListCell.CommandParameterProperty, "Value");
listView.ItemTemplate = cell;
listView.ItemsSource = items;
}
// This is the method I want to activate when the context action is called
void OnEditAction (object sender, EventArgs e)
{
var cell = (sender as Xamarin.Forms.MenuItem).BindingContext as PickerListCell;
await Navigation.PushAsync (new RecordEditPage (recId), true);
}
}
As you can see by my comments in the code, I have indicated where I believe things are missing.
Please assist guys!
Thanks!
Probably is too late for you, but can help others. The way i've found to do this is passing the instance of page on creation the ViewCell.
public class PickerListCell : TextCell
{
public PickerListCell (PickerPage myPage)
{
var moreAction = new MenuItem { Text = App.Translate ("Edit") };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
var option = (PickerListPage.OptionListItem)mi.CommandParameter;
var recId = new Guid (option.Value);
myPage.OnEditAction();
};
ContextActions.Add (moreAction);
}
}
So, in your page:
public class PickerPage : ContentPage
{
ListView listView { get; set; }
public PickerPage (OptionListItem [] items)
{
listView = new ListView () ;
Content = new StackLayout {
Children = { listView }
};
var cell = new DataTemplate(() => {return new PickerListCell(this); });
cell.SetBinding (PickerListCell.TextProperty, "Caption");
cell.SetBinding (PickerListCell.CommandParameterProperty, "Value");
listView.ItemTemplate = cell;
listView.ItemsSource = items;
}
void OnEditAction (object sender, EventArgs e)
{
var cell = (sender as Xamarin.Forms.MenuItem).BindingContext as PickerListCell;
await Navigation.PushAsync (new RecordEditPage (recId), true);
}
}
Ok, so with the help of some posts, specifically this one https://forums.xamarin.com/discussion/27881/best-practive-mvvm-navigation-when-command-is-not-available, I came to the following solution, though I'm not perfectly satisfied with the way it looks.
My custom cell now announces when a command is being executed using MessagingCenter:
public class PickerListCell : TextCell
{
public PickerListCell ()
{
var moreAction = new MenuItem { Text = App.Translate ("Edit") };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
var option = (PickerListPage.OptionListItem)mi.CommandParameter;
var recId = new Guid (option.Value);
// HERE I send a request to open a new page. This looks a
// bit crappy with a magic string. It will be replaced with a constant or enum
MessagingCenter.Send<OptionListItem, Guid> (this, "PushPage", recId);
};
ContextActions.Add (moreAction);
}
}
And in my PickerPage constructor I added this subscription to the Messaging service:
MessagingCenter.Subscribe<OptionListItem, Guid> (this, "PushPage", (sender, recId) => {
Navigation.PushAsync (new RecordEditPage (recId), true);
});
All this works just find, but I'm not sure if this is the way it was intended to. I feel like the binding should be able to solve this without the Messaging Service, but I can't find out how to bind to a method on the page, only to a model, and I don't want to pollute my model with methods that have dependencies on XF.
I am trying to implement instant search functionality using edittext.I have just binded the json array response to listview and added edittext at top of listview and trying to filter or search data in listview as user starts to type in edittext below code is used.Please help me. Any kind of suggestion,guidence and help is appreciated.
MainActivity.cs
SetContentView(Resource.Layout.HomeScreen);
tableItems = new List<TableItem>();
var client = new RestClient("http://azurewebsites.net/");
var request = new RestRequest("Service/regionSearch", Method.POST);
request.RequestFormat = DataFormat.Json;
tableItems = client.Execute<List<TableItem>>(request).Data;
listView.Adapter = new HomeScreenAdapter(this, tableItems);
region = FindViewById<TextView> (Resource.Id.viewtext);
area= FindViewById<TextView> (Resource.Id.viewtext2);
_filterText = FindViewById<EditText>(Resource.Id.search);
listView = FindViewById<ListView>(Resource.Id.listView);
_filterText.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
// filter on text changed
var searchTerm = _filterText.Text;
};
listView.ItemClick += OnListItemClick;
}
protected void OnListItemClick(object sender, Android.Widget.AdapterView.ItemClickEventArgs e)
{
var listView = sender as ListView;
var t = tableItems[e.Position];
// var clickedTableItem = listView.Adapter[e.Position];
Android.Widget.Toast.MakeText(this, clickedTableItem.DDLValue, Android.Widget.ToastLength.Short).Show();
}
HomeScreenAdapter.cs
public class HomeScreenAdapter : BaseAdapter<TableItem> {
List<TableItem> items;
Activity context;
public HomeScreenAdapter(Activity context, List<TableItem> items)
: base()
{
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override TableItem this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
// TableItem item = items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.DDLValue;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.areaMsg;
return view;
}
}
It looks like you're pretty close. The last step is to use the searchTerm to filter out the results in tableItems. The easiest way to do this is to simply create a new HomeScreenAdapter with the filtered list, and set that as the ListView.Adapter. Check out this example code that implements: getting the search text, filtering all of your TableItem instances, and then giving the ListView a new Adapter.
_filterText.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
// filter on text changed
var searchTerm = _filterText.Text;
var updatedTableItems = tableItems.Where(
// TODO Fill in your search, for example:
tableItem => tableItem.Msg.Contains(searchTerm) ||
tableItem.DDLValue.Contains(searchTerm)
).ToList();
var filteredResultsAdapter = new HomeScreenAdapter(this, updatedTableItems);
listView.Adapter = filteredResultsAdapter;
};
Notice the TODO inside of the Where clause. I have no idea how you want to search on your TableItem but once you write your Where clause, this should do what you want.
It looks like your TableItem class is something like this (for reference):
public class TableItem {
public int Id {get; set;}
public string DDLValue {get; set;}
public string Msg {get; set;}
public int Status {get; set;}
}
I want add search logic for my application (IOS8). I have simple MvxTableViewController and display my data by UITableViewSource. Here is:
...controller:
MvxViewFor(typeof(MainViewModel))]
partial class MainController : MvxTableViewController
{
public MainController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
// make background trasnsparent page
this.View.BackgroundColor = UIColor.Clear;
this.TableView.BackgroundColor = UIColor.Clear;
this.NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
this.SetBackground ();
(this.DataContext as MainViewModel).PropertyChanged += this.ViewModelPropertyChanged;
}
private void SetBackground()
{
// set blured bg image
}
private void ViewModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var viewModel = this.ViewModel as MainViewModel;
if (e.PropertyName == "Title")
{
this.Title = viewModel.Title;
}
else if (e.PropertyName == "Topics")
{
var tableSource = new TopicTableViewSource(viewModel.Topics);
tableSource.TappedCommand = viewModel.NavigateToChildrenPageCommand;
this.TableView.Source = tableSource;
this.TableView.ReloadData();
}
}
I read about search in IOS and choosed UISearchController for IOS8 app. But I don't understand, how I can add this controller to my view :(
I found sample from Xamarin (TableSearch) - but they don't use UITableViewSource and I don't understand what I should do with this.
I tried add controller:
this.searchController = new UISearchController (this.searchTableController)
{
WeakDelegate = this,
DimsBackgroundDuringPresentation = false,
WeakSearchResultsUpdater = this,
};
this.searchController.SearchBar.SizeToFit ();
this.TableView.TableHeaderView = searchController.SearchBar;
this.TableView.WeakDelegate = this;
this.searchController.SearchBar.WeakDelegate = this;
what should I do in this.searchTableController? Do I need move my display logic there?
Yes. The "searchTableController" should be responsible for the presentation of search results.
Here is the test project (native, not xmarin) which help you understand.
The searchController manages a "searchBar" and "searchResultPresenter". His not need add to a view-hierarchy of the carrier controller. When user starts typing a text in the "searchBar" the "SearchController" automatically shows your SearchResultPresenter for you.
Steps:
1) Instantiate search controller with the SearchResultsPresenterController.
2) When user inputs text in the search-bar you should invoke a your own service for the search. Below a sample of code..
#pragma mark - UISearchResultsUpdating
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
if (searchString.length > 1)
{
// TODO - call your service for the search by string
// this may be async or sync
// When a data was found - set it to presenter
[self.searchResultPresenter dataFound:<found data>];
}
}
3) In the search presenter need to reload a table in the method "dataFound:"
- (void)dataFound:(NSArray *)searchResults
{
_searchResults = searchResults;
[self.tableView reloadData];
}
Here are some advice on how to use the UISearchController with Xamarin.iOS.
Create a new class for the results table view subclassing UITableViewSource. This is gonna be the view responsible of displaying the results. You need to make the items list of that table view public.
public List<string> SearchedItems { get; set; }
In your main UIViewController, create your UISearchController and pass your result table view as an argument. I added some extra setup.
public UISearchController SearchController { get; set; }
public override void ViewDidLoad ()
{
SearchController = new UISearchController (resultsTableController) {
WeakDelegate = this,
DimsBackgroundDuringPresentation = false,
WeakSearchResultsUpdater = this,
};
SearchController.SearchBar.SizeToFit ();
SearchController.SearchBar.WeakDelegate = this;
SearchController.HidesNavigationBarDuringPresentation = false;
DefinesPresentationContext = true;
}
The best way to add the search bar to your UI in term of user experience, in my opinion, is to add it as a NavigationItem to a NavigationBarController.
NavigationItem.TitleView = SearchController.SearchBar;
Add methods to perform the search in the main UIViewController:
[Export ("updateSearchResultsForSearchController:")]
public virtual void UpdateSearchResultsForSearchController (UISearchController searchController)
{
var tableController = (UITableViewController)searchController.SearchResultsController;
var resultsSource = (ResultsTableSource)tableController.TableView.Source;
resultsSource.SearchedItems = PerformSearch (searchController.SearchBar.Text);
tableController.TableView.ReloadData ();
}
static List<string> PerformSearch (string searchString)
{
// Return a list of elements that correspond to the search or
// parse an existing list.
}
I really hope this will help you, good luck.
Hello my main issue is how to use MKAnnotationView to set a custom pin image for all my coordinate points.
For reference, I've went ahead and hardcoded values that I will normally be calling down from a json webservice call.
Heres an example of a hardcoded trails:
CLLocationCoordinate2D[] trail1 = new CLLocationCoordinate2D[]{
new CLLocationCoordinate2D(10.74812, -97.330277),
new CLLocationCoordinate2D(10.74501, -97.350277),
new CLLocationCoordinate2D(10.74912, -97.340277),
};
CLLocationCoordinate2D[] trail2 = new CLLocationCoordinate2D[]{
new CLLocationCoordinate2D(10.84812, -97.331277),
new CLLocationCoordinate2D(10.94501, -97.352277),
new CLLocationCoordinate2D(10.14912, -97.343277),
new CLLocationCoordinate2D(10.12912, -97.313277),
};
mapview.AddAnnotation (new SampleMapAnnotation (trail1));
Right now I am using MKAnnotation but realized I need to use the MKAnnotationView for custom image pins.
public class SampleMapAnnotation : MKAnnotation
{
string _title;
public SampleMapAnnotation (CLLocationCoordinate2D coordinate)
{
Coordinate = coordinate;
_title = "Sample";
}
public override CLLocationCoordinate2D Coordinate { get; set; }
public override string Title
{
get {
return _title;
}
}
}
Have a look at the MapCallout sample from Xamarin. This is a C# port from the Objective-C sample by Apple. It will show you how to create image-based annotations and show them on a map.