I can't populate date from webservice to xamarin android
namespace Printopack
{
[Activity(Label = "Mainlistview", Icon = "#drawable/icon")]
public class Mainlistview : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Mainlistview);
ListView ListView = FindViewById<ListView>(Resource.Id.listView1);
Selling.WebServiceDB ws = new Selling.WebServiceDB();
ws.OrderStatusListCompleted += Ws_OrderStatusListCompleted;
ws.OrderStatusListAsync(Convert.ToString(1));
}
private void Ws_OrderStatusListCompleted(object sender, Selling.OrderStatusListCompletedEventArgs e)
{
ListView ListView = FindViewById<ListView>(Resource.Id.listView1);
string msg = "";
if (e.Result.ToString().Equals("0"))
{
msg = e.Result.ToString();
}
else
{
// full class
List<TableItem> tableItems = new List<TableItem>();
tableItems.Add(new TableItem("" + e.Result, "" + e.Result, Resource.Drawable.Icon));
ListView.Adapter = new HomeScreenAdapter(this, tableItems);
}
}
// adpater manage
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];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.Ticket_News, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);
return view;
}
}
public class TableItem
{
public string Heading;
public string SubHeading;
public int ImageResourceId;
public TableItem(string Heading, string SubHeading, int ImageResourceId)
{
this.Heading = Heading;
this.SubHeading = SubHeading;
this.ImageResourceId = ImageResourceId;
}
}
}
}
I think the error is in this line:
tableItems.Add(new TableItem("" + e.Result, "" + e.Result, Resource.Drawable.Icon));
You're adding the e.Result as one item and I think the Result holds the complete list. You should loop through the entries in the e.Result and call tableItems.Add for each of them.
Similar to this:
foreach (var item in e.Result)
{
tableItems.Add(new TableItem("" + item.Property, "" + item.Property1, Resource.Drawable.Icon));
}
Related
every time i update my screen (change rotation or leave the screen and then go back to it) it doesn't save the updated list and i go back to the default list. thank you in advance <3
MovieActivity:
public class MovieActivity : Activity, ListView.IOnItemClickListener, Android.Views.View.IOnClickListener, ListView.IOnItemLongClickListener
{
public static List<Movie> movieList { get; set; }
MovieAdapter movieAdapter;
ListView lv;
Button btnAdd;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.movie_page);
// Create your application here
btnAdd = FindViewById<Button>(Resource.Id.btnAdd);
Bitmap vannila_sky_pic = Android.Graphics.BitmapFactory.DecodeResource(Application.Context.Resources, Resource.Drawable.Vanilla_Sky);
Bitmap jimmyneutron_pic = Android.Graphics.BitmapFactory.DecodeResource(Application.Context.Resources, Resource.Drawable.Jimmy_Neutron_Boy_Genius_film);
Movie m1 = new Movie(90, "Vanilla Sky", "James", vannila_sky_pic);
Movie m2 = new Movie(124, "jimmy neutron", "arthur", jimmyneutron_pic);
movieList = new System.Collections.Generic.List<Movie>();
movieList.Add(m1);
movieList.Add(m2);
movieAdapter = new MovieAdapter(this, movieList);
lv = FindViewById<ListView>(Resource.Id.lv);
lv.Adapter = movieAdapter;
lv.OnItemClickListener = this;
lv.OnItemLongClickListener = this;
btnAdd.SetOnClickListener(this);
}
protected override void OnResume()
{
base.OnResume();
if (movieAdapter != null)
{
movieAdapter.NotifyDataSetChanged();
}
}
public void OnItemClick(AdapterView parent, View view, int position, long id)
{
Intent intent = new Intent(this, typeof(EditMovieActivity));
Movie temp = MovieActivity.movieList[position];
intent.PutExtra("pos", position);
StartActivity(intent);
}
public void OnClick(View v)
{
if(v == btnAdd)
{
Intent intent = new Intent(this, typeof(EditMovieActivity));
StartActivity(intent);
}
}
public bool OnItemLongClick(AdapterView parent, View view, int position, long id)
{
MovieActivity.movieList.RemoveAt(position);
movieAdapter.NotifyDataSetChanged();
return true;
}
}
EditMovieActivity:` public class EditMovieActivity : Activity, Android.Views.View.IOnClickListener
{
Button btnSave, btnAddPic;
EditText etTitle, etDirector, etAvg, etLength;
Bitmap bitmap;
int pos = -1;
ImageView iv;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.edit_movie);
iv = FindViewById<ImageView>(Resource.Id.ivMovie);
btnSave = FindViewById<Button>(Resource.Id.btnSave);
btnAddPic = FindViewById<Button>(Resource.Id.btnAddPic);
etTitle = FindViewById<EditText>(Resource.Id.etTitle);
etDirector = FindViewById<EditText>(Resource.Id.etDirector);
etAvg = FindViewById<EditText>(Resource.Id.etAvg);
etLength = FindViewById<EditText>(Resource.Id.etLength);
pos = Intent.GetIntExtra("pos", -1);//-1 is default
btnAddPic.SetOnClickListener(this);
btnSave.SetOnClickListener(this);
if (pos != -1)// update
{
Movie temp = MovieActivity.movieList[pos];
Toast.MakeText(this, "position is " + pos, ToastLength.Long).Show();
etTitle.Text = temp.getTitle();
etDirector.Text = temp.getDirector();
etAvg.Text = "" + temp.getAvg();
etLength.Text = "" + temp.getLength();
bitmap = temp.getBitmap();
iv.SetImageBitmap(temp.getBitmap());
}
else // new movie
{
Toast.MakeText(this, "lets add new item ", ToastLength.Long).Show();
}
}
public void OnClick(View v)
{
if (v == btnAddPic)
{
Intent intent = new Intent(Android.Provider.MediaStore.ActionImageCapture);
StartActivityForResult(intent, 0);
}
else
if (v == btnSave)
{
int length = int.Parse(etLength.Text);
int avg = int.Parse(etAvg.Text);
string title = etTitle.Text;
string director = etDirector.Text;
Movie m = null;
if (pos != -1)//updates
{
m = new Movie(length, title, director, bitmap);
MovieActivity.movieList[pos] = m;
Finish();
}
else// adds new movie
{
m = new Movie(length, title, director, bitmap);
MovieActivity.movieList.Add(m);
Finish();
}
}
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 0)//coming from camera
{
if (resultCode == Result.Ok)
{
bitmap = (Android.Graphics.Bitmap)data.Extras.Get("data");
iv.SetImageBitmap(bitmap);
}
}
}
}`
Movie:
public class Movie
{
private int length;
private string title;
private string director;
private int avg;
private Android.Graphics.Bitmap bitmap;
public Movie(int length, string title, string director,Android.Graphics.Bitmap bitmap )
{
this.length = length;
this.title = title;
this.director = director;
this.avg = 0;
this.bitmap = bitmap;
}
public void setBitmap(Android.Graphics.Bitmap bitmap)
{
this.bitmap = bitmap;
}
public Android.Graphics.Bitmap getBitmap()
{
return bitmap;
}
public void setAvg(int avg)
{
this.avg = avg;
}
public int getAvg()
{
return avg;
}
public void setDirector(string director)
{
this.director = director;
}
public string getDirector()
{
return director;
}
public void setTitle(string title)
{
this.title = title;
}
public string getTitle()
{
return title;
}
public void setLength(int length)
{
this.length = length;
}
public int getLength()
{
return length;
}
}
MovieAdapter:
class MovieAdapter:BaseAdapter<Movie>
{
Android.Content.Context context;
List<Movie> objects;
public MovieAdapter(Android.Content.Context context, System.Collections.Generic.List<Movie> objects)
{
this.context = context;
this.objects = objects;
}
public List<Movie> GetList()
{
return this.objects;
}
public override long GetItemId(int position)
{
return position;
}
public override int Count
{
get { return this.objects.Count; }
}
public override Movie this[int position]
{
get { return this.objects[position]; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
Android.Views.LayoutInflater layoutInflater = ((MovieActivity)context).LayoutInflater;
Android.Views.View view = layoutInflater.Inflate(Resource.Layout.movie_layoutxml, parent, false);
TextView tvTitle = view.FindViewById<TextView>(Resource.Id.tvTitle);
TextView tvDirector = view.FindViewById<TextView>(Resource.Id.tvDirector);
TextView tvLength = view.FindViewById<TextView>(Resource.Id.tvlength);
TextView tvAvg = view.FindViewById<TextView>(Resource.Id.tvAvg);
ImageView ivCover = view.FindViewById<ImageView>(Resource.Id.ivCover);
Movie temp = objects[position];
if(temp != null)
{
ivCover.SetImageBitmap(temp.getBitmap());
tvAvg.Text = "" + temp.getAvg();
tvTitle.Text = temp.getTitle();
tvLength.Text ="" + temp.getLength();
tvDirector.Text = temp.getDirector();
}
return view;
}
}
According to your description, listview don't update when you change some listview item.
I do one sample that you can take a look, create public static List and ListAdapter.
public class MainActivity : AppCompatActivity
{
public static List<Earthquake> earthquakes;
ListView lvw;
public static EarthquakeListAdapter listadapter;
Button btnadd;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
earthquakes = new List<Earthquake>
{
new Earthquake{Place="Nepal", DateOccured="May 12, 2015" },
new Earthquake{Place="Solomon Sea", DateOccured="May 7, 2015" },
new Earthquake{Place="Papua New Guinea", DateOccured="May 5, 2015" },
new Earthquake{Place="Nepal", DateOccured="April 25, 2015" },
new Earthquake{Place="Taiwan", DateOccured="April 20, 2015" },
new Earthquake{Place="Papua New Guinea", DateOccured="March 29, 2015" },
new Earthquake{Place="Flores Sea", DateOccured="Febdruary 27, 2015" },
new Earthquake{Place="Mid-Atlantic range", DateOccured="Febdruary 13, 2015" }
};
lvw = FindViewById<ListView>(Resource.Id.lvwEarthquakes);
btnadd = FindViewById<Button>(Resource.Id.button1);
btnadd.Click += Btnadd_Click;
listadapter= new EarthquakeListAdapter(this, earthquakes);
lvw.Adapter = listadapter;
lvw.ItemLongClick += Lvw_ItemLongClick; ;
lvw.ItemClick += Lvw_ItemClick;
}
protected override void OnResume()
{
Log.Debug("OnResume", "OnResume called, app is ready to interact with the user");
base.OnResume();
listadapter = new EarthquakeListAdapter(this, earthquakes);
lvw.Adapter = listadapter;
}
private void Lvw_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
{
var item = earthquakes[e.Position];
MainActivity.earthquakes.Remove(item);
List<Earthquake> items = MainActivity.earthquakes;
listadapter = new EarthquakeListAdapter(this, earthquakes);
lvw.Adapter = listadapter;
}
private void Lvw_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Intent intent = new Intent(this, typeof(editActivity));
//Earthquake temp = MainActivity.earthquakes[e.Position];
string position = e.Position.ToString();
intent.PutExtra("p", position);
StartActivity(intent);
}
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);
}
}
public class Earthquake
{
public string Place { get; set; }
public string DateOccured { get; set; }
}
public class EarthquakeListAdapter : BaseAdapter<Earthquake>
{
List<Earthquake> earthquakes;
Activity context;
/// <summary>
/// Constructor
/// </summary>
/// <param name="context"></param>
/// <param name="earthquakeList"></param>
public EarthquakeListAdapter(Activity currentContext, List<Earthquake> earthquakeList) : base()
{
this.earthquakes = earthquakeList;
this.context = currentContext;
}
public override Earthquake this[int position]
{
get { return earthquakes.ToArray()[position]; }
}
public override int Count
{
get { return earthquakes.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(Android.Resource.Layout.SimpleListItem2, null);
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = earthquakes.ToArray()[position].Place;
view.FindViewById<TextView>(Android.Resource.Id.Text2).Text = earthquakes.ToArray()[position].DateOccured;
}
return view;
}
}
public class editActivity : Activity
{
EditText edittext1;
EditText edittext2;
int position;
Button button;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.editlayout1);
// Create your application here
edittext1 = FindViewById<EditText>(Resource.Id.editText1);
edittext2 = FindViewById<EditText>(Resource.Id.editText2);
button = FindViewById<Button>(Resource.Id.button1);
button.Click += Butto1_Click;
string text = Intent.GetStringExtra("p");
position = Convert.ToInt32(text);
edittext1.Text = MainActivity.earthquakes[position].Place;
edittext2.Text = MainActivity.earthquakes[position].DateOccured;
}
private void Butto1_Click(object sender, EventArgs e)
{
MainActivity.earthquakes[position] = new Earthquake() { Place = edittext1.Text, DateOccured = edittext2.Text };
OnBackPressed();
}
}
I have a custom Listview in my C# Android, each row contains one textview and one checkbox. I am saving the value (or the text) of the selected row's textview in a public list named usercoin. Each time the user opens the app, the list usercoin will contain the text of the his textview selected items, and I am doing that using SQLite. The problem is I want to re-check the items which the user have previously selected automatically when the activity starts which are stored in the usercoin list as I have previously noted. But I am not able to achieve this.
MainActivity.cs
ListView mListView;
MyAdapter adapter;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
mListView = FindViewById<ListView>(Resource.Id.listview);
List<TableList> list = new List<TableList>();
list.Add(new TableList("Germany",false));
list.Add(new TableList("France", false));
list.Add(new TableList("Finland", false));
list.Add(new TableList("Germany", false));
list.Add(new TableList("France", false));
list.Add(new TableList("Germany", false));
list.Add(new TableList("France", false));
list.Add(new TableList("Finland", false));
adapter = new MyAdapter(this, list);
mListView.Adapter = adapter;
mListView.ItemClick += MListView_ItemClick;
}
private void MListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
var t = list[e.Position];
string selected = t.name;
var ll = e.View as LinearLayout;
var cb = ll.GetChildAt(2) as CheckBox;
if (cb.Checked)
{
cb.Checked = false;
adapter.changeState((int)cb.Tag, false);
}
else
{
cb.Checked = true;
adapter.changeState((int)cb.Tag, true);
}
}
class MyAdapter : BaseAdapter
{
Context mContext;
List<TableList> mitems;
public MyAdapter(Context context, List<TableList> list)
{
this.mContext = context;
this.mitems = list;
}
public override int Count
{
get
{
return mitems.Count;
}
}
public override Java.Lang.Object GetItem(int position)
{
return mitems[position];
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
DataViewHolder holder = null;
if (convertView == null)
{
convertView = LayoutInflater.From(mContext).Inflate(Resource.Layout.CoinList, null, false);
holder = new DataViewHolder();
holder.tv = convertView.FindViewById<TextView>(Resource.Id.CoinName);
holder.iv = convertView.FindViewById<ImageView>(Resource.Id.imageView1);
holder.cb = convertView.FindViewById<CheckBox>(Resource.Id.checkBox1);
convertView.Tag = holder;
}
else
{
holder = convertView.Tag as DataViewHolder;
}
holder.cb.Tag = position;
holder.tv.Text = mitems[position].Name;
holder.cb.Focusable = false;
holder.cb.Checked = mitems[position].bl;
holder.iv.SetImageResource(Resource.Drawable.dapao);
holder.cb.CheckedChange += Cb_CheckedChange;
return convertView;
}
private void Cb_CheckedChange(object sender, CompoundButton.CheckedChangeEventArgs e)
{
var cb = sender as CheckBox;
if (e.IsChecked && !mitems[(int)cb.Tag].bl)
{
mitems[(int)cb.Tag].bl = true;
this.NotifyDataSetChanged();
}
else if (!e.IsChecked && mitems[(int)cb.Tag].bl)
{
mitems[(int)cb.Tag].bl = false;
this.NotifyDataSetChanged();
}
}
internal void changeState(int tag, bool v)
{
mitems[tag].bl = v;
this.NotifyDataSetChanged();
}
}
public class DataViewHolder : Java.Lang.Object
{
public ImageView iv { get; set; }
public TextView tv { get; set; }
public CheckBox cb { get; set; }
}
public class TableList : Java.Lang.Object
{
private string v;
public TableList(string name, bool b)
{
this.Name = name;
this.bl = b;
}
public string Name { get; set; }
public bool bl { get; set; }
}
}
}
For example, when the user first run the app and select France and Germany from the listview, next time he re-opens the app, the usercoin list will contain France and Germany. Now the question is how can I check the checkboxes corresponding to those values in the listview. I have tried to do so by including this code in MyAdapter : BaseAdapter class:
if (Class1.usercoin.Contains(item.CoinAbr))
{
Class1.adapter[(int)holder.cb.Tag].bl = true;
this.NotifyDataSetChanged();
}
But when this code get executed, the previously checked items are checked plus some other items which the user haven't checked previously are also checked. So how can I check the previously checked items in the Listview on the app start ? Please help me to find a solution.
string[] arrays = new string[] { "A", "B", "C", "D", "E", "F" };
ListView lstItems;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
lstItems = FindViewById<ListView>(Resource.Id.listView1);
lstItems.Adapter = new CustomAdapter(Activity, arrays);
}
public class CustomAdapter : BaseAdapter
{
//private const int TYPE_ITEM = 0;
//private const int TYPE_SEPARATOR = 1;
string[] mData;
//private TreeSet sectionHeader;
LayoutInflater mInflater;
public CustomAdapter(Context context, string[] Data)
{
mInflater = LayoutInflater.FromContext(context);
mData = Data;
}
public override int Count
{
get { return mData.Length; }
}
public override Java.Lang.Object GetItem(int position)
{
return mData[position];
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
//var data = mData [position];
if (convertView == null)
{
holder = new ViewHolder();
holder.textViewHeader = (TextView)convertView.FindViewById(Resource.Id.textviewHeaderItems);
holder.textViewSeparator = (TextView)convertView.FindViewById(Resource.Id.textviewItemsSeparator);
convertView.Tag = holder;
}
else
{
holder = (ViewHolder)convertView.Tag as ViewHolder;
}
for (int i = 0; i <= mData.Length - 1; i++)
{
if (i == 0)
{
holder.textViewHeader.Text = "Group A";
}
else if (i == 4)
{
holder.textViewHeader.Text = "Group B";
}
holder.textViewSeparator.Text = mData[i];
}
return convertView;
}
}
public class ViewHolder : Java.Lang.Object
{
public TextView textViewHeader { get; set; }
public TextView textViewSeparator { get; set; }
}
In CustomerAdapter I have a string[] Data parameter. After in OnCreate I got this problem at lstItems.Adapter = new CustomAdapter(Activity, arrays). I don't understand.
I was trying to create a header listview on xamarin android.
I saw several samples but that code has much errors.
You are passing the Activity class name. Instead you should pass an instance of the Activity you are in. You should be instantiating Adapter like below from Activity
lstItems.Adapter = new CustomAdapter (this, arrays);
Activity is a type. What you need is an instance of type Context. In Xamarin Android that's most commonly Android.App.Application.Context.
So your line should look like this:
lstItems.Adapter = new CustomAdapter(Android.App.Application.Context, arrays);
I m a beginner in android dev, I m struggling with passing string Clicked_Message from Click event in Recycle Adapter Class to the other activity. Is it a good way to use Intent? If so how can I pass context to click event? Thanks
public class RecyclerAdapter : RecyclerView.Adapter
{
private RecyclerView mRecyclerView;
private List<NotificationClass> mEmails;
public RecyclerAdapter(List<NotificationClass> emails, RecyclerView recyclerView)
{
mEmails = emails;
mRecyclerView = recyclerView;
}
public class MyView : RecyclerView.ViewHolder
{
public View mMainView { get; set; }
public TextView mName { get; set; }
public TextView mSubject { get; set; }
public TextView mMessage { get; set; }
public MyView(View view) : base(view)
{
mMainView = view;
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View row = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.row, parent, false);
TextView txtName = row.FindViewById<TextView>(Resource.Id.txtName);
TextView txtSubject = row.FindViewById<TextView>(Resource.Id.txtSubject);
TextView txtMessage = row.FindViewById<TextView>(Resource.Id.txtMessage);
MyView view = new MyView(row) { mName = txtName, mSubject = txtSubject, mMessage = txtMessage };
return view;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
MyView myHolder = holder as MyView;
int indexPosition = (mEmails.Count - 1) - position;
myHolder.mMainView.Click += mMainView_Click;
myHolder.mName.Text = mEmails[position].Name;
myHolder.mSubject.Text = mEmails[position].Subject;
myHolder.mMessage.Text = mEmails[position].Message;
}
public override int ItemCount
{
get { return mEmails.Count; }
}
public void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
}
public void mMainView_Click(object sender, EventArgs e,Context context)
{
int position = mRecyclerView.GetChildPosition((View)sender);
int indexPosition = (mEmails.Count - 1) - position;
Console.WriteLine(mEmails[indexPosition].Message);
string Clicked_Message = (mEmails[indexPosition].Message);
var activity2 = new Intent(context, typeof(ContactActivity));
activity2.PutExtra("MyData", Clicked_Message);
context.StartActivity(activity2);
}
}
You don't need to pass a context. Just use an intent and put the information you want to pass as extras into the intent.
In case your adapter needs a context, pass it in through the constructor and store it as a field member.
This is my typical implementation of the RecyclerView.Adapter with a view holder...
public class ContactsAdapter : V7.RecyclerView.Adapter
{
private List<Contact> _contacts;
public event EventHandler ItemClick;
public void OnItemClick(ContactViewHolder holder)
{
if (ItemClick != null)
{
ItemClick(holder, EventArgs.Empty);
}
}
public ContactsAdapter(List<Contact> contacts)
: base()
{
_contacts = contacts;
}
public override void OnBindViewHolder(V7.RecyclerView.ViewHolder holder, int position)
{
var contactHolder = (ContactViewHolder)holder;
contactHolder.BindUI(_contacts[position]);
}
public override V7.RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
var view = LayoutInflater.FromContext(parent.Context).Inflate(Resource.Layout.ContactsListItem, parent, false);
return new ContactViewHolder(view)
{
Adapter = this
};
}
public override int ItemCount
{
get
{
return _contacts.Count;
}
}
}
View Holder (typically in the same file as the adapter)
public class ContactViewHolder : V7.RecyclerView.ViewHolder, View.IOnClickListener
{
public TextView ContactNameTextView { get; set; }
public TextView ContactPhoneTextView { get; set; }
public TextView ContactIntialsTextView { get; set; }
public Contact Contact { get; set; }
private WeakReference _adapter;
public ContactsAdapter Adapter
{
get { return (ContactsAdapter)_adapter.Target; }
set { _adapter = new WeakReference(value); }
}
public ContactViewHolder(View view)
: base(view)
{
GetUI(view);
view.SetOnClickListener(this);
}
private void GetUI(View view)
{
ContactNameTextView = view.FindViewById<TextView>(Resource.Id.ContactName);
ContactPhoneTextView = view.FindViewById<TextView>(Resource.Id.ContactPhone);
ContactIntialsTextView = view.FindViewById<TextView>(Resource.Id.ContactInitialsTextView);
}
public void BindUI(Contact contact)
{
Contact = contact;
ContactNameTextView.Text = contact.ContactName;
ContactPhoneTextView.Text = contact.Phone1;
ContactIntialsTextView.Text = contact.Initials;
}
public void OnClick(View v)
{
Adapter.OnItemClick(this);
}
}
This encapsulates the functionality to the view holder. I also give the instance of the adapter to the view holder as a WeakReference. This allows me to call the OnItemClick, passing the instance of the view holder. If you will notice that the view holder also has an instance of the object that it is representing. This means I don't have to worry about the index that was chosen. I already have the object data available to me.
So the implementation in the Activity/Fragment is like this...
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
_contacts = Contact.GetAllContacts();
_adapter = new ContactsAdapter(_contacts);
_adapter.ItemClick += ContactSelected;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = inflater.Inflate(Resource.Layout.ContactsFragment, container, false);
var layoutManager = new V7.LinearLayoutManager(this.Activity) { Orientation = V7.LinearLayoutManager.Vertical };
_contactsView = view.FindViewById<V7.RecyclerView>(Resource.Id.ContactList);
_contactsView.SetAdapter(_adapter);
_contactsView.HasFixedSize = true;
_contactsView.SetLayoutManager(layoutManager);
return view;
}
private void ContactSelected (object sender, EventArgs e)
{
var holder = (ContactViewHolder)sender;
var detailFragment = new ContactDetailsFragment(holder.Contact);
MainActivity.ShowFragment(detailFragment);
}
I give the Contact to a Fragment, but you could do something similar for an activity using an intent.
Now whether this is the most efficient way of handling a click of a row in a RecyclerView, I don't know. But this implementation has been working for me.
I'm trying to make an Expandable ListView, but I don't know how to retrieve the info of some methods from the ExpandableListAdapter, so here is my code:
This the Main Activity:
[Activity (Label = "AR Transactions Details")]
public class ARInquiry : ExpandableListActivity
{
private ARExpandableListAdapter adapter;
private string[] groups = {"1","2","3","4"};
private string[,] children = {
{ "Arnold", "Barry", "Chuck", "David" },
{"Ace", "Bandit", "Cha-Cha", "Deuce"},
{ "Fluffy", "Snuggles", "", ""},
{ "Goldy", "Bubbles", "", "" }
};
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView(Resource.Layout.ar_inquiry);
//Restrieve the ExpandableListView from the layout
ExpandableListView listview = FindViewById<ExpandableListView>(Android.Resource.Id.List);
//Initialize the adapter with blank groups and children
//We will be adding children on a thread, and then update the ListView
adapter = new ARExpandableListAdapter(this, groups, children);
listview.SetAdapter(adapter);
}
}
This is the ExpandableListViewAdapter Class Code:
public class ARExpandableListAdapter : BaseExpandableListAdapter
{
private Context context;
private string[] groups;
private string[,] children;
public ARExpandableListAdapter(Context context, string[] groups, string[,] children)
{
this.context = context;
this.groups = groups;
this.children = children;
}
public override Java.Lang.Object GetChild (int groupPosition, int childPosition)
{
return children[groupPosition, childPosition];
}
public override long GetChildId (int groupPosition, int childPosition)
{
return childPosition;
}
public override View GetChildView (int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
{
if(convertView == null)
{
LayoutInflater infaInflater = (LayoutInflater) context.GetSystemService(Context.LayoutInflaterService);
convertView = infaInflater.Inflate(Resource.Layout.child_layout, null);
}
TextView tv = (TextView) convertView.FindViewById(Resource.Id.tvChild);
if(isLastChild == true)
{
return convertView;
}
tv.SetText(" " + children[groupPosition, childPosition], TextView.BufferType.Normal);
return convertView;
}
public override int GetChildrenCount (int groupPosition)
{
return children[groupPosition, 3];
}
public override Java.Lang.Object GetGroup (int groupPosition)
{
return groups[groupPosition];
}
public override long GetGroupId (int groupPosition)
{
return groupPosition;
}
public override View GetGroupView (int groupPosition, bool isExpanded, View convertView, ViewGroup parent)
{
string _group = (string)GetGroup(groupPosition);
if(convertView==null)
{
LayoutInflater infalInflater = (LayoutInflater) context.GetSystemService(Context.LayoutInflaterService);
convertView = infalInflater.Inflate(Resource.Layout.group_layout, null);
}
TextView tv = (TextView)convertView.FindViewById(Resource.Id.tvGroup);
tv.SetText(_group, TextView.BufferType.Normal);
return convertView;
}
public override bool IsChildSelectable (int groupPosition, int childPosition)
{
return true;
}
public override int GroupCount {
get {
return groups.Count();
}
}
public override bool HasStableIds {
get {
return true;
}
}
}
How can I retrieve the length of the GetChildrenCount Method?
To get the length of the groups children it should be:
public override int GetChildrenCount (int groupPosition)
{
return children[groupPosition].Length;
}
I solve like this, cuz its working:
public class ARExpandableListAdapter : BaseExpandableListAdapter
{
private Context context;
private IList<string> groups;
private IList<IAccountsReceivable> children;
public ARExpandableListAdapter(Context context, IList<string> groups, IList<IAccountsReceivable> children)
{
this.context = context;
this.groups = groups;
this.children = children;
}
#region implemented abstract members of Android.Widget.BaseExpandableListAdapter
public override Java.Lang.Object GetChild (int groupPosition, int childPosition)
{
return (Java.Lang.Object)children[groupPosition]; //as Java.Lang.Object.JavaCast<decimal>();
}
public override long GetChildId (int groupPosition, int childPosition)
{
return childPosition;
}
public override View GetChildView (int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
{
if(convertView == null)
{
LayoutInflater infaInflater = (LayoutInflater) context.GetSystemService(Context.LayoutInflaterService);
convertView = infaInflater.Inflate(Resource.Layout.child_layout, null);
}
if(childPosition<6)
{
string label = " ";
if (childPosition == 0)
label = children[groupPosition].TransactionType;
if (childPosition == 1)
label = children[groupPosition].TransactionValue.ToString();
if (childPosition == 2)
label = children[groupPosition].TransactionDate.ToString();
if (childPosition == 3)
label = children[groupPosition].TransactionDueDate.ToString();
if (childPosition == 4)
label = children[groupPosition].OrderNumber.ToString();
if (childPosition == 5)
label = children[groupPosition].CustomerReference;
TextView tv = (TextView) convertView.FindViewById(Resource.Id.tvChild);
tv.SetText(" " + label, TextView.BufferType.Normal);
}
return convertView;
}
public override int GetChildrenCount (int groupPosition)
{
return children.Count;
}
public override Java.Lang.Object GetGroup (int groupPosition)
{
return groups[groupPosition];
}
public override long GetGroupId (int groupPosition)
{
return groupPosition;
}
public override View GetGroupView (int groupPosition, bool isExpanded, View convertView, ViewGroup parent)
{
string _group = (string)GetGroup(groupPosition);
if(convertView==null)
{
LayoutInflater infalInflater = (LayoutInflater) context.GetSystemService(Context.LayoutInflaterService);
convertView = infalInflater.Inflate(Resource.Layout.group_layout, null);
}
TextView tv = (TextView)convertView.FindViewById(Resource.Id.tvGroup);
tv.SetText(_group, TextView.BufferType.Normal);
return convertView;
}
public override bool IsChildSelectable (int groupPosition, int childPosition)
{
return true;
}
public override int GroupCount {
get {
return groups.Count();
}
}
public override bool HasStableIds {
get {
return true;
}
}
#endregion
}