Xamarin Image Grid from Folder - c#

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; }
}

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;
}
}

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.Android - Listview within a listview

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);

How to validate a spinner in Xamarin Android

I'm trying to validate a spinner in C# in xamarin in visual studio if the user didn't select an option. similar to setError in TextView, I have seen examples in SO but all of them are for java if I'm not wrong.
This is my spinner
Spinner spinnerJobTypes = FindViewById<Spinner>(Resource.Id.spinnerJobTypes);
and this does not work for me
TextView errorText = (TextView)mySpinner.getSelectedView();
I would like to display this, if the user hasn't selected anything
else if (spinnerJobTypes.SelectedItem.ToString() == "-Select-")
{
//Display validation error
}
Any help is appreciated,
Spinner spinnerJobTypes = FindViewById<Spinner>(Resource.Id.spinnerJobTypes);
spinnerJobTypes.ItemSelected += new EventHandler<AdapterView.ItemSelectedEventArgs> (spinner_ItemSelected);
private void spinner_ItemSelected (object sender, AdapterView.ItemSelectedEventArgs e)
{
Spinner spinner = (Spinner)sender;
string toast = string.Format ("The planet is {0}", spinner.GetItemAtPosition (e.Position));
Toast.MakeText (this, toast, ToastLength.Long).Show ();
}
for reference https://developer.xamarin.com/guides/android/user_interface/spinner/
Edited:
Use this and check
errorText.SetCompoundDrawablesWithIntrinsicBounds(0, 0, Resource.Drawable.errorIcon, 0);
My Suggestion is, add an "None selected" view to the Spinner and use a bool parameter to identify whether user has selected certain item or not:
SpinnerAdapter.cs
public class SpinnerAdapter : BaseAdapter<String>
{
Context context;
List<String> list;
public SpinnerAdapter(Context c, List<String> list)
{
context = c;
this.list = list;
}
public override string this[int position] => list[position-1];
public override int Count => this.list.Count+1;
public override long GetItemId(int position)
{
return 0;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view;
if (position == 0)
{
view = LayoutInflater.From(context).Inflate(Resource.Layout.spinner_error,null);
var txtView = view.FindViewById<TextView>(Resource.Id.tvErr);
view.FindViewById<TextView>(Resource.Id.tvErr).Text = "None Selected";
//uncomment the following line if you want to show the error icon inside of spinner
//view.FindViewById<TextView>(Resource.Id.tvErr).Error = "";
}
else
{
view = convertView;
if (view == null|| view.FindViewById<TextView>(Resource.Id.tvItem)==null)
{
view = LayoutInflater.From(context).Inflate(Resource.Layout.spinner_item, null);
}
view.FindViewById<TextView>(Resource.Id.tvItem).Text = list[position-1];
}
return view;
}
}
MainActivity:
public class MainActivity : Activity
{
Spinner mSpinner;
bool validatePass=false;
TextView tvResult;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
mSpinner = FindViewById<Spinner>(Resource.Id.mSpinner);
var list = InitList();
SpinnerAdapter adapter = new SpinnerAdapter(this, list);
tvResult = FindViewById<TextView>(Resource.Id.tvResult);
mSpinner.Adapter = adapter;
mSpinner.ItemSelected += MSpinner_ItemSelected;
}
private void MSpinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
{
//use validatePass to indicate if user has selected something.
if (e.Position != 0)
{
validatePass = true;
}
else
{
validatePass = false;
}
tvResult.Text ="Validate Result: "+ validatePass.ToString();
}
private List<string> InitList()
{
List<string> list = new List<string>();
for (int i = 0; i < 15; i++)
{
list.Add("Item: " + i);
}
return list;
}
}
But if you really want to show the error icon inside the spinner, you can set the TextView.Error inside of GetView.
Here is my complete Demo:HelloSpinner.

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