Customizing the custom picker in Xamarin - xamarin

I hope everyone is doing great. Can someone help me on how can I remove the 'cancel' and 'Ok' buttons and allow/raise an event selection if I release the mouse on the item on the screen, Secondly I need help with changing the color of the borderlines and background color? I will appreciate your help thanks.
Picker :
public class BorderlessPickerRenderer : PickerRenderer
{
public static void Init() { }
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
Control.Background = Android.Graphics.Color.Rgb();
string fontFamily = e.NewElement?.FontFamily;
var layoutParams = new MarginLayoutParams(Control.LayoutParameters);
layoutParams.SetMargins(0, 0, 0, 0);
LayoutParameters = layoutParams;
Control.LayoutParameters = layoutParams;
Control.SetPadding(0, 0, 0, 0);
SetPadding(0, 0, 0, 0);
}
}
}

You could use Custon Remderer to define a custom Dialog.
how can I remove the 'cancel' and 'Ok' buttons and allow/raise an event selection if I release the mouse on the item on the screen,
The AlertDialog provides SetNegativeButton event to set the cancel and Ok button. Remove both in the view would be okay. The custom view is a listview. You could use the ItemClick of ListView.
Secondly I need help with changing the color of the borderlines and background color?
You could set the background color of the dialog to change. Add the android:divider to set the borderline color. And add the android:dividerHeight to set the borderline height.
Custom Renderer:
[assembly: ExportRenderer(typeof(Picker), typeof(BorderlessPickerRenderer))]
namespace App15.Droid
{
public class BorderlessPickerRenderer : PickerRenderer
{
AlertDialog listDialog;
string[] items;
public BorderlessPickerRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Click += Control_Click1; ;
}
}
private void Control_Click1(object sender, EventArgs e)
{
Picker model = Element;
items = model.Items.ToArray();
AlertDialog.Builder builder = new AlertDialog.Builder(this.Context);
builder.SetTitle(model.Title ?? "");
//builder.SetNegativeButton("Cancel", (s, a) =>
//{
// Control?.ClearFocus();
// builder = null;
//});
Android.Views.View view = LayoutInflater.From(this.Context).Inflate(Resource.Layout.listview, null);
Android.Widget.ListView listView = view.FindViewById<Android.Widget.ListView>(Resource.Id.listView1);
MyAdapter myAdapter = new MyAdapter(items, Element.SelectedIndex);
listView.Adapter = myAdapter;
listView.ItemClick += ListView_ItemClick;
builder.SetView(view);
listDialog = builder.Create();
listDialog.Window.DecorView.SetBackgroundColor(Android.Graphics.Color.Pink); // set the dialog background color
listDialog.Show();
//Android.Widget.Button button = listDialog.GetButton((int)DialogButtonType.Negative);
//button.Text = "Cancel";
//button.Click += Button_Click;
//button.SetTextColor(Android.Graphics.Color.Blue); // set the button bottom color
}
//private void Button_Click(object sender, EventArgs e)
//{
// listDialog.Dismiss();
// listDialog = null;
//}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Control.Text = items[e.Position];
Element.SelectedIndex = e.Position;
Console.WriteLine(items[e.Position]);
listDialog.Dismiss();
listDialog = null;
}
class MyAdapter : BaseAdapter
{
private string[] items;
private int selectedIndex;
public MyAdapter(string[] items)
{
this.items = items;
}
public MyAdapter(string[] items, int selectedIndex) : this(items)
{
this.selectedIndex = selectedIndex;
}
public override int Count => items.Length;
public override Java.Lang.Object GetItem(int position)
{
return items[position];
}
public override long GetItemId(int position)
{
return position;
}
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.listview_item, null);
}
TextView textView = convertView.FindViewById<TextView>(Resource.Id.textView1);
textView.Text = items[position];
return convertView;
}
}
}
}
Xaml:
<Picker x:Name="picker" Title="Title" VerticalOptions="CenterAndExpand" >
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Option 1</x:String>
<x:String>Option 2</x:String>
<x:String>Option 3</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
listview.xml: You could creat in your Resources/layout in android project.
<?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">
<ListView
android:id="#+id/listView1"
android:divider="#android:color/holo_green_light"
android:dividerHeight="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
listview_item.xml : You could creat in your Resources/layout in android project.
<?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">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

Related

the view is invisible when Drop

I Create A Custom View named ScrollView
The ability of this view is just like its name
this view of children include only Label,
And support scroll and click,even drop
In actual use,scrolling and clicking works well,dropping was too
but the Label will invisible when drop
this label still occupy the layout,just invisible
the drop func will still execute when i drop once again in that invisible label
I execute apps on Android
ScrollPicker of XAML:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DebugTest.MyView.ApplyView.ScrollPicker">
<ContentView.Content>
<ScrollView x:Name="ScrollView" x:FieldModifier="Public">
<StackLayout x:Name="MainView" x:FieldModifier="Public">
</StackLayout>
</ScrollView>
</ContentView.Content>
</ContentView>
And C# Code
public partial class ScrollPicker : ContentView
{
public static readonly BindableProperty OrientationProperty = BindableProperty.Create("Orientation", typeof(StackOrientation), typeof(ScrollPicker), StackOrientation.Vertical, propertyChanged: Orientation_Changed);
public static readonly BindableProperty ItemSourceProperty = BindableProperty.Create("ItemSource", typeof(List<string>), typeof(ScrollPicker), propertyChanged: ItemSource_Changed);
private static void Orientation_Changed(BindableObject bindable, object oldValue, object newValue)
{
if(((StackOrientation)newValue) == StackOrientation.Horizontal)
{
((ScrollPicker)bindable).ScrollView.Orientation = ScrollOrientation.Horizontal;
((ScrollPicker)bindable).MainView.Orientation = StackOrientation.Horizontal;
}
else
{
((ScrollPicker)bindable).ScrollView.Orientation = ScrollOrientation.Vertical;
((ScrollPicker)bindable).MainView.Orientation = StackOrientation.Vertical;
}
}
private static void ItemSource_Changed(BindableObject bindable, object oldValue, object newValue)
{
var view = ((ScrollPicker)bindable);
view.ItemSourceList = (List<string>)newValue;
view.ResetLabelList();
}
public StackOrientation Orientation
{
get { return (StackOrientation)GetValue(ItemSourceProperty); }
set { SetValue(ItemSourceProperty, value); }
}
public List<string> ItemSource
{
get { return (List<string>)GetValue(ItemSourceProperty); }
set { SetValue(ItemSourceProperty, value); }
}
public DropGestureRecognizer DropGR;
public event EventHandler<IndexArgs> ItemClickEvent;
public event EventHandler<IndexArgs> DropEvent;
public List<string> ItemSourceList;
public List<Label> LabelList = new List<Label>();
public ScrollPicker()
{
InitializeComponent();
ItemClickEvent += ScrollPicker_ItemClickEvent;
DropEvent += ScrollPicker_DropEvent;
}
private void ScrollPicker_DropEvent(object sender, EventArgs e)
{
}
private void CE_Click(Element obj)
{
if(LabelList != null && LabelList.Count != 0)
{
if(LabelList.Exists(label => label == obj))
{
int index = LabelList.IndexOf((Label)obj);
ItemClickEvent.Invoke(obj, new IndexArgs(index));
}
}
}
private void ScrollPicker_ItemClickEvent(object sender, EventArgs e)
{
}
private void ResetLabelList()
{
MainView.Children.Clear();
LabelList.Clear();
if (ItemSourceList != null && ItemSourceList.Count != 0)
{
for(int i=0;i< ItemSourceList.Count;i++)
{
//创建Label
Label temp = CreateSubView(ItemSourceList[i]);
//绑定CE
ClickEffect CE = new ClickEffect();
CE.Click += CE_Click;
Global.ClickEffect_BindClickEffect(temp, CE);
//添加Drop
DropGR = new DropGestureRecognizer();
DropGR.DragOver += DropGR_DragOver;
DropGR.DragLeave += DropGR_DragLeave;
DropGR.Drop += DropGR_Drop;
temp.GestureRecognizers.Add(DropGR);
//添加视图
LabelList.Add(temp);
MainView.Children.Add(temp);
if (i == 0) temp.Opacity = 0.1;
}
}
}
private void DropGR_DragOver(object sender, DragEventArgs e)
{
}
private void DropGR_DragLeave(object sender, DragEventArgs e)
{
}
private void DropGR_Drop(object sender, DropEventArgs e)
{
var view = (sender as GestureRecognizer).Parent as View;
int index = MainView.Children.IndexOf(view);
DropEvent.Invoke(view, new IndexArgs(index));
}
private Label CreateSubView(string text)
{
Label label = new Label()
{
Text = text,
FontSize = 20,
WidthRequest = 75,
VerticalTextAlignment = TextAlignment.Start,
HorizontalTextAlignment = TextAlignment.Start,
};
return label;
}
}
public abstract partial class ScrollPickerItemView : ContentView
{
}
public class IndexArgs: EventArgs
{
public int Index;
public IndexArgs(int index =0)
{
Index = index;
}
}
public enum ScrollPickerOrientation
{
Vertical,
Horizontal
}
How Use In Page:
......
<AbsoluteLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,0.1" BackgroundColor="#66CCFF">
<Label AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,0.2,1"
Text="Project:" FontSize="Large" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
<applyview:ScrollPicker x:Name="ProjectPicker" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="1,0,0.8,1" Orientation="Horizontal"
ItemClickEvent="ProjectPicker_ItemClickEvent" DropEvent="ProjectPicker_DropEvent"/>
</AbsoluteLayout>
I don't know how to solve this problem. Can someone help me?
I'm afraid I've found the problem
I added a PropertyChanged callback function to each label. I was surprised to find that when I triggered the drop function, the text of the label changed and became Empty
That's why he disappeared!!!
I'm very sorry, but it's a shame
Although the problem has been solved, I still don't know why the text of label becomes null when I trigger the drop function

How to display image with text in 2 columns GridView

How to display image with text ( like name, price.. etc )
Below code only display images with no text.
--- UI :
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="230dp"
android:numColumns="2"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:background="#ffffff"
android:stretchMode="columnWidth"
android:gravity="center" />
-- Code:
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 ModSpforce
{
class ImageAdapter : BaseAdapter
{
Context context;
public ImageAdapter(Context c)
{
context = c;
}
public override int Count
{
get { return thumbIds.Length; }
}
public override Java.Lang.Object GetItem(int position)
{
return null;
}
public override long GetItemId(int position)
{
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public override View GetView(int position, View convertView, ViewGroup parent)
{
ImageView imageView;
if (convertView == null)
{ // if it's not recycled, initialize some attributes
imageView = new ImageView(context);
imageView.LayoutParameters = new GridView.LayoutParams(200, 200);
imageView.SetScaleType(ImageView.ScaleType.CenterCrop);
imageView.SetPadding(3, 3, 3, 3);
}
else
{
imageView = (ImageView)convertView;
}
imageView.SetImageResource(thumbIds[position]);
return imageView;
}
// references to our images
int[] thumbIds = {
Resource.Drawable.sample_2, Resource.Drawable.sample_3,
Resource.Drawable.sample_4, Resource.Drawable.sample_5,
Resource.Drawable.sample_6, Resource.Drawable.sample_7,
Resource.Drawable.sample_0, Resource.Drawable.sample_1,
Resource.Drawable.sample_2, Resource.Drawable.sample_3,
Resource.Drawable.sample_4, Resource.Drawable.sample_5,
Resource.Drawable.sample_6, Resource.Drawable.sample_7,
Resource.Drawable.sample_0, Resource.Drawable.sample_1,
Resource.Drawable.sample_2, Resource.Drawable.sample_3,
Resource.Drawable.sample_4, Resource.Drawable.sample_5,
Resource.Drawable.sample_6, Resource.Drawable.sample_7
};
}
}
You can inflate your GridView's cell in the GetView method of your adapter, so you can simply design your item's template in xml.
For example:
Code behind of your GridView:
public ObservableCollection<MyItemModel> items = new ObservableCollection<MyItemModel>();
public MyGridViewAdapter adapter;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
//add your items here.
for (int i = 0; i < 50; i++)
{
items.Add(new MyItemModel { ImageSource = Resource.Drawable.Pika, Name = "Name " + i });
}
adapter = new MyGridViewAdapter(this, items);
GridView gv = FindViewById<GridView>(Resource.Id.gridview);
gv.Adapter = adapter;
}
MyItemModel is for image resource and name of this image, like this:
public class MyItemModel
{
public string Name { get; set; }
public int ImageSource { get; set; }
}
And MyGridViewAdapter is like this:
public class MyGridViewAdapter : BaseAdapter<MyItemModel>
{
private ObservableCollection<MyItemModel> items;
private Activity context;
public MyGridViewAdapter(Activity context, ObservableCollection<MyItemModel> items)
{
this.items = items;
this.context = context;
}
public override MyItemModel this[int position]
{
get
{
return items[position];
}
}
public override int Count
{
get
{
return items.Count;
}
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
{
view = context.LayoutInflater.Inflate(Resource.Layout.MyGridViewCell, null);
}
var image = view.FindViewById<ImageView>(Resource.Id.image);
image.SetImageResource(items[position].ImageSource);
var name = view.FindViewById<TextView>(Resource.Id.name);
name.Text = items[position].Name;
return view;
}
}
Finally the layout of MyGridViewCell is like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView android:id="#+id/image"
android:layout_height="200dp"
android:layout_width="200dp" />
<TextView android:id="#+id/name"
android:layout_height="wrap_content"
android:layout_width="200dp"
android:textColor="#android:color/holo_blue_light" />
</LinearLayout>

Loading an image URL from Xamarin Forms PCL to PageRenderer in Android project fails

I am passing an URL string of an image from a website, these images appear in a listview on the PCL project, the URL of the image passes fine to the Android Custom Renderer, but loading the image with MonoDroidToolKit fails with the following error:
Unhandled Exception:
System.ArgumentNullException: Value cannot be null.
Parameter name: key
From PCL(passing attachment information):
public partial class ImageViewPage : ContentPage
{
public ImageViewPage(Attachment imageItem)
{
if (imageItem == null)
throw new ArgumentNullException();
BindingContext = imageItem;
_imageItem = imageItem.url;
InitializeComponent();
}
public string _imageItem { get; private set; }
}
In Android Custom Renderer:
[assembly: ExportRenderer(typeof(ImageViewPage),typeof(ImageViewRenderer))]
namespace BibleCodesApp.Droid
{
public class ImageViewRenderer : PageRenderer
{
global::Android.Views.View view;
ImageLoader imageLoader;
Activity activity;
ImageView imageView;
private string imageItem
{
get
{
var imageViewPage = Element as ImageViewPage;
return imageViewPage == null
? null
: imageViewPage._imageItem;
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Page>e)
{
base.OnElementChanged(e);
activity = this.Context as Activity;
view = activity.LayoutInflater.Inflate
(Resource.Layout.ImageView,this,false);
imageLoader = new ImageLoader(activity, 512);
imageView = FindViewById<ImageView>(Resource.Id.image_view);
imageLoader.DisplayImage(imageItem, imageView, -1);
}
}
}
The layout in Android:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<BibleCodesApp.Droid.ScaleImageView
android:id="#+id/image_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:adjustViewBounds="true" />
</LinearLayout>
</RelativeLayout>
I see it now:
You are inflating your new view, but never actually adding it to the page!
You should call
this.ViewGroup.AddView(view);
after your imageLoader.DisplayImage call at the end of OnElementChanged
This is the correct solution:
[assembly: ExportRenderer(typeof(ZoomImage), typeof(ZoomImageRenderer))]
namespace WPAppTemplate.Droid
{
public class ZoomImageRenderer : ImageRenderer
{
private ZoomImage _zoomImage;
private ScaleImageView _scaleImage;
protected async override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_zoomImage = (ZoomImage)e.NewElement;
// create the scale image and set it as the native control so it's available
_scaleImage = new ScaleImageView(Context, null);
_scaleImage.ZoomImage = _zoomImage;
SetNativeControl(_scaleImage);
await LoadImage();
}
}
protected async override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ZoomImage.AspectProperty.PropertyName
|| e.PropertyName == ZoomImage.HeightProperty.PropertyName
|| e.PropertyName == ZoomImage.WidthProperty.PropertyName)
{
_scaleImage.ZoomToAspect();
}
else if (e.PropertyName == ZoomImage.SourceProperty.PropertyName)
{
await LoadImage();
_scaleImage.ZoomToAspect();
}
else if (e.PropertyName == ZoomImage.CurrentZoomProperty.PropertyName)
{
_scaleImage.ZoomFromCurrentZoom();
}
else if (e.PropertyName == ZoomImage.MaxZoomProperty.PropertyName)
{
_scaleImage.UpdateMaxScaleFromZoomImage();
}
else if (e.PropertyName == ZoomImage.MinZoomProperty.PropertyName)
{
_scaleImage.UpdateMinScaleFromZoomImage();
}
}
private async Task LoadImage()
{
var image = await (new ImageLoaderSourceHandler()).LoadImageAsync(_zoomImage.Source, Context);
try
{
if (image != null && image.ByteCount > 0)
_scaleImage.SetImageBitmap(image);
}
catch (Exception e)
{
// catch an image loading failure
Console.WriteLine($"Unable to load bitmap. Exception: {e.Message}");
}
}
}

SeekBar.IOnSeekBarChangeListener, seekBar can't run

A callback that notifies clients when the progress level has been changed. This includes changes that were initiated by the user through a touch gesture or arrow key/trackball as well as changes that were initiated programmatically.
Inside OnCreate
public class AudioPlayer : Activity,SeekBar.IOnSeekBarChangeListener
seekBar.SetOnSeekBarChangeListener (this);
seekBar.ProgressChanged+= (object sender, SeekBar.ProgressChangedEventArgs e) => {
int progress=(int)(utils.getProgressPercentage(player.CurrentPosition,player.Duration));
seekBar.Progress = progress;
};
public void OnStartTrackingTouch(SeekBar seekBar) {}
public void OnStopTrackingTouch(SeekBar seekBar) {}
public int getProgressPercentage(int currentDuration, int totalDuration)
{
int percentage;
int currentSeconds = (int)(currentDuration / 1000);
int totalSeconds = (int)(totalDuration / 1000);
//calculating percentage
percentage = (((int)currentSeconds) / totalSeconds) * 100;
return percentage;
}
While tracks are playing, seekBar still stops.
Think you want to do is create a timer which will update the seekBar like this:
Activity:
using System;
using Android.App;
using Android.Widget;
using Android.OS;
using Java.Lang;
using Android.Content;
using Android.Graphics.Drawables;
using Java.Util;
namespace PlayVideo
{
[Activity (Label = "PlayVideo", MainLauncher = true)]
public class Activity1 : Activity
{
VideoView videoView;
SeekBar seekBar;
System.Timers.Timer timer;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
videoView = FindViewById<VideoView> (Resource.Id.SampleVideoView);
videoView.SetMediaController(new MediaController(this));
videoView.SetVideoPath ($"android.resource://{PackageName}/{Resource.Raw.output2}");
videoView.Start ();
seekBar = FindViewById<SeekBar> (Resource.Id.seekBar);
seekBar.Max = videoView.Duration;
seekBar.StartTrackingTouch += (object sender, SeekBar.StartTrackingTouchEventArgs e) =>
{
timer.Enabled = false;
};
seekBar.StopTrackingTouch += (object sender, SeekBar.StopTrackingTouchEventArgs e) =>
{
videoView.SeekTo (e.SeekBar.Progress);
timer.Enabled = true;
};
UpdateProgressBar ();
}
private void UpdateProgressBar() {
timer = new System.Timers.Timer();
timer.Interval = 100;
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e)
{
seekBar.Progress = videoView.CurrentPosition;
seekBar.Max = videoView.Duration;
}
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<VideoView
android:id="#+id/SampleVideoView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<SeekBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/seekBar" />
</LinearLayout>
it will look like this:

How to make a Single Row Horizontal ListView/List?

What I want to do is Create a Single Row Listview/List with a image and text is this is what i have right now
I have Changed the numColumns to 1 but how do I change it so it is Horizontal and Scrollable? the image should be one top and the text should be below it?
This is the Layout
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="1"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
Single Grid Item
<?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="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="centerCrop"
android:id="#+id/my_image_vieww" />
<TextView
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/my_text_view" />
</LinearLayout>
Main Activity
var gridview = FindViewById<GridView> (Resource.Id.gridview);
gridview.Adapter = new ImageAdapter (this);
gridview.ItemClick += delegate (object sender, AdapterView.ItemClickEventArgs args) {
Toast.MakeText (this, args.Position.ToString (), ToastLength.Short).Show ();
};
public class ImageAdapter : BaseAdapter
{
Context context;
public ImageAdapter (Context c)
{
context = c;
}
public override int Count {
get { return thumbIds.Length; }
}
public override Java.Lang.Object GetItem (int position)
{
return null;
}
public override long GetItemId (int position)
{
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public override View GetView (int position, View convertView, ViewGroup parent)
{
ImageView imageView;
View view;
if (convertView == null) { // if it's not recycled, initialize some attributes
view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.my_grid_row, parent, false);
} else {
view = convertView;
}
var imageView2 = view.FindViewById<ImageView>(Resource.Id.my_image_vieww);
imageView2.SetImageResource (thumbIds[position]);
var textView = view.FindViewById<TextView>(Resource.Id.my_text_view);
textView.Text = "Text to Display";
return view;
}
}
Please Dont user horizontal list view.
There is predefined android controll to achieve this. View Pager
Sample Code:
var _viewPager = view.FindViewById<ViewPager>(Resource.Id.viewPager);
var _viewPageIndicatorCircle = view.FindViewById<CirclePageIndicator>(Resource.Id.viewPageIndicator);
_viewPager.Adapter = new TestFragmentAdapter(fm);
_viewPageIndicatorCircle.SetViewPager(_viewPager);
public class TestFragmentAdapter : FragmentPagerAdapter
{
public TestFragmentAdapter(Android.Support.V4.App.FragmentManager fm)
: base(fm)
{
}
public override Android.Support.V4.App.Fragment GetItem(int position)
{
return new TestFragment();
}
public override int Count
{
get
{
return 5;
}
}
}
class TestFragment : Android.Support.V4.App.Fragment
{
public TestFragment()
{
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = inflater.Inflate(Resource.Layout.MyViewPager , container, false);
return view;
}
}
Viewpager.xml
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="209.6dp" />
If you have any queries please feel free to ask me

Resources