Xamarin.Android - Listview within a listview - c#

Hello sorry for the massive code dump but I have can't quite figure out how to solve this.
For this application I'm making a listview filled with medical conditions and lifestyles affecting diet. So there is the condition listview and an ingredients listview under each conditions' title with a corresponding symbol meaning no or moderate.
I have gotten the condition listview to work fine but when i am calling the ingredients adapter an error shows up at the context parameter saying:
Argument 1: cannot convert from 'FoodTranslate.TranslateAdapter' to 'Android.Content.Context'
I was just wondering if there are changes to the second lot of code that can fix this.
Thank you in advanced.
namespace FoodTranslate
{
class TranslateAdapter : BaseAdapter<OptionItem>
{
private List<OptionItem> Options;
private Context mContext;
public TranslateAdapter(Context context, List<OptionItem> items)
{
Options = items;
mContext = context;
}
public override int Count
{
get { return Options.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override OptionItem this[int position]
{
get { return Options[position]; }
}
//customising starts here
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(mContext).Inflate(Resource.Layout.ConditionItem, null, false);
}
TextView OptionName = row.FindViewById<TextView>(Resource.Id.OptionName);
ListView ingOut = row.FindViewById<ListView>(Resource.Id.Ingredients);
OptionName.Text = Options[position].Name;
//where the error occurs
IngredientAdapter ingAdapter = new IngredientAdapter(this, Options[position].Ingredients);
return row;
}
}
}
Ingredients listview:
namespace FoodTranslate
{
class IngredientAdapter : BaseAdapter<Ingredient>
{
private List<Ingredient> Ingredients;
private Context mContext;
public IngredientAdapter(Context context, List<Ingredient> items)
{
Ingredients = items;
mContext = context;
}
public override int Count
{
get { return Ingredients.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override Ingredient this[int position]
{
get { return Ingredients[position]; }
}
//Customising starts here
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(mContext).Inflate(Resource.Layout.IngredientItem, null, false);
}
TextView IngredientName = row.FindViewById<TextView>(Resource.Id.IngredientName);
ImageView imgLevel = row.FindViewById<ImageView>(Resource.Id.imgLevel);
IngredientName.Text = Ingredients[position].name;
switch (Ingredients[position].level)
{
case ("no"):
imgLevel.SetImageResource(Resource.Drawable.noldpi);
break;
case ("yes"):
imgLevel.SetImageResource(Resource.Drawable.yesldpi);
break;
case ("moderate"):
imgLevel.SetImageResource(Resource.Drawable.moderateldpi);
break;
};
return row;
}
}
}

Try passing mContext instead of this :-
IngredientAdapter ingAdapter = new IngredientAdapter(m, Options[position].Ingredients);

Related

How to Use ArrayAdapter with Multiple Textview columns in listView Xamarin Android

I have listview with 4 columns like ItemLookupCode,Quantity,Description,Price
I am adding full code i am sorting list on button click.
i have issue in following Populate() to call 4 textview
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.PriceCheckList);
List<string> list = new List<string>();
foreach (crItem item in listObject)
{
list.Add(item.ItemLookupCode);
list.Add(Convert.ToString(item.Quantity));
list.Add(item.Description);
list.Add(Convert.ToString(item.Price));
}
spacecrafts = list.ToArray();
this.InitializeViews();
this.SortData(ascending);
this.ascending = !ascending;
}
SortBtnItemLookupCode.Click += sortBtn_Click;
void sortBtn_Click(object sender, EventArgs e)
{
SortData(ascending);
this.ascending = !ascending;
}
private void InitializeViews()
{
listView = FindViewById<ListView>(Resource.Id.listView);
SortBtnItemLookupCode = FindViewById<Button>(Resource.Id.SortBtnItemLookupCode);
}
private void Populate()
{
ArrayAdapter adapter = new ArrayAdapter<string>(this, Resource.Layout.PriceCheckListTemplate, Resource.Id.lblItemLookupCode, spacecrafts);
listView.SetAdapter(adapter);
}
private void SortData(bool asc)
{
if (asc)
{
Array.Sort(spacecrafts);
}
else
{
Array.Reverse(spacecrafts);
}
Populate();
}
}
I want to assign all above 4 object to Textview but currently ArrayAdapter accept only one Textview like i have use below Resource.Id.lblItemLookupCode but How i can assign 4 object to 4 columns Textview in ArrayAdapter
Help much appreciated
Thanks in advance
Try create model class to define data for the listView's item, then customize a custom Adapter to populate the data.
Check the code:
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
string[] items = new string[] { "Vegetables", "Fruits", "Flower Buds", "Legumes", "Bulbs", "Tubers" };
List<CustomModel> list = new List<CustomModel>();
//add data
CustomAdapter adapter = new CustomAdapter(list);
ListView listview_ = FindViewById<ListView>(Resource.Id.listview_);
listview_.SetAdapter(adapter);
}
}
public class CustomModel
{
public string Value1 { get; set; }
...
}
public class CustomAdapter : BaseAdapter<CustomModel>
{
List<CustomModel> list = new List<CustomModel>();
public _Adapter(List<CustomModel> list)
{
this.list = list;
}
public override CustomModel this[int position]
{
get
{
return list[position];
}
}
public override int Count
{
get
{
return list.Count;
}
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var view = convertView;
view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.layout1, parent, false);
//specify value to the each textView
var textview = view.FindViewById<TextView>(Resource.Id.text_1);
textview.Text = list[position].Value1;
...
return view;
}
}

Android - Check custom listView items on the start of the App

I have a custom Listview, each row contains one textviewand 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 usaer have previously selected which are available in the usercoin list. I am not able to do so.
MyActivity.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 run the app and select France and Germany from the listview, next time he 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.
I have stored the data(useritems) in both DataBase and memory.
If your app is killed by system or user, you can restore the data from DataBase.
If your app isn't killed by system or user, but user jump to other activity, when he back to this activity, you can use memory to restore the data.
About DataBase, I am use SQLite.Net. I am using DBHelper to operation the DataBase.
And I have add Application class in the app.
I have update the demo. Here is gif.

RecyclerView not showing - Xamarin .Droid

To me, it seems there's nothing wrong in my code but my recyclerView is not showing up. Please look into my code if the adapter is well set up. Thank you. Please what am i missing in my adapter? The page appears empty although i see that the datasnapShot in my adapter runs but my recyclerView doesn't show.
Adapter
public class PhotoHolder : RecyclerView.ViewHolder
{
public ImageView ImgPhotos;
public PhotoHolder(View itemView):base(itemView)
{
ImgPhotos = (ImageView)itemView.FindViewById(Resource.Id.imageView);
}
public class PhotoAdapter : RecyclerView.Adapter, IValueEventListener
{
public PhotoAdapter(List<Photos> Photos, Context mContext)
{
this.Photos = Photos;
this.mContext = mContext;
photos = (PhotosActivity)mContext;
mDatabaseImage = FirebaseDatabase.Instance.Reference.Child("Photos");
mDatabaseImage.AddValueEventListener(this);
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
hold = holder as PhotoHolder;
hold.ImgPhotos.SetImageResource(Resource.Drawable.cheese_5);
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.list_photos, parent, false);
PhotoHolder holder = new PhotoHolder(v);
return holder;
}
public override int ItemCount
{
get { return Photos.Count; }
}
public void OnCancelled(DatabaseError error)
{
throw new NotImplementedException();
}
public void OnDataChange(DataSnapshot snapshot)
{
var items = snapshot.Children?.ToEnumerable<DataSnapshot>();
foreach (DataSnapshot item in items)
{
map = (HashMap)item.Value;
imageUrl = new FilePhotos(map.Get("URL").ToString());
}
}
}
}
PhotoActivity
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
FrameLayout content = (FrameLayout)FindViewById(Resource.Id.content_frame);
LayoutInflater.Inflate(Resource.Layout.PhotoView, content);
adapter = new PhotoAdapter(Photos, this);
rv = FindViewById<RecyclerView>(Resource.Id.recyclerView);
rv.SetLayoutManager(new LinearLayoutManager(this));
rv.SetItemAnimator(new DefaultItemAnimator());
rv.SetAdapter(adapter);
adapter.NotifyDataSetChanged();
}

Xamarin Image Grid from Folder

I am trying to display an Image Grid with Text. Using Images from a Folder. I have tries various approaches and tutorials with no success. I have both READ and WRITE permissions for the Internal and External Storage. Whenever I debug the application all I get is a blank screen. I have tried setting a breakpoint on the Adapters GetView() method which never gets hit.
Here is my MainActivity OnCreate() method:
protected override void OnCreate(Bundle bundle)
{
if (!_dir.Exists()) { _dir.Mkdir(); }
base.OnCreate(bundle);
SetContentView(R.Layout.Main);
string[] FilePath = null;
string[] FileName = null;
if (_dir.IsDirectory)
{
DroidIO.File[] imageList = _dir.ListFiles();
FilePath = new string[imageList.Length];
FileName = new string[imageList.Length];
for (int i = 0; i < imageList.Length; i++)
{
FilePath[i] = imageList[i].AbsolutePath;
FileName[i] = imageList[i].Name;
}
}
var gvImageList = FindViewById<GridView>(R.Id.gvImageList);
gvImageList.SetAdapter(new ImagesFromFolderAdapter(this, FilePath, FileName));
gvImageList.ItemClick += delegate { gvImageList_ItemClick(); };
}
And my Image Adapter Class:
public class ImagesFromFolderAdapter : BaseAdapter
{
private Activity context;
private string[] filePath;
private string[] fileName;
public ImagesFromFolderAdapter(Activity c, string[] fp, string[] fn)
{
this.context = c;
this.fileName = fn;
this.filePath = fp;
}
public override int Count { get; }
public int GetCount()
{
return filePath.Length;
}
public override Java.Lang.Object GetItem(int position)
{
return position;
}
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(R.Layout.gallery_item_layout, null);
view.FindViewById<ImageView>(R.Id.gitemImage).SetImageBitmap(BitmapFactory.DecodeFile(filePath[position]));
view.FindViewById<TextView>(R.Id.gitemText).Text = fileName[position];
return view;
}
}
Any ideas where I am going wrong? I am currently using an LG G3 as a debug device if this helps. Thankyou for any help in advance.
You returned a zero count for your grid adapter.
Change
public override int Count { get; }
To
public override int Count
{
get { return filePath.Length; }
}

xamarin android ExpandableListView: remove or hide a childview from group

How to remove a child view from group after clicking a button of the child view?
class ExpandableListAdapter : BaseExpandableListAdapter {
private ListView listview;
private LinearLayout mainLayout;
private View linearLayout;
public Activity _context;
TextView txtListChild;
private List<string> _listDataHeader; // header titles
private Dictionary<string, List<string>> _listDataChild;
public ExpandableListAdapter(Activity activity, List<string> listDataHeader, Dictionary<String, List<string>> listChildData) {
//, Dictionary<String, List<string>> listChildData2
this._context = activity;
this._listDataHeader = listDataHeader;
this._listDataChild = listChildData;
// this._listDataChild2 = listChildData2;
}
public override Java.Lang.Object GetChild(int groupPosition, int childPosition) {
return _listDataChild[_listDataHeader[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) {
string childText = (string)GetChild(groupPosition, childPosition);
convertView = null;
if (convertView == null) {
convertView = _context.LayoutInflater.Inflate(Resource.Layout.childRowWithButton, null);
Button no = (Button)convertView.FindViewById(Resource.Id.gono);
no.Click += delegate{
// I want hide my child
};
txtListChild.Text = childText;
}
return convertView;
}
public override int GetChildrenCount(int groupPosition) {
return _listDataChild[_listDataHeader[groupPosition]].Count;
}
public override Java.Lang.Object GetGroup(int groupPosition) {
return _listDataHeader[groupPosition];
}
public override long GetGroupId(int groupPosition){
return groupPosition;
}
public override View GetGroupView(int groupPosition, bool isExpanded, View convertView, ViewGroup parent){
string headerTitle = (string)GetGroup(groupPosition);
convertView = convertView ? ? _context.LayoutInflater.Inflate(Resource.Layout.HeaderCustomLayout, null);
var lblListHeader = (TextView)convertView.FindViewById(Resource.Id.Header);
//string headerTitle2 = (string)GetGroup(groupPosition);
//var ListHeader2 = (TextView)convertView.FindViewById(Resource.Id.Header2);
//ListHeader2.Text = headerTitle2;
lblListHeader.Text = headerTitle;
return convertView;
}
public override int GroupCount{
get{
return _listDataHeader.Count;
}
}
public override bool HasStableIds{
get{
return false;
}
}
public override bool IsChildSelectable(int groupPosition, int childPosition){
return true;
}
}
You can use listView.SetOnChildClickListener() to remove your child view as following code:
public class MainActivity : Activity , IOnChildClickListener
{
ExpandableListView listView;
List<Data> newDataList;
ExpandableDataAdapter myadapter;
public bool OnChildClick(ExpandableListView parent, View clickedView, int groupPosition, int childPosition, long id)
{
newDataList.RemoveAt(0);
myadapter.NotifyDataSetChanged();
return true;
}
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);
newDataList = Data.SampleData();
myadapter = new ExpandableDataAdapter(this, newDataList);
listView = FindViewById<ExpandableListView> (Resource.Id.myExpandableListview);
listView.SetAdapter (myadapter);
listView.SetOnChildClickListener(this);
}
}
In my sample, I just remove the first item of the child, You can use the int groupPosition, int childPosition to get the current location you click. And remove it from your listData. Remember to call adapter.NotifyDataSetChanged(); when you change the data set.
I am using the ExpandableListView sample from github
Screen shot:

Categories

Resources