I want to place a pin whenever the screen is touched using MKMapView inside the method ViewDidLoad()
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
mapView.ShowsUserLocation = true;
MKUserLocation currentLocation = mapView.UserLocation;
}
How would I go about doing this? The Xamarindocs are specific about placing an image, but how do I place a pin? Isn't it built into MKMapView?
You add an MKAnnotation to the Map
class BasicMapAnnotation : MKAnnotation{
public override CLLocationCoordinate2D Coordinate {get;set;}
string title, subtitle;
public override string Title { get{ return title; }}
public override string Subtitle { get{ return subtitle; }}
public BasicMapAnnotation (CLLocationCoordinate2D coordinate, string title, string subtitle) {
this.Coordinate = coordinate;
this.title = title;
this.subtitle = subtitle;
}
}
var annotation = new BasicMapAnnotation (new CLLocationCoordinate2D(48.857,2.351), "Paris", "City of Light");
mapView.AddAnnotation(annotation);
Related
hello everyone, I am kind of new using android studio and I am working on my school project. I need to use RecycleVie wand I tried making it but without success.
I use a Object class caled Task whcih have 3 propeties to be shown on the layout but I don't know where is my mistake. the rows which shown as problems are in bold. I will be glad if anyone can help me!
my Object class:
public class Task {
private String material;
private String day;
private String month;
public Task (String material,String day,String month)
{
this.material = material;
this.day = day;
this.month = month;
}
public String getMaterial() {
return material;
}
public void setMaterial(String material) {
this.material = material;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
}
the Adapter Code:
public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerViewAdapter.ViewHolder> {
private Context mCtx;
private List<Task> tList;
// data is passed into the constructor
public HomeRecyclerViewAdapter(Context mCtx, List<Task> tList) {
this.mCtx = mCtx;
this.tList = tList;
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvText, tvDateDay, tvDateMonth;
public ViewHolder(View itemView) {
super(itemView);
tvText = itemView.findViewById(R.id.tvText);
tvDateDay = itemView.findViewById(R.id.tvDateDay);
tvDateMonth = itemView.findViewById(R.id.tvDateMonth);
}
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//inflating and returning our view holder
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.home_recyclerview_row, null);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Task task = tList.get(position);
**holder.tvText.setText(task.getMaterial());**
}
// allows clicks events to be caught
#Override
public int getItemCount() {
return tList.size();
}
}
and the main code:
public class HomeScreen_activity extends AppCompatActivity implements View.OnClickListener {
List<Task> tList;
RecyclerView homercy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.home_screen_layout);
homercy = (RecyclerView) findViewById(R.id.homercy);
homercy.setHasFixedSize(true);
homercy.setLayoutManager(new LinearLayoutManager(this));
// set up the RecyclerView
RecyclerView recyclerView = findViewById(R.id.homercy);
tList = new ArrayList<Task>();
Task t1 = new Task("test","12","05");
tList.add(t1);
**HomeRecyclerViewAdapter adapter = new HomeRecyclerViewAdapter(this,tList);**
recyclerView.setAdapter(adapter);
}
Maybe in onCreateViewHolder(), you must do this:
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_recyclerview_row, parent, false);
return new ViewHolder(view);
}
I'm trying to use UICollectionView but I can't find any samples that I can take advantage of. I needed the UICollectionView by code (without using swift/storyboard/forms). Could you give me a really simple example? For example 2 lines with 2 columns please? Basic stuff just to try to understand how I can implement it.
Thank you
You can refer to Collection Views in Xamarin.iOS doc to check how to use Collection View with Code .And here I will show a sample code to explain how to implement it .
Could you give me a really simple example? For example 2 lines with 2 columns please?
First , need to create a GridLayout :
public class GridLayout : UICollectionViewFlowLayout
{
public GridLayout ()
{
}
public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
{
return true;
}
public override UICollectionViewLayoutAttributes LayoutAttributesForItem (NSIndexPath path)
{
return base.LayoutAttributesForItem (path);
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
{
return base.LayoutAttributesForElementsInRect (rect);
}
}
Then you can init the Collection View in ViewDidLoad :
static NSString animalCellId = new NSString("AnimalCell");
List<IAnimal> animals;
animals = new List<IAnimal>();
for (int i = 0; i < 2; i++)
{
animals.Add(new Monkey());
}
// Perform any additional setup after loading the view, typically from a nib.
UICollectionView collectionView = new UICollectionView(new CGRect(0, 0, UIScreen.MainScreen.Bounds.Size.Width, 300), new GridLayout());
collectionView.RegisterClassForCell(typeof(AnimalCell), animalCellId);
collectionView.BackgroundColor = UIColor.Blue;
collectionView.DataSource = new MyCollectionViewDataDelegate(animals);
View.AddSubview(collectionView);
Here you also need to creat a Custom Cell for your needs , this can be modified by yourself :
public class AnimalCell : UICollectionViewCell
{
UIImageView imageView;
[Export("initWithFrame:")]
public AnimalCell(CGRect frame) : base(frame)
{
BackgroundView = new UIView { BackgroundColor = UIColor.Orange };
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.Green };
ContentView.Layer.BorderColor = UIColor.LightGray.CGColor;
ContentView.Layer.BorderWidth = 2.0f;
ContentView.BackgroundColor = UIColor.White;
ContentView.Transform = CGAffineTransform.MakeScale(0.8f, 0.8f);
imageView = new UIImageView(UIImage.FromBundle("placeholder.png"));
imageView.Center = ContentView.Center;
imageView.Transform = CGAffineTransform.MakeScale(0.7f, 0.7f);
ContentView.AddSubview(imageView);
}
public UIImage Image
{
set
{
imageView.Image = value;
}
}
[Export("custom")]
void Custom()
{
// Put all your custom menu behavior code here
Console.WriteLine("custom in the cell");
}
public override bool CanPerform(Selector action, NSObject withSender)
{
if (action == new Selector("custom"))
return true;
else
return false;
}
}
The MyCollectionViewDataDelegate also need to be created:
public class MyCollectionViewDataDelegate : UICollectionViewDataSource
{
private List animals;
public MyCollectionViewDataDelegate(List<IAnimal> animals)
{
this.animals = animals;
}
public override nint NumberOfSections(UICollectionView collectionView)
{
return 2;
}
public override nint GetItemsCount(UICollectionView collectionView, nint section)
{
return animals.Count;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var animalCell = (AnimalCell)collectionView.DequeueReusableCell(animalCellId, indexPath);
var animal = animals[indexPath.Row];
animalCell.Image = animal.Image;
return animalCell;
}
}
You can find that animalCell should be registed when init Collection View .
Then effect :
This is the sample link for reference .
I am collaborating with a designer who styles elements on my Xamarin project storyboard. I have trouble referencing his carefully placed elements in code. All the outlets are created, but in a UICollectionViewCell the UILabels etc are not instantiated. Here is code from a simple test app to demonstrate the problem.
The Xamarin generated code-behind:
[Register ("CardCell")]
partial class CardCell
{
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UILabel txtName { get; set; }
void ReleaseDesignerOutlets ()
{
if (txtName != null) {
txtName.Dispose ();
txtName = null;
}
}
}
My attempt to set the UI properties which causes the crash:
public partial class CardCell : UICollectionViewCell
{
public CardCell (IntPtr handle) : base (handle)
{
}
public void Update(string name)
{
txtName.Text = name; // throws exception here, because textName is null
}
}
The view controller with delegate methods:
public partial class TestCollectionController : UICollectionViewController
{
static NSString cardCellId = new NSString ("cardcell");
string[] cards = new string[] {"Red", "Green", "White", "Blue", "Pink", "Yellow"};
public TestCollectionController (IntPtr handle) : base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
CollectionView.RegisterClassForCell (typeof(CardCell), cardCellId);
}
public override nint NumberOfSections (UICollectionView collectionView)
{
return 1;
}
public override nint GetItemsCount (UICollectionView collectionView, nint section)
{
return (nint)cards.Length;
}
public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
CardCell cell = (CardCell)collectionView.DequeueReusableCell (cardCellId, indexPath);
var card = cards [indexPath.Row];
cell.Update(card);
return cell;
}
}
I have tried both the Xamarin iOS Designer and Xcode's Interface Builder, but it does not make a difference. Any help will be greatly appreciated.
Examples of collection views driven by a storyboard are quite scarce, but I found this one and teased through it meticulously till I discovered that it did not include the call to register a class for the cell. So, remove this line:
CollectionView.RegisterClassForCell (typeof(CardCell), cardCellId);
and suddenly everything works as expected.
I was following this recipe and other examples, which all had the call included, which is only needed when you don't use a storyboard.
I am learning custom views in android.
I made one custom view, with a rectangle and a text. The code of the custom view is:
public class TileGenerator extends View {
// rectangle parameters
private Rect rect = new Rect();
private Paint rectPaint = new Paint();
private Integer rectEndX;
private Integer rectEndY;
private Integer rectStartX;
private Integer rectStartY;
private Integer rectFillColor;
private Float rectTextStartX;
private Float rectTextStartY;
//rectangle text
private String rectText;
private Paint rectTextPaint = new Paint();
public TileGenerator(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void setTileTitleText(String rectText) {
this.rectText = rectText;
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
rectEndX = getrectEndX();
rectEndY = getrectEndY();
rectStartX = getRectStartX();
rectStartY = getRectStartY();
rectTextStartX = rectEndX/4f + rectStartX;
rectTextStartY = 3.5f * rectEndY/4f + rectStartY;
rectTextPaint.setTextSize(rectEndY/8);
rectTextPaint.setColor(Color.BLACK);
rect.set(rectStartX,rectStartY,rectEndX,rectEndY);
rectPaint.setColor(getRectFillColor());
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(rect, rectPaint);
canvas.drawText(rectText,rectTextStartX,rectTextStartY,rectTextPaint );
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
public Integer getrectEndX() {
return rectEndX;
}
public void setrectEndX(Integer rectEndX) {
this.rectEndX = rectEndX;
}
public Integer getrectEndY() {
return rectEndY;
}
public void setrectEndY(Integer rectEndY) {
this.rectEndY = rectEndY;
}
public Integer getRectStartX() {
return rectStartX;
}
public void setRectStartX(Integer rectStartX) {
this.rectStartX = rectStartX;
}
public Integer getRectStartY() {
return rectStartY;
}
public void setRectStartY(Integer rectStartY) {
this.rectStartY = rectStartY;
}
public Integer getRectFillColor() {
return rectFillColor;
}
public void setRectFillColor(Integer rectFillColor) {
this.rectFillColor = rectFillColor;
}
public String getRectText() {
return rectText;
}
}
After that I created an blank activity. I am doing all with JAVA code. No XML. Then I try to add above custom view to a gridview layout. I want to add two custom views with different text in a horizontal gridview. So far my code is as below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GridLayout gridLayout = new GridLayout(this);
// first custom view
CustomRectWithText customRectWithText = new CustomRectWithText(this);
customRectWithText.setRectEndX(200);
customRectWithText.setRectEndY(200);
customRectWithText.setRectStartX(2);
customRectWithText.setRectStartY(2);
customRectWithText.setImage(image);
customRectWithText.setRectText("Text");
customRectWithText.setRectFillColor(Color.BLUE);
gridLayout.addView(customRectWithText);
// second custom view
CustomRectWithText customRectWithText1 = new CustomRectWithText(this);
customRectWithText1.setRectEndX(400);
customRectWithText1.setRectEndY(200);
customRectWithText1.setRectStartX(200 + 5);
customRectWithText1.setRectStartY(2);
customRectWithText1.setTileTitleText("Text 1");
customRectWithText1.setRectFillColor(Color.GREEN);
gridLayout.addView(customRectWithText1);
setContentView(gridLayout);
}
But still I am not getting both of the rectangles in a grid view. Only one rectangle is displayed at a time. In above case only first custom view is displayed.
Where am I doing wrong.
All I want is to make a repetitive rectangle of varying labels of any size inside a grid view.
Is this the way to do it. I mean is there any other way around.
I dont want to use ListItems.
Sorry but i do not have enough repo to comment.
But why dont you make an adapter?
Gridview behaves same as listView.
Use adapter to fill your grid.
This is the proper way to populate listView and gridView also.
I'm experiencing with the UICollectionView(Controller) for the first time. Actually it should be as simple as working with TableViews, it's not though.
Rather than showing all images in a flow (several rows) just the top row is displayed. All the other images are somewhere... scrolling is enabled but nothing happens, no bouncing, no scrolling, ...
And after an orientation change (and back) some more images are visible but they appear randomly. After every orientation change they appear at an other location.
My example should have 7 images.
My properties in IB:
First time:
After rotating (and back):
And my source code to implement the photo gallery.
using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Collections.Generic;
using Xamarin.Media;
using MonoTouch.AssetsLibrary;
using MonoTouch.CoreGraphics;
using System.Diagnostics;
using System.Linq;
using System.Drawing;
namespace B2.Device.iOS
{
public partial class TagesRapportDetailRegieBilderCollectionViewController : UICollectionViewController
{
private const string Album = "Rapport";
public TagesRapportDetailRegieBilderSource Source { get; private set; }
private TagesRapportDetailRegieBilderDelegate _delegate;
public TagesRapportDetailRegieBilderCollectionViewController (IntPtr handle) : base (handle)
{
Source = new TagesRapportDetailRegieBilderSource(this);
_delegate = new TagesRapportDetailRegieBilderDelegate(this);
// Delegate - Muss im konstruktor sein. ViewDidLoad geht nicht!
CollectionView.Delegate = _delegate;
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Cell Klasse registrieren
CollectionView.RegisterClassForCell (typeof(ImageCell), new NSString("imageCell"));
// DataSource
CollectionView.Source = Source;
// Bilder laden
LoadImages();
}
private void LoadImages()
{
Source.Images.Clear();
var assetsLibrary = new ALAssetsLibrary();
assetsLibrary.Enumerate(ALAssetsGroupType.Album, GroupsEnumeration, GroupsEnumerationFailure);
}
private void GroupsEnumeration(ALAssetsGroup group, ref bool stop)
{
if (group != null && group.Name == Album)
{
//notifies the library to keep retrieving groups
stop = false;
//set here what types of assets we want,
//photos, videos or both
group.SetAssetsFilter(ALAssetsFilter.AllPhotos);
//start the asset enumeration
//with ALAssetsGroup's Enumerate method
group.Enumerate(AssetsEnumeration);
CollectionView.ReloadData();
}
}
private void AssetsEnumeration(ALAsset asset, int index, ref bool stop)
{
if (asset != null)
{
//notifies the group to keep retrieving assets
stop = false;
//use the asset here
var image = new UIImage(asset.AspectRatioThumbnail());
Source.Images.Add(image);
}
}
private void GroupsEnumerationFailure(NSError error)
{
if (error != null)
{
new UIAlertView("Zugriff verweigert", error.LocalizedDescription, null, "Schliessen", null).Show();
}
}
}
public class TagesRapportDetailRegieBilderDelegate : UICollectionViewDelegateFlowLayout
{
private TagesRapportDetailRegieBilderCollectionViewController _controller;
public TagesRapportDetailRegieBilderDelegate(TagesRapportDetailRegieBilderCollectionViewController controller)
{
_controller = controller;
}
public override System.Drawing.SizeF GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
{
var size = _controller.Source.Images[indexPath.Row].Size.Width > 0
? _controller.Source.Images[indexPath.Row].Size : new SizeF(100, 100);
size.Width /= 3;
size.Height /= 3;
return size;
}
public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout, int section)
{
return new UIEdgeInsets(50, 20, 50, 20);
}
}
public class TagesRapportDetailRegieBilderSource : UICollectionViewSource
{
private TagesRapportDetailRegieBilderCollectionViewController _controller;
public List<UIImage> Images { get; set; }
public TagesRapportDetailRegieBilderSource(TagesRapportDetailRegieBilderCollectionViewController controller)
{
_controller = controller;
Images = new List<UIImage>();
}
public override int NumberOfSections(UICollectionView collectionView)
{
return 1;
}
public override int GetItemsCount(UICollectionView collectionView, int section)
{
return Images.Count;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = collectionView.DequeueReusableCell(new NSString("imageCell"), indexPath) as ImageCell;
cell.Image = Images[indexPath.Row];
return cell;
}
}
public class ImageCell : UICollectionViewCell
{
UIImageView imageView;
[Export ("initWithFrame:")]
public ImageCell (System.Drawing.RectangleF frame) : base (frame)
{
imageView = new UIImageView(frame);
imageView.AutoresizingMask = ~UIViewAutoresizing.None;
ContentView.AddSubview (imageView);
}
public UIImage Image
{
set
{
imageView.Image = value;
}
}
}
}
If all you want to do is displaying the cells in an uniform grid, overriding GetSizeForItem shouldn't be necessary in the first place. Just configure the cellsize property of your flow layout either in IB or programatically during ViewDidLoad and be done with it.
There's another problem with your code:
group.Enumerate(AssetsEnumeration)
This will run asynchronously. That means:
CollectionView.ReloadData();
Will only cover a small subset of your images. It would be better to issue a ReloadData() when group == null, which indicates that the enumeration is complete.
You could also avoid ReloadData alltogether and call CollectionView.InsertItem() everytime you've added an image. This has the benefit of your items become immediately visible instead of all of them at once after everything has been enumerated - which may take some time (on the device). The downside is that you've got to be careful to not run into this.