I am implementing recyclerview in my xamarin android application and it is working in a very weird way
first when I hardcode item(data) in list my application halts and when I put data into list using database it doesn't stop working but doeesn't show any view.
Here is my HomeActivity.cs Code
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.Home);
InitData();
recycler = FindViewById<RecyclerView>(Resource.Id.recyclerView1);
recycler.HasFixedSize = true;
// layoutManager = new LinearLayoutManager(this);
layoutManager = new GridLayoutManager(this, 1, GridLayoutManager.Horizontal, false);
recycler.SetLayoutManager(layoutManager);
adapter = new RecyclerViewAdapter(lstData);
recycler.SetAdapter(adapter);
}
private void InitData()
{
//foreach (var item in await IssueController.FetchPostList())
//{
// lstData.Add(item);
//}
lstData.Add(new Data()
{
IssueImage = "base64stringofimage",
UserImage = "base64stringofimage",
IssueDate = DateTime.Now,
UserName = "asadullah",
IssueStatement = "some issue statement"
});
}
I tried debugging to be more specific what is causing in to halt and I realized that it is halting at the end of OnBindViewHolder() method in recyclerviewadapter class.
This is the RecyclerViewAdapter Class:
RecyclerViewAdapter.cs
using Android.Graphics;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using Refractored.Controls;
using System.Collections.Generic;
using System;
using Android.Content;
using AndroidX.Core.Graphics;
namespace FinalProject_PU.Helper
{
class RecyclerViewHolder : RecyclerView.ViewHolder
{
public ImageView imageview { get; set; }
public CircleImageView UserImage { get; set; }
public TextView UserName { get; set; }
public TextView IssueDate { get; set; }
public TextView IssueStatement { get; set; }
Android.Graphics.Typeface tf;
//
// public TextView Description { get; set; }
public RecyclerViewHolder(Android.Views.View itemView) : base(itemView)
{
imageview = itemView.FindViewById<ImageView>(Resource.Id.imageView1);
UserImage = itemView.FindViewById<CircleImageView>(Resource.Id.imgProfile);
UserName = itemView.FindViewById<TextView>(Resource.Id.tvname);
IssueDate = itemView.FindViewById<TextView>(Resource.Id.tvtime);
IssueStatement = itemView.FindViewById<TextView>(Resource.Id.tvinfo);
//beauttification
/*
tf = Typeface.CreateFromAsset(Assets, "Quicksand-Bold.otf");
IssueStatement.SetTypeface(tf, TypefaceStyle.Bold);
tf = Typeface.CreateFromAsset(Assets, "Quicksand-Bold.otf");
UserName.SetTypeface(tf, TypefaceStyle.Bold);
tf = Typeface.CreateFromAsset(Assets, "Quicksand-Bold.otf");
IssueDate.SetTypeface(tf, TypefaceStyle.Bold);
*/
}
}
class RecyclerViewAdapter : RecyclerView.Adapter
{
private List<Data> lstData = new List<Data>();
public RecyclerViewAdapter(List<Data> lstData)
{
this.lstData = lstData;
}
public override int ItemCount
{
get
{
return lstData.Count;
}
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
RecyclerViewHolder viewHolder = holder as RecyclerViewHolder;
byte[] arr0 = Convert.FromBase64String(lstData[position].IssueImage); //IssueImage
Bitmap b0 = BitmapFactory.DecodeByteArray(arr0, 0, arr0.Length);
viewHolder.imageview.SetImageBitmap(b0);
byte[] arr1 = Convert.FromBase64String(lstData[position].UserImage); //UserImage
Bitmap b1 = BitmapFactory.DecodeByteArray(arr1, 0, arr1.Length);
viewHolder.UserImage.SetImageBitmap(b1); //
viewHolder.UserName.Text = lstData[position].UserName;
viewHolder.IssueDate.Text = lstData[position].ElevatedDays;
viewHolder.IssueStatement.Text = lstData[position].IssueStatement;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.From(parent.Context);
Android.Views.View itemView = inflater.Inflate(Resource.Layout.items, parent, false);
return new RecyclerViewHolder(itemView);
}
}
}
Related
I'm trying to load the data from API in custom map (xamarin.forms.maps) when user click on pin to send (index + 1) on the pin like as parameter.
1. Here I set index + 1 on the Address property on the pin:
List<CustomPin> pins = new List<CustomPin>();
for (int i = 0; i < HardcodedLocations.Positions.Count; i++)
{
CustomPin pin = new CustomPin
{
Type = PinType.Place,
Position = HardcodedLocations.Positions[i],
Label = "Xamarin San Francisco Office",
Address = $"{i + 1}",
Name = "Xamarin",
Url = "http://xamarin.com/about/"
};
pins.Add(pin);
customMap.Pins.Add(pin);
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(42.8742, 25.3187), Distance.FromKilometers(250.0)));
}
customMap.CustomPins = pins;
2. In CustomMKAnnotationView class I create property Address:
public class CustomMKAnnotationView : MKAnnotationView
{
public string Name { get; set; }
public string Url { get; set; }
public string Address { get; set; }
public CustomMKAnnotationView(IMKAnnotation annotation, string id)
: base(annotation, id)
{
}
3. In GetViewForAnnotation method in CustomMapRenderer class I appropriate annotationView.Address to be equal on customPin.Address
protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
MKAnnotationView annotationView = null;
if (annotation is MKUserLocation)
return null;
var customPin = GetCustomPin(annotation as MKPointAnnotation);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
annotationView = mapView.DequeueReusableAnnotation(customPin.Name);
if (annotationView == null)
{
annotationView = new CustomMKAnnotationView(annotation, customPin.Name);
annotationView.Image = UIImage.FromFile("pin.png");
annotationView.CalloutOffset = new CGPoint(0, 0);
annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
((CustomMKAnnotationView)annotationView).Name = customPin.Name;
((CustomMKAnnotationView)annotationView).Url = customPin.Url;
((CustomMKAnnotationView)annotationView).Address = customPin.Address;
}
annotationView.CanShowCallout = true;
return annotationView;
}
4. I create a method to get the data from API in CustomMapRenderer class:
string GenerateRequestUri(string endpoint, string date, string id)
{
string requestUri = endpoint;
requestUri += $"?date={date}";
requestUri += $"&id={id}";
requestUri += $"&daysForward=8";
return requestUri;
}
public async Task<IEnumerable<AladinModel>> GetDataFromAPI(string indexOnClick)
{
DateTime dtNow = DateTime.Now;
var dtNowAPI = dtNow.ToString("yyyy-MM-dd");
var listData = new List<AladinModel>();
var result = await _restServiceAPI.GetAladinData(GenerateRequestUri(ConstantsAPI.EndPoint, dtNowAPI, indexOnClick));
foreach (var item in result)
{
var currentData = new AladinModel()
{
Dats = item.Dats,
Ta = item.Ta,
Rh = item.Rh,
Ws = item.Ws,
Rr = item.Rr,
Sr = item.Sr,
Apres = item.Apres
};
listData.Add(currentData);
}
return listData;
}
5. In OnDidSelectAnnotationView method I trying to send the data with MessagingCenter:
void OnDidSelectAnnotationView(object sender, MKAnnotationViewEventArgs e)
{
CustomMKAnnotationView customView = e.View as CustomMKAnnotationView;
customPinView = new UIView();
if (customView.Name.Equals("Xamarin"))
{
customPinView.Frame = new CGRect(0, 0, 200, 84);
var image = new UIImageView(new CGRect(0, 0, 200, 84));
image.Image = UIImage.FromFile("xamarin.png");
customPinView.AddSubview(image);
customPinView.Center = new CGPoint(0, -(e.View.Frame.Height + 75));
e.View.AddSubview(customPinView);
}
string addressIndex = customView.Address;
var result = GetDataFromAPI(addressIndex);
MessagingCenter.Send<object, IEnumerable<AladinModel>>(this, "PinSelected", (IEnumerable<AladinModel>)result);
}
6. In MainPage I trying to receive the data like that:
protected override void OnAppearing()
{
base.OnAppearing();
MarkerPressed();
}
public void MarkerPressed()
{
MessagingCenter.Subscribe<object, IEnumerable<AladinModel>>(this, "PinSelected", (sender, arg) =>
{
var test = arg;
});
}
When I click on the marker I receive error: Specified cast is not valid on this line:
MessagingCenter.Send<object, IEnumerable<AladinModel>>(this, "PinSelected", (IEnumerable<AladinModel>)result);
Đ¢his is my object class:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace pizhevsoft.Models
{
public class ItemsAPI
{
public partial class RootAladinModel
{
[JsonProperty("aladinModel")]
public AladinModel[] AladinModel { get; set; }
}
public partial class AladinModel
{
[JsonProperty("DATS")]
public DateTime Dats { get; set; }
[JsonProperty("TA")]
public double Ta { get; set; }
[JsonProperty("RH")]
public double Rh { get; set; }
[JsonProperty("WS")]
public double Ws { get; set; }
[JsonProperty("RR")]
public double Rr { get; set; }
[JsonProperty("SR")]
public double Sr { get; set; }
[JsonProperty("APRES")]
public double Apres { get; set; }
}
}
}
The main goal when clicking on the marker is to take its index + 1, to pass it as a parameter to API to get the data ?
If there is an easier option or way to deal with the problem please share how to do it?
According to my logic, a method GetDataFromAPI must be created in the CustomMapRenderer class, to be called in OnDidSelectAnnotationView, and data to be sending to the Main project with messaging center ?
GetDataFromAPI is an async method and needs to be called using await
I am implementing recycler view in my Xamarin android application, But Items are not showing on debugging the application altough the InitData() Method is properly executed.
Here is the mainactivity.cs code in which recycler view is implemented:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FinalProject_PU.Helper
{
class Data
{
public string IssueImage { get; set; }
public string UserImage { get; set; }
public string UserName { get; set; }
public DateTime IssueDate { get; set; }
public string IssueStatement { get; set; }
public int GetElevatedDates()
{
var ElevatedDays = (IssueDate.Date - DateTime.Now.Date).Days;
return ElevatedDays;
}
public string ElevatedDays
{
get { return ElevatedDays; }
set
{
if (GetElevatedDates() == 0)
{
ElevatedDays = "Today";
}
else
{
ElevatedDays = GetElevatedDates() + "Days";
}
}
}
}
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.Home);
byte[] arr = Convert.FromBase64String(UserInfoHolder.Profile_pic);
imgwriteIssue = (ImageView)FindViewById(Resource.Id.imgwriteIssue);
imgwriteIssue.Click += delegate
{
var i = new Intent(this, typeof(CreateIssue));
this.StartActivity(i);
};
CircleImageView img = FindViewById<CircleImageView>(Resource.Id.circleImageView1);
Android.Graphics.Bitmap bitmap = BitmapFactory.DecodeByteArray(arr, 0, arr.Length);
img.SetImageBitmap(bitmap);
iconfunds = (ImageView)FindViewById(Resource.Id.iconFunds);
iconfunds.Click += Iconfunds_Click;
notifications = (ImageView)FindViewById(Resource.Id.iconNotifications);
notifications.Click += Notifications_Click;
map = (ImageView)FindViewById(Resource.Id.iconMap);
map.Click += Map_Click;
setting = (ImageView)FindViewById(Resource.Id.iconSettings);
setting.Click += Setting_Click;
recycler = FindViewById<RecyclerView>(Resource.Id.recyclerView1);
recycler.HasFixedSize = true;
// layoutManager = new LinearLayoutManager(this);
layoutManager = new GridLayoutManager(this, 1, GridLayoutManager.Horizontal, false);
recycler.SetLayoutManager(layoutManager);
InitData();
adapter = new RecyclerViewAdapter(lstData);
recycler.SetAdapter(adapter);
}
private async void InitData()
{
lstData = await IssueController.FetchPostList();
}
fetchallpost() method fetch all the issues from data and return a list of it.
but it is not showing in recycler view and application is halting in a few seconds after opening Homeactivity.cs
Here is the recycler view adapter class on which my programs breaks automatially
RecyclerViewAdapter.cs
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using Refractored.Controls;
using System.Collections.Generic;
using System;
using Android.Content;
using AndroidX.Core.Graphics;
namespace FinalProject_PU.Helper
{
class RecyclerViewHolder : RecyclerView.ViewHolder
{
public ImageView imageview { get; set; }
public CircleImageView UserImage { get; set; }
public TextView UserName { get; set; }
public TextView IssueDate { get; set; }
public TextView IssueStatement { get; set; }
Android.Graphics.Typeface tf;
//
// public TextView Description { get; set; }
public RecyclerViewHolder(Android.Views.View itemView) : base(itemView)
{
imageview = itemView.FindViewById<ImageView>(Resource.Id.imageView1);
UserImage = itemView.FindViewById<CircleImageView>(Resource.Id.imgProfile);
UserName = itemView.FindViewById<TextView>(Resource.Id.tvname);
IssueDate = itemView.FindViewById<TextView>(Resource.Id.tvtime);
IssueStatement = itemView.FindViewById<TextView>(Resource.Id.tvinfo);
//beauttification
/*
tf = Typeface.CreateFromAsset(Assets, "Quicksand-Bold.otf");
IssueStatement.SetTypeface(tf, TypefaceStyle.Bold);
tf = Typeface.CreateFromAsset(Assets, "Quicksand-Bold.otf");
UserName.SetTypeface(tf, TypefaceStyle.Bold);
tf = Typeface.CreateFromAsset(Assets, "Quicksand-Bold.otf");
IssueDate.SetTypeface(tf, TypefaceStyle.Bold);
*/
}
}
class RecyclerViewAdapter : RecyclerView.Adapter
{
private List<Data> lstData = new List<Data>();
public RecyclerViewAdapter(List<Data> lstData)
{
this.lstData = lstData;
}
public override int ItemCount
{
get
{
return lstData.Count;
}
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
RecyclerViewHolder viewHolder = holder as RecyclerViewHolder;
byte[] arr0 = Convert.FromBase64String(lstData[position].IssueImage); //IssueImage
Bitmap b0 = BitmapFactory.DecodeByteArray(arr0, 0, arr0.Length);
viewHolder.imageview.SetImageBitmap(b0);
byte[] arr1 = Convert.FromBase64String(lstData[position].UserImage); //UserImage
Bitmap b1 = BitmapFactory.DecodeByteArray(arr1, 0, arr1.Length);
viewHolder.UserImage.SetImageBitmap(b1); //
viewHolder.UserName.Text = lstData[position].UserName;
viewHolder.IssueDate.Text = lstData[position].ElevatedDays;
viewHolder.IssueStatement.Text = lstData[position].IssueStatement;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.From(parent.Context);
Android.Views.View itemView = inflater.Inflate(Resource.Layout.items, parent, false);
return new RecyclerViewHolder(itemView);
}
}
}```
I have tried debugging the application to see what is causing the problem and it was found out that application is breaking when it reaches on this line in recycler view constructor.
I have made sure that the fetchallpost() method is actually returning list with data.
imageview = itemView.FindViewById<ImageView>(Resource.Id.imageView1);
please help me with this
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
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:
I'm tring to create a ListView which is fed data from an SQLite Database (pre-existing db file). The ListView uses a custom row which is one of the aspects which baffle me; How do I extract the data and then assign it to a TextView in the custom row?
I'm new to Xamarin, so would really appreciate any guidance you can give me on this, Thank you!
Current Dialog Box Error When Run:
Java.Lang.ClassNotFoundException: Didn't find class "md5c4f65b5cf99ab8e97737acf0f8ec7efd.DBHelper" on path: DexPathList[[zip file "/data/app/AppName.Droid-1/base.apk"],nativeLibraryDirectories=[/data/app/AppName.Droid-1/lib/arm, /system/fake-libs, /data/app/AppName.Droid-1/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
'MainActivity':
public class EateriesActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Title = "Find An Eatery";
SetContentView(Resource.Layout.Eateries);
DBHelper db = new DBHelper();
db.CreateDatabase();
db.CreateTable();
var items = db.GetData();
var listView = FindViewById<ListView>(Resource.Id.EateryList_ListView);
listView.Adapter = new ArrayAdapter<string>(this, Resource.Layout.Eatery_ListView_Row, items);
}
}
ListViewAdapter (is this necessary?):
class ListViewAdapter : BaseAdapter<Eatery>
{
private List<Eatery> myItems;
private Context myContext;
public ListViewAdapter(Context context, List<Eatery> items)
{
myItems = items;
myContext = context;
}
public override int Count
{
get { return myItems.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override Eatery this[int position]
{
get
{
return myItems[position];
}
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(myContext).Inflate(Resource.Layout.Eatery_ListView_Row, null, false);
}
TextView placeName = row.FindViewById<TextView>(Resource.Id.placeName);
placeName.Text = myItems[position].Name;
TextView placeTown = row.FindViewById<TextView>(Resource.Id.placeTown);
placeTown.Text = myItems[position].Town;
return row;
}
}
Eatery:
public class Eatery
{
[PrimaryKey]
public string ID { get; set; }
public string Image { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address1 { get; set; }
public string Town { get; set; }
public string PostCode { get; set; }
public string Cuisine { get; set; }
}
DBHelper:
public class DBHelper
{
private static string DB_PATH = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
private static string DB_NAME = "EateryDB.db";
public void CreateDatabase()
{
string dbPath = Path.Combine(DB_PATH, DB_NAME);
var db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dbPath);
}
public void CreateTable()
{
string dbPath = Path.Combine(DB_PATH, DB_NAME);
var db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dbPath);
db.CreateTable<Eatery>();
}
public List<string> GetData()
{
string dbPath = Path.Combine(DB_PATH, DB_NAME);
var db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dbPath);
List<string> data = new List<string>();
foreach (var item in db.Table<Eatery>())
{
var place = item.Name.ToString(); item.Town.ToString();
data.Add(place);
}
return data;
}
Based on your two version of code, I think what you need is adding data from your database to the myItems.
Then you can for example code like this:
List<Eatery> data = new List<Eatery>();
foreach (var item in db.Table<Eatery>())
{
var place = item.Name.ToString();
var location = item.Location.ToString();
var rating = item.Rating;
item.Town.ToString();
data.Add(new Eatery() { PlaceName = place, PlaceLocation = location, PlaceRating = rating });
}
And finally add this data to your adapter as you did when you hard code:
MyListViewAdapter adapter = new MyListViewAdapter(this, data);