Custom listview has false information Xamarin Android - c#

I'm new coding Xamarin, so i made a custom adapter, my idea was to save everything, when the user closes the app. After some research I thought this code was gonna work:
List<GardenClass> MyList = new List<GardenClass> ();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
listview.Adapter = new GardenAdapter(this, MyList);
}
protected override void OnPause()
{
base.OnPause();
write();
}
public void write()
{
string path = System.Environment.GetFolderPath(SpecialFolder.Personal);
string filename = Path.Combine(path, "Files.txt");
try
{
File.WriteAllText(filename,JsonConvert.SerializeObject(MyList));
}
catch (Exception e)
{
Console.WriteLine("Failed to serialize. Reason: " + e.Message);
throw;
}
}
public class GardenAdapter : BaseAdapter<GardenClass>
{
private Context MyCon;
List<GardenClass> items;
Activity context;
public GardenAdapter(Activity context, List<GardenClass> items)
: base()
{
MyCon = context;
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override GardenClass this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
var item = items[position];
Android.Views.View view;
if (convertView == null) {
view = context.LayoutInflater.Inflate(Resource.Layout.ListItem, null);
} else { view = convertView; }
view.FindViewById<TextView>(Resource.Id.textView1).Text = item.ToDo;
view.FindViewById<TextView>(Resource.Id.textView2).Text = "Week " + item.Week.ToString();
view.FindViewById<CheckBox>(Resource.Id.checkBox1).Checked = item.Done;
CheckBox MyCheckBox;
checkding = view.FindViewById<CheckBox>(Resource.Id.checkBox1);
// The folowing code prevents the checkbox of stealing the focus, which make a singular listview item unclickable
MyCheckBox.Focusable = false;
MyCheckBox.FocusableInTouchMode = false;
MyCheckBox.Clickable = true;
return view;
}
}
[Serializable]
public class ZaaiSpul
{
public int Week { get; set; }
public string ToDo { get; set; }
public bool Done { get; set; }
}
But when the OnPause() function gets called, then MyList gives me incorrect information(saw it myself in the debugger).
I'm sorry if I did some wrong things, but I'm new to Xamarin.
I hope you can help me.

You're only reading the check box state, you're never saving it when it changes. Add this in your GetView:
MyCheckBox.CheckedChange += (sender, e) =>
{
items[position].Done = e.IsChecked;
};

Related

Xamarin Android C# filterable / searchview with recyclerview and checkboxes

I've Created and App with Search View comes up with RecyclerView with Check box. When i checked a checkbox then search the checked checkbox becomes uncheck. How can i resolve the issue? Checkbox state when searching state the checkbox is still checked. Thanks fellow programmers
Screenshot 1:
Application View
When checking item in recycler view :
Selecting Item Checkbox
When i searched the item the checkbox state changes it becomes unchecked item: Searching the item becomes unchecked
public class SelectBranch : AppCompatActivity
{
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
List<Info_LoadBranch> loadBranch = new List<Info_LoadBranch>();
BranchAdapter holder;
Android.Widget.SearchView searchViewBranch;
List<string> SelectedBranchCode = new List<string>();
Button BtnProceed;
string dbPath;
SQLiteConnection db;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_select);
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView1);
mLayoutManager = new LinearLayoutManager(this);
BtnProceed = FindViewById<Button>(Resource.Id.btnProceed);
BtnProceed.Click += BtnProceed_Click;
LoadData();
searchViewBranch = FindViewById<Android.Widget.SearchView>(Resource.Id.searchView1);
searchViewBranch.QueryTextChange += SearchViewBranch_QueryTextChange;
GlobalVariable.SelectedBranchCode = new List<string>();
// Create your application here
}
private void SearchViewBranch_QueryTextChange(object sender, Android.Widget.SearchView.QueryTextChangeEventArgs e)
{
var adapter = new BranchAdapter(this, FindInsideList(e.NewText));
holder.NotifyDataSetChanged();
mRecyclerView.SetAdapter(adapter);
}
private List<Info_LoadBranch> FindInsideList(string text)
{
if (text != null && text.Length > 0)
{
List<Info_LoadBranch> filteredList = new List<Info_LoadBranch>();
foreach (var itm in loadBranch)
{
if (itm != null)
{
text = text.ToLower();
if (itm.BranchName != null ? itm.BranchName.ToLower().Contains(text) : false)
{
filteredList.Add(itm);
}
}
}
return filteredList;
}
return loadBranch;
}
private void BtnProceed_Click(object sender, EventArgs e)
{
if (GlobalVariable.SelectedBranchCode.Count > 0)
{
var intent = new Intent(this, typeof(Inquiry));
StartActivity(intent);
this.Finish();
}
else
{
DialogHelper.ShowAlertMessage(this, "Exception", "Please select Branch");
return;
}
}
private void LoadData()
{
dbPath = Path.Combine(BaseVariable.DEFAULT_APP_SETTINGS_DB_PATH, BaseVariable.DEFAULT_SQLITE_DB_COMPANY);
db = new SQLiteConnection(dbPath);
loadBranch = db.Query<Info_LoadBranch>("Select BranchCode, BranchName from BranchDB");
holder = new BranchAdapter(this, loadBranch);
//ListViewSelectedBranch.Adapter = output;
mRecyclerView.SetLayoutManager(mLayoutManager);
holder.NotifyDataSetChanged();
mRecyclerView.SetAdapter(holder);
}
public class BranchAdapter : RecyclerView.Adapter
{
public event EventHandler<int> ItemClick;
AppCompatActivity activity;
private List<Info_LoadBranch> branchesList;
public BranchAdapter(AppCompatActivity activity, List<Info_LoadBranch> branchesList)
{
//this.items = items;
this.activity = activity;
this.branchesList = branchesList;
//this.branchesList = branchesList.OrderBy(s => s.BranchName).ToList();
}
public override int ItemCount
{
get
{
return branchesList.Count;
}
}
public Filter Filter { get; private set; }
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.adapter_selectbranch, parent, false);
//itemView.SetBackgroundResource(Resource.Drawable.listItem1);
PickingViewHolder vh = new PickingViewHolder(itemView);
return vh;
}
private Dictionary<int, bool> map = new Dictionary<int, bool>();
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
var item = branchesList[position];
PickingViewHolder vh = holder as PickingViewHolder;
vh.BranchCodeCheckBox.SetOnCheckedChangeListener(new MyListener(map, position));
vh.LblBranch.Text = item.BranchName;
vh.BranchCodeCheckBox.Tag = item.BranchCode;
if (map != null && map.ContainsKey(position))
{
vh.BranchCodeCheckBox.Checked = true;
// vh.BranchCodeCheckBox.Checked = branchesList[position].IsChecked;
}
else
{
vh.BranchCodeCheckBox.Checked = false;
}
//vh.BranchCodeCheckBox.Checked = branchesList[position].IsChecked;
//vh.BranchCodeCheckBox.SetOnCheckedChangeListener(new CheckedChangeListener(this.activity));
//if (map != null && map.ContainsKey(position))
//{
// vh.BranchCodeCheckBox.Checked = true;
//}
//else
//{
// vh.BranchCodeCheckBox.Checked = false;
//}
//if (position != 0)
//{
// var linearLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent,
// ViewGroup.LayoutParams.WrapContent);
// linearLayoutParams.SetMargins(0, 10, 0, 0);
// vh.MainLinearLayout.LayoutParameters = linearLayoutParams;
//}
//vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);
}
class MyListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
{
public Dictionary<int, bool> map;
public int mPosotion;
string name;
public MyListener(Dictionary<int, bool> map, int position)
{
this.map = map;
mPosotion = position;
}
public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
{
if (isChecked == true)
{
if (!map.ContainsKey(mPosotion))
{
map.Add(mPosotion, true);
name = (string)buttonView.Tag;
GlobalVariable.SelectedBranchCode.Add(name);
}
}
else
{
map.Remove(mPosotion);
foreach (var a in GlobalVariable.SelectedBranchCode)
{
GlobalVariable.SelectedBranchCode.Remove(name);
break;
}
}
}
}
public class PickingViewHolder : RecyclerView.ViewHolder
{
public LinearLayout MainLinearLayout { get; set; }
public TextView LblBranch { get; set; }
public CheckBox BranchCodeCheckBox { get; set; }
public bool IsChecked { get; set; }
public PickingViewHolder(View itemView):base(itemView)
{
//Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
MainLinearLayout = itemView.FindViewById<LinearLayout>(Resource.Id.linearLayout1);
LblBranch = itemView.FindViewById<TextView>(Resource.Id.textViewBranch);
BranchCodeCheckBox = itemView.FindViewById<CheckBox>(Resource.Id.checkBoxSelect);
// Detect user clicks on the item view and report which item
// was clicked (by layout position) to the listener:
// itemView.Click += (sender, e) => listener(base.LayoutPosition);
BranchCodeCheckBox.Click += delegate
{
if (BranchCodeCheckBox.Checked)
{
IsChecked = true;
}
else
{
IsChecked = false;
}
};
}
}
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
}
}
public class CheckedChangeListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
{
public Activity activity;
string name;
public CheckedChangeListener(Activity activity)
{
this.activity = activity;
}
public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
{
if (isChecked)
{
name = (string)buttonView.Tag;
GlobalVariable.SelectedBranchCode.Add(name);
}
else if (!isChecked)
{
foreach (var a in GlobalVariable.SelectedBranchCode)
{
GlobalVariable.SelectedBranchCode.Remove(name);
break;
}
}
}
}
}
When use a separate dataset(Dictionary<int, bool> map) to store the position, you need to deal with the Item data and position separately.
private Dictionary<int, bool> map = new Dictionary<int, bool>();
Try another method, just add a field in your Object model : Info_LoadBranch. For example:
public bool isChecked { get; set; }
And initialize the variable to false.
And When you check (or uncheck) the checkBox, you can refer to the following code:
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;
//***********************
Photo item = mPhotoAlbum[position];
//***********************
//vh.MyCheckBox.Tag = position;
vh.Caption.Text = item.Caption;
vh.MyCheckBox.SetOnCheckedChangeListener(null);
vh.MyCheckBox.SetOnCheckedChangeListener(new MyListener(item));
vh.MyCheckBox.Checked = item.isChecked;
}
And MyListener
class MyListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
{
Photo photo;
public MyListener( Photo item)
{
this.photo = item;
}
public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
{
photo.isChecked = isChecked;
}
}
If you want to find the checked Items, you can filter like this:
List<Photo> checkedList = new List<Photo>();
for (int i=0;i< loadBranch.Count;i++) {
Photo temp = loadBranch[i];
if (temp.isChecked) {
checkedList.Add(temp);
}
}
Note: the model Photo is my model, you just use yours.

StartActivityForResult inside adapter from button does not fire OnActivityResult

I have try the following code to fire on activity result inside my atapter, when my button pressed without success. The activity TraEdit is starting correctly and updates my data. I can't refresh my list with NotifyDataSetChanged(), OnActivityResult never fires to control the result.
What i am doing wrong? Is there a way to NotifyDataSetChanged() inside my adapter or i have to try a different approach?
Any help appreciated.
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Views;
using Android.Widget;
namespace Cashier
{
[Activity(Label = "TraBaseAdapter")]
public partial class TraBaseAdapter : BaseAdapter<TraTable>
{
List<TraTable> TraListArrayList;
private LayoutInflater mInflater;
private Context activity;
public TraBaseAdapter(Context context, List<TraTable> results)
{
activity = context;
TraListArrayList = results;
mInflater = (LayoutInflater)activity.GetSystemService(Context.LayoutInflaterService);
}
public override int Count { get { return TraListArrayList.Count; } }
public override long GetItemId(int position) { return position; }
public override TraTable this[int position] { get { return TraListArrayList[position]; } }
public override View GetView(int position, View convertView, ViewGroup parent)
{
TraViewHolder holder = null;
if (convertView == null)
{
convertView = mInflater.Inflate(Resource.Layout.TraRecord_view, null);
holder = new TraViewHolder
{
TxtBtnEdit = convertView.FindViewById<Button>(Resource.Id.TraEditButtonHolder),
TxtTraName = convertView.FindViewById<TextView>(Resource.Id.TraNameHolder),
TxtTraCode = convertView.FindViewById<TextView>(Resource.Id.TraCodeHolder)
};
if (!holder.TxtBtnEdit.HasOnClickListeners)
{
holder.TxtBtnEdit.Click += (sender, e) =>
{
TraEditClick(holder);
};
}
convertView.Tag = holder;
}
else { holder = convertView.Tag as TraViewHolder; }
holder.LineId = position;
holder.TraId = TraListArrayList[position].Cs_Traid;
holder.TxtBtnEdit.Tag = holder.LineId + 1;
holder.TxtTraName.Text = TraListArrayList[position].Cs_Name;
holder.TxtTraCode.Text = TraListArrayList[position].Cs_Code;
return convertView;
}
private void TraEditClick(TraViewHolder LineHolder)
{
Intent ActivityAddEditTra = new Intent(this.activity, typeof(TraEdit));
ActivityAddEditTra.PutExtra("TraIdSel", TraListArrayList[LineHolder.LineId].Cs_Traid);
ActivityAddEditTra.PutExtra("NameSel", TraListArrayList[LineHolder.LineId].Cs_Name);
ActivityAddEditTra.PutExtra("TraCodeSel", TraListArrayList[LineHolder.LineId].Cs_Code);
((Activity)activity).StartActivityForResult(ActivityAddEditTra, 99);
}
public void OnActivityResult(int RequestCode, Result ResultCode, Intent Data)
{
if (ResultCode == Result.Ok & RequestCode == 99)
{
int RowUpdate = Data.GetIntExtra("RowUpdate", 0);
NotifyDataSetChanged();
Toast.MakeText(activity, "Data changes :" + RowUpdate.ToString(), ToastLength.Short).Show();
}
}
public class TraViewHolder : Java.Lang.Object
{
public TextView TxtTraCode { get; set; }
public TextView TxtTraName { get; set; }
public Button TxtBtnEdit { get; set; }
public int LineId { get; set; }
public int TraId { get; set; }
}
}
}
In TraEdit:
......
Intent RetunData = new Intent();
SetResult(Result.Ok, RetunData);
RetunData.PutExtra("RowUpdate", RowsUpd);
......
Maybe
RetunData.PutExtra("RowUpdate", RowsUpd);
should come before
SetResult(Result.Ok, RetunData);
Im not good with VS but maybe the OnActivityResult method must be in the Activity not in the adapater

Xamarin.android - get information from a ListView

i'm new on Xamarin, i created a view where i'm showing a list of items, i created activity, axml files and style. It work well.
Now i would like start a "intent" on item selected but i have problem to get position or title of item.
My "Console.WriteLine(selectedFromList)" show just 0 value, i would like get more information from my item selected, like the right position or title, so i can validate and "intent" my specific activities for each item selected.
namespace app_sofis.Droid
{
[Activity(Label = "ServiziActivity" , Theme = "#style/ThemeActionBar")]
public class ServiziActivity : Activity
{
public static int TYPE_ITEM = 0;
public static int TYPE_SEPORATOR = 1;
List<IMenuItemsType> item = new List<IMenuItemsType>();
private ListView lst;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Servizi);
// my items
item.Add(new MenuHeaderItem("Servizi per il paziente"));
item.Add(new MenuContentItem("COLLO", "Inforntuni, patologie, interventi e riabilitazione", Resource.Mipmap.ic_schiena));
item.Add(new MenuContentItem("SPALLA", "Inforntuni, patologie, interventi e riabilitazione", Resource.Mipmap.ic_schiena));
item.Add(new MenuContentItem("SCHIENA", "Inforntuni, patologie, interventi e riabilitazione", Resource.Mipmap.ic_schiena));
lst = FindViewById<ListView>(Resource.Id.lstview);
lst.Adapter = new ListViewAdapter(this, item);
lst.ItemClick += (object sender, Android.Widget.AdapterView.ItemClickEventArgs e) =>
{
// HERE I WOULD LIKE VALIDATE ITEM AND START "intent" with my specific activities :)
string selectedFromList = lst.GetItemAtPosition(e.Position).ToString();
// trying to show item position but it return always 0
Console.WriteLine(selectedFromList);
};
}
// code for my listview
public interface IMenuItemsType
{
int GetMenuItemsType();
}
public class MenuHeaderItem : IMenuItemsType
{
public string HeaderText { get; set; }
public int GetMenuItemsType()
{
return TYPE_ITEM;
}
public MenuHeaderItem(string _headerText)
{
HeaderText = _headerText;
}
}
public class MenuContentItem : IMenuItemsType
{
public string Title { get; set; }
public string SubTitle { get; set; }
public int IconImage { get; set; }
public int GetMenuItemsType()
{
return TYPE_SEPORATOR;
}
public MenuContentItem(string _title, string _subtitle, int _iconImage)
{
Title = _title;
SubTitle = _subtitle;
IconImage = _iconImage;
}
}
public class ListViewAdapter : ArrayAdapter<IMenuItemsType>
{
private Context context;
private List<IMenuItemsType> items;
private LayoutInflater inflater;
public ListViewAdapter(Context context, List<IMenuItemsType> items) : base(context, 0, items)
{
this.context = context;
this.items = items;
this.inflater = (LayoutInflater)this.context.GetSystemService(Context.LayoutInflaterService);
}
public override int Count
{
get
{
//throw new System.NotImplementedException();
return items.Count;
}
}
public override long GetItemId(int position)
{
//throw new System.NotImplementedException();
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
//throw new System.NotImplementedException();
View view = convertView;
try
{
IMenuItemsType item = items[position];
if (item.GetMenuItemsType() == TYPE_ITEM)
{
MenuHeaderItem _headerItem = (MenuHeaderItem)item;
view = inflater.Inflate(Resource.Layout.ListViewHeaderItem, null);
// user dont click header item
view.Clickable = false;
var headerName = view.FindViewById<TextView>(Resource.Id.txtHeader);
headerName.Text = _headerItem.HeaderText;
}
else if (item.GetMenuItemsType() == TYPE_SEPORATOR)
{
MenuContentItem _contentItem = (MenuContentItem)item;
view = inflater.Inflate(Resource.Layout.ListViewContentItem, null);
var _title = view.FindViewById<TextView>(Resource.Id.txtTitle);
var _imgIcon = view.FindViewById<ImageView>(Resource.Id.imgIcon);
var _subTitle = view.FindViewById<TextView>(Resource.Id.txtSubTitle);
_title.Text = _contentItem.Title;
_imgIcon.SetBackgroundResource(_contentItem.IconImage);
_subTitle.Text = _contentItem.SubTitle;
}
}
catch (Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Long);
}
return view;
}
}
}
}
MY CONSOLE RETURN
[ViewRootImpl#1fcd26a[ServiziActivity]] ViewPostImeInputStage processPointer 0
[ViewRootImpl#1fcd26a[ServiziActivity]] ViewPostImeInputStage processPointer 1
app_sofis.Droid.ServiziActivity+MenuContentItem
You can use position to get item from the list:
lst.ItemClick += (object sender, Android.Widget.AdapterView.ItemClickEventArgs e) =>
{
MenuItemsType selectedItem = (MenuItemsType)item[e.Position];
Console.WriteLine(selectedItem.Title);
Console.WriteLine(selectedItem.SubTitle);
};
Hope this helps
I would suggest the following addition to your adapter class:
public override IMenuItemsType this [int index]
{
get { return items[index]; }
}
That way it is easier to access an item at the given position.
lst.ItemClick += (object sender, Android.Widget.AdapterView.ItemClickEventArgs e) =>
{
var selectedFromList = (lst.Adapter as ListViewAdapter)[e.Position];
if(selectedFromList is MenuHeaderItem)
{
var intent = new Intent(this, typeof(YOUR_ACTIVITY1));
StartActivity(intent);
}
if(selectedFromList is MenuContentItem)
{
var intent = new Intent(this, typeof(YOUR_ACTIVITY2));
StartActivity(intent);
}
};

Realm Updating Seekbar

I'm using Realm to save my seekbar updates.
I have a RecyclerView, adding X Items manual to the RecyclerView,
Inside the Items there are settings for the User and i want the settings seperate for each Item.
public static BottomSheet_Faecher newInstance(String mString)
{
BottomSheet_Faecher f = new BottomSheet_Faecher();
Bundle args = new Bundle();
args.PutString("string", mString);
f.Arguments = args;
return f;
}
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
mString = Arguments.GetString("string");
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.Inflate(Resource.Layout.Settings_Faecher_Wertung, container, false);
Fach1 = v.FindViewById<SeekBar>(Resource.Id.seek1);
Fach2 = v.FindViewById<SeekBar>(Resource.Id.seek2);
var prefs = PreferenceManager.GetDefaultSharedPreferences(this.Activity);
bool previouslyStarted = prefs.GetBoolean("first", false);
string name = name = Arguments.GetString("Name");
Ad = realm.All<SAd>().Where(m => m.mName == name).First();
if (!previouslyStarted)
{
wertungen = new HNWertung { HWertung = Fach1.Progress, NhWertung = Fach2.Progress };
realm.Write(() =>
{
Ad.mWertunglist.Add(wertungen);
});
var edit = prefs.Edit();
edit.PutBoolean("first", true);
edit.Commit();
}
var test = realm.All<HNWertung>().First();
Fach1.Progress = test.HauptfachWertung;
Fach2.Progress = test.NebenfachWertung;
//Fach1.Progress = L;
//Fach2.Progress = ListWertung.NebenfachWertung;
Fach1.ProgressChanged += Fach1_ProgressChanged;
Fach2.ProgressChanged += Fach2_ProgressChanged;
return v;
}
private void Fach2_ProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e)
{
Fach1.Progress = 100 - e.Progress;
}
private void Fach1_ProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e)
{
Fach2.Progress = 100 - e.Progress;
}
public override void OnDestroy()
{
base.OnDestroy();
}
And how can i update/ save the Progress, after the Fragment is destroyed
and how can i reach the updated Progress
//Edit
public class StufeAdapter : RecyclerView.Adapter
{
public event EventHandler<int> ItemClick;
private RecyclerView mRecyclerView;
private List<StufeAd> mStufenListe;
Realm realm = Realm.GetInstance();
public StufeAdapter(List<StufeAd> stufenListe, RecyclerView recyclerView)
{
mStufenListe = stufenListe;
mRecyclerView = recyclerView;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
var viewholder = holder as StufeViewHolder;
viewholder.StufenPhoto.SetImageResource(mStufenListe[position].mPhoto);
viewholder.Stufe.Text = mStufenListe[position].mName;
viewholder.Durchschnitt.Text = mStufenListe[position].mDurchschnitt.ToString();
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.CardView_Stufe_Row, parent, false);
StufeViewHolder vh = new StufeViewHolder(view, OnClick);
return vh;
}
public override int ItemCount
{
get
{
return mStufenListe.Count;
}
}
//Realm Object
public class StufeAd : RealmObject
{
[PrimaryKey]
public string mName { get; set; }
public int mPhoto { get; set; }
public int mDurchschnitt { get; set; }
public IList<HNWertung> mWertunglist { get; }
}
public class HNWertung : RealmObject
{
public int HauptfachWertung { get; set; }
public int NebenfachWertung { get; set; }
}
So assuming you have a RecyclerView that looks like:
We can create a matching RealmObject that persists your data.
RealmObject:
public class ARealmObject : RealmObject
{
[PrimaryKey] // Use Gap-less Primary keys for super fast RecyclerView, otherwise you have to create a "positional" RealmObject mapping
public int Key { get; set; } // zero-based for RecyclerView Adapter
public string Caption { get; set; }
public int SeekBar1 { get; set; }
public int SeekBar2 { get; set; }
}
We can create a RecyclerView.Adapter that pulls the data from your Realm instance and persists user changes changes to each SeekBar.
RecyclerView.Adapter:
public class RealmAdapter : RecyclerView.Adapter
{
Realm realm;
IQueryable<ARealmObject> realmobjects;
public RealmAdapter(RealmConfiguration config)
{
realm = Realm.GetInstance(config);
realmobjects = realm.All<ARealmObject>();
}
public class RealmObjectViewHolder : RecyclerView.ViewHolder
{
readonly Timer timer;
readonly Realm realm;
ARealmObject aRealmObject;
string lastCaption;
public RealmObjectViewHolder(View view, Realm realm) : base(view)
{
this.realm = realm;
Caption = view.FindViewById<TextView>(Resource.Id.realmTextView);
SeekBar1 = view.FindViewById<SeekBar>(Resource.Id.seekBar1);
SeekBar2 = view.FindViewById<SeekBar>(Resource.Id.seekBar2);
SeekBar1.StopTrackingTouch += SeekBar_HandleEventHandler;
SeekBar2.StopTrackingTouch += SeekBar_HandleEventHandler;
}
public TextView Caption { get; private set; }
public SeekBar SeekBar1 { get; private set; }
public SeekBar SeekBar2 { get; private set; }
public int Key
{
get { return aRealmObject.Key; }
set
{
aRealmObject = realm.Find<ARealmObject>(value);
aRealmObject = aRealmObject ?? new ARealmObject { Key = value, Caption = $"missing key : {value}", SeekBar1 = 50, SeekBar2 = 50 };
Caption.Text = aRealmObject.Caption;
lastCaption = Caption.Text;
SeekBar1.Progress = aRealmObject.SeekBar1;
SeekBar2.Progress = aRealmObject.SeekBar2;
}
}
void SeekBar_HandleEventHandler(object sender, SeekBar.StopTrackingTouchEventArgs e)
{
UpdateRealmObject();
}
void UpdateRealmObject()
{
if (aRealmObject.Caption != Caption.Text || aRealmObject.SeekBar1 != SeekBar1.Progress || aRealmObject.SeekBar2 != SeekBar2.Progress)
{
lastCaption = Caption.Text;
realm.Write(() =>
{
aRealmObject.SeekBar1 = SeekBar1.Progress;
aRealmObject.SeekBar2 = SeekBar2.Progress;
realm.Add(aRealmObject, true); // Using the optional update: parameter set to true
});
}
}
}
public override int ItemCount
{
get { return realmobjects.Count(); }
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
var vh = holder as RealmObjectViewHolder;
vh.Key = position;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
var itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.ARealmObjectCardView, parent, false);
var vh = new RealmObjectViewHolder(itemView, realm);
return vh;
}
}
Example Usage w/ 10,000 test items:
[Activity(Label = "RecyclerViewWithRealm", MainLauncher = true, Icon = "#mipmap/icon")]
public class MainActivity : Activity
{
RecyclerView recyclerView;
RecyclerView.Adapter adapter;
RecyclerView.LayoutManager layoutManager;
Realm masterRealmInstance;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
masterRealmInstance = Realm.GetInstance("RecyclerViewExample.realm");
if (masterRealmInstance.All<ARealmObject>().Count() == 0)
{
masterRealmInstance.Write(() => // Create some test data
{
for (int i = 0; i < 10000; i++)
{
masterRealmInstance.Add(new ARealmObject { Key = i, Caption = $"StackOverFlow # + {i.ToString()}", SeekBar1 = 50, SeekBar2 = 50 });
}
});
}
SetContentView(Resource.Layout.ARecyclerLayOut);
recyclerView = (RecyclerView)FindViewById(Resource.Id.recyclerView);
recyclerView.HasFixedSize = true;
layoutManager = new LinearLayoutManager(this);
recyclerView.SetLayoutManager(layoutManager);
adapter = new RealmAdapter((RealmConfiguration)masterRealmInstance.Config);
recyclerView.SetAdapter(adapter);
}
}
Change the values of any of the individual SeekBars exit and restart the application and your changes will be reloaded:

Xamarin - Recycled View gives errors

I'm new to app development and I'm trying to create a Recycled View on a Fragment, however there are some problems, it throws the following errors:
Code:
namespace Homecheck.Fragments {
public class SmokeSensor : Fragment {
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private List<ItemData> itemData;
public override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
recyclerView.HasFixedSize = true;
layoutManager = new LinearLayoutManager(Activity);
recyclerView.SetLayoutManager(layoutManager);
itemData = new List<ItemData>();
itemData.Add(new ItemData() {title = "Testing", image = Resource.Drawable.ic_circle_red});
adapter = new MyAdapter(itemData);
recyclerView.SetAdapter(adapter);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.Inflate(Resource.Layout.SmokeSensor, container, false);
recyclerView = view.FindViewById<RecyclerView>(Resource.Id.smoke_recycler_view);
return view;
}
}
public class MyAdapter : RecyclerView.Adapter {
private List<ItemData> itemData;
private TextView titleText;
private ImageView imageId;
public MyAdapter(List<ItemData> itemData) {
this.itemData = itemData;
}
public class ViewHolder : RecyclerView.ViewHolder {
public View mainView { get; set; }
public TextView title { get; set; }
public ImageView image { get; set; }
public ViewHolder (View view) : base (view) {
mainView = view;
}
}
public override MyAdapter.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SmokeItemView, null);
titleText = itemLayoutView.FindViewById<TextView>(Resource.Id.item_title);
imageId = itemLayoutView.FindViewById<ImageView>(Resource.Id.item_icon);
ViewHolder viewHolder = new ViewHolder(itemLayoutView) { title = titleText, image = imageId };
return viewHolder;
}
public override void OnBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.title.SetText(itemData[position]);
}
public override int getItemCount() {
return itemData.Count();
}
}
public class ItemData {
public string title { get; set; }
public int image { get; set; }
}
}
I know it's most likely a stupid mistake, but I can't seem to find it and fix it.
The return type of OnCreateViewHolder is wrong, it should be Android.Support.V7.Widget.RecyclerView.ViewHolder
You need to override ItemCount:
public override int ItemCount {get{...}}
Wrong parameter type, fix it like this:
public override void OnBindViewHolder(Android.Support.V7.Widget.RecyclerView.ViewHolder viewHolder, int position)

Categories

Resources