I have a listview with a button in it. if i click this button the row it is in needs to be deleted. it "kinda" works, the only thing that is giving me issues is that it does not refresh good. only if i go out and back in the list its gone. or if i flip my screen.
this is the code i have at the moment.
using System;
using System.Collections.Generic;
using Android.App;
using Android.Graphics;
using Android.Views;
using Android.Widget;
using CardAppReal.Lib.Models;
using NavigationDrawerTest;
using Square.Picasso;
using SQLite;
using Path = System.IO.Path;
namespace CardAppReal.Assets
{
public class ListAdapter : BaseAdapter<Card>
{
List<Card> items;
Activity context;
public ListAdapter(Activity context, List<Card> items)
: base()
{
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override Card this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(NavigationDrawerTest.Resource.Layout.CardSavedRowLayout, null);
view.FindViewById<TextView>(NavigationDrawerTest.Resource.Id.TextCardSavedList1).Text = item.name;
view.FindViewById<TextView>(NavigationDrawerTest.Resource.Id.TextCardSavedList2).Text = item.supertype;
view.FindViewById<TextView>(NavigationDrawerTest.Resource.Id.TextCardSavedList3).Text = item.set;
Picasso.With(context).Load(item.imageUrl).Into(view.FindViewById<ImageView>(NavigationDrawerTest.Resource.Id.CardSavedImage));
var imgButton = view.FindViewById<ImageButton>(NavigationDrawerTest.Resource.Id.ImgButtonSaved);
Picasso.With(context).Load(Resource.Drawable.delete).Into(imgButton);
view.SetBackgroundColor(Color.Argb(150, 153, 217, 234));
imgButton.Tag = item.id;
imgButton.SetOnClickListener(new ButtonClickListener(this.context, this));
return view;
}
private class ButtonClickListener : Java.Lang.Object, View.IOnClickListener
{
private Activity activity;
private ListAdapter adapter;
public ButtonClickListener(Activity activity, ListAdapter adapter)
{
this.activity = activity;
this.adapter = adapter;
}
public void OnClick(View v)
{
string name = (string)v.Tag;
string text = $"{name} Button Click.";
Toast.MakeText(this.activity, text, ToastLength.Short).Show();
string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),
"database.db3");
var db = new SQLiteConnection(folder);
db.Delete<Card>(v.Tag.ToString());
adapter.NotifyDataSetChanged();
}
}
}
}
i tried giving the adapter to the listener but that does not really work.
Related
I have created a project in which I am retrieving data from the database and display it into a ListView. See image below.
Here is the code for retrieving data for the ListView
public class MainActivity : Activity
{
public static Context context;
public static List<UserInfo> UserInfoList = new List<UserInfo>();
public static ListView ListView;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView (Resource.Layout.Main);
ListView = FindViewById<ListView>(Resource.Id.Listview);
GetList list = new GetList();
list.Execute();
}
public class GetList : AsyncTask
{
Context con;
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient( );
var _WebApiUrl = string.Format("URL");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage messge = client.GetAsync(_WebApiUrl).Result;
var Return_EventList = messge.Content.ReadAsStringAsync().Result;
var EventList = JsonConvert.DeserializeObject<List<UserInfo>>(Return_EventList);
foreach (var data in EventList)
{
UserInfoList.Add(data);
}
return true;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
ListView.Adapter = new UserInfoListAdapter(context, UserInfoList);
}
}
class UserInfoListAdapter : BaseAdapter<UserInfo>
{
private List<UserInfo> mItem = new List<UserInfo>();
private Context context;
public UserInfoListAdapter(Context mcontext, List<UserInfo> mItems)
{
mItem.Clear();
mItem = mItems;
context = mcontext;
this.NotifyDataSetChanged();
}
public override UserInfo this[int position]
{
get
{
return mItem[position];
}
}
public override int Count
{
get
{
return mItem.Count;
}
}
public Context MContext { get; private set; }
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View listitem = convertView;
listitem = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.ListViewDesign, parent, false);
TextView TxtName = listitem.FindViewById<TextView>(Resource.Id.TxtName);
TextView TxtNumber = listitem.FindViewById<TextView>(Resource.Id.TxtNumber);
TxtName.Text = mItem[position].firstname;
TxtNumber.Text = mItem[position].contact_no;
listitem.Click += (object sender, EventArgs e) =>
{
Toast.MakeText(parent.Context, "Clicked " + mItem[position].firstname, ToastLength.Long).Show();
};
return listitem;
}
}
}
I want to put buttons in the ListView, one per row. Here is the example of how I want to implement it
Now when user click on button, a pdf file should download based on current id from database. For example in my database xray id is 1, so when user download pdf for xray it should download based on id which is 1
Place TableLayout in your 'ListViewDesign' android layout in order to
get required view (or it can be achieved by Linear Layout by setting
its orientation horizontal and its layout_weight)
Place Button in Fourth Column
Remove Click Event from GetView Method
Access Button in GetView Method
Button DownloadButton = view.FindViewbyId<Button>(Resource.Id.btn_download);
DownloadButton.Click += delegate { DownloadFile( link + mItem[position].Id ) };
Add Namespaces
using System.Net;
using System.IO;
using System.Text;
Add a new method in your listView Adapter Class
private void DownloadFile(string url)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += (s, e) => {
var text = e.Result; // get the downloaded text
string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string localFilename = "downloaded.txt";
string localPath = Path.Combine(documentsPath, localFilename);
File.WriteAllText(localPath, text); // writes to local storage
};
var url = new Uri("http://xamarin.com");
webClient.Encoding = Encoding.UTF8;
webClient.DownloadStringAsync(url);
RunOnUiThread(() => {
Toast.MakeText(this, "Download Completed", ToastLength.Short).Show();
});
}
I'm trying to make Master and Details Application for learning purpose.
In my recyclerview, When I click item I want to start new activity and send data to a new activity.
I was making it in listview examples, but I struggled here.
This is my Adapter
using Android.App;
using Android.Widget;
using Android.OS;
using System.Threading.Tasks;
using System;
using System.Threading;
using System.Collections.Generic;
using Android.Content;
using Newtonsoft.Json;
using Petrolium.DataObjects;
using Petrolium.Utilities;
using Petrolium.Activities;
using Android.Support.V7.Widget;
using Android.Views;
using static Android.Support.V7.Widget.RecyclerView;
namespace Petrolium.Adapters
{
public class CompanyRecyclerAdapter : RecyclerView.Adapter
{
static List<Company> _companies = new List<Company>();
public CompanyRecyclerAdapter(Context context, List<Company> companies) => _companies = companies;
public override int ItemCount => _companies.Count;
private class CompanyViewHolder : ViewHolder
{
public ImageView companyImageView
{
get;
set;
}
public TextView companyNameView
{
get;
set;
}
public CompanyViewHolder(View itemView) : base(itemView)
{
companyImageView = itemView.FindViewById<ImageView>(Resource.Id.company_image);
companyNameView = itemView.FindViewById<TextView>(Resource.Id.company_name);
itemView.Click += (sender, e) =>
{
var context = itemView.Context;
Intent intent = new Intent(context, typeof(DetailsActivity));
intent.PutExtra(GetText(Resource.String.DetailsStringToJSON),
JsonConvert.SerializeObject(_companies[e.Position].Fuels));
StartActivity(intent);
};
}
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
CompanyViewHolder vh = holder as CompanyViewHolder;
vh.companyImageView.SetImageResource(Resource.Drawable.gulf);
vh.companyNameView.Text = _companies[position].Name;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemview = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.Company, parent, false);
CompanyViewHolder vh = new CompanyViewHolder(itemview);
return vh;
}
}
}
But there isn't GetText method, also e. doesn't have any Position field or property.
Also, there isn't StartActivity method to pass my intent on it.
What is best-practice to make itemClick in recyclerView and start a new activity? How to handle this problem?
I'm the beginner in android development and sorry if I'm asking something simple.
Your ViewHolder should be just pass out the click event to the Adapter then back to the Fragment or Activity to handle the event.
public CompanyViewHolder(View itemView, Action<int> listener) : base(itemView)
{
companyImageView = itemView.FindViewById<ImageView>(Resource.Id.company_image);
companyNameView = itemView.FindViewById<TextView>(Resource.Id.company_name);
itemView.Click += (sender, e) => listener (base.LayoutPosition);
}
Then in your adapter should have an event to let Fragment or Activity to bind to:
public class CompanyRecyclerAdapter : RecyclerView.Adapter
{
public event EventHandler<int> ItemClick;
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
}
...
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemview = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.Company, parent, false);
CompanyViewHolder vh = new CompanyViewHolder(itemview, OnClick);
return vh;
}
}
Then finally in your Fragment or Activity you can bind to the ItemClick event in Adapter to handle it:
mAdapter = new CompanyRecyclerAdapter(mPhotoAlbum);
mAdapter.ItemClick += OnItemClick;
Hi guys I have a problem. I have a DialogFragment with content that is saved in a sqlite db on the phone, and a Fragment that retrieves the information and shows it. The ListView initially (upon creation) shows everything like its supposed to, but when the stuff is updated inside the Dialog Fragment, I dont know how to update the adapter for ListView. Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
namespace Zrelya.Fragments
{
public class OnSelectedEventArgs : EventArgs
{
public ORM.Plan Plan { get; set; }
public OnSelectedEventArgs( ORM.Plan plan )
{
Plan = plan;
}
}
public class ViewPlans : FragmentSuper
{
private Context mContext;
private ORM.DBRep dbr;
public EventHandler<OnSelectedEventArgs> OnSelected;
public ViewPlans(Context context)
{
mContext = context;
}
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
dbr = new ORM.DBRep();
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
var view = inflater.Inflate(Resource.Layout.ViewPlans, container, false);
var listView = view.FindViewById<ListView>(Resource.Id.listView);
List<ORM.Plan> plansList = dbr.GetPlans();
Adapters.Plan adapter = new Adapters.Plan(mContext, plansList);
listView.Adapter = adapter;
listView.ItemClick += (o, e) =>
{
int id = plansList[e.Position].Id;
OnSelected.Invoke(this, new OnSelectedEventArgs(plansList[e.Position]));
};
return view;
}
}
}
OnSelected.Invoke is what happens when an item is clicked, showing the dialog fragment. The following code is a snippet from MainActivity OnCreate method:
fragmentViewPlans.OnSelected += (o, e) =>
{
int id = e.Plan.Id;
DialogViewPlan(e.Plan);
};
...and the DialogViewPlan method is below:
private void DialogViewPlan(ORM.Plan plan)
{
if (plan != null)
{
Android.App.FragmentTransaction transaction = FragmentManager.BeginTransaction();
Helpers.DialogViewPlan dialog = new Helpers.DialogViewPlan(this, plan);
dialog.Show(transaction, "dialog");
dialog.OnDelete += delegate
{
Toast.MakeText(this, "Plan deleted...", ToastLength.Short).Show();
};
dialog.OnSave += delegate
{
Toast.MakeText(this, "Plan saved!", ToastLength.Short).Show();
};
}
}
I dont know how to talk between activity, fragment and dialog fragment, does anyone know how to do this?
I found an answer:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
namespace Zrelya.Fragments
{
public class OnSelectedEventArgs : EventArgs
{
public ORM.Plan Plan { get; set; }
public OnSelectedEventArgs( ORM.Plan plan )
{
Plan = plan;
}
}
public class ViewPlans : FragmentSuper
{
private Context mContext;
private ORM.DBRep dbr;
private static Adapters.Plan Adapter;
private static ListView listView;
public EventHandler<OnSelectedEventArgs> OnSelected;
public ViewPlans(Context context)
{
mContext = context;
}
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
dbr = new ORM.DBRep();
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
var view = inflater.Inflate(Resource.Layout.ViewPlans, container, false);
listView = view.FindViewById<ListView>(Resource.Id.listView);
List<ORM.Plan> plansList = dbr.GetPlans();
Adapter = new Adapters.Plan(mContext, plansList);
listView.Adapter = Adapter;
listView.ItemClick += (o, e) =>
{
int id = plansList[e.Position].Id;
var plan = plansList[e.Position];
DialogViewPlan(plan);
};
return view;
}
private void DialogViewPlan(ORM.Plan plan)
{
if (plan != null)
{
FragmentTransaction transaction = Activity.FragmentManager.BeginTransaction();
Helpers.DialogViewPlan dialog = new Helpers.DialogViewPlan(Activity, plan);
dialog.Show(transaction, "dialog");
dialog.OnDelete += delegate
{
Adapter = new Adapters.Plan(mContext, dbr.GetPlans());
listView.Adapter = Adapter;
};
dialog.OnSave += delegate
{
Adapter = new Adapters.Plan(mContext, dbr.GetPlans());
listView.Adapter = Adapter;
};
}
}
}
}
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; }
}
I have a Listview and in it are 4 different kinds of views. One of them should be a ViewPager (like in the playstore). Using a PagerAdapter I have put the Viewpager in the Listview with 3 pictures. But I can't get it as smooth as the PlayStore.
Has anyone tried this before and succeeded in this?
My Getview in the adapter looks like this:
public override View GetView(int position, View convertView, ViewGroup parent)
{
int type = position;
if (convertView == null) {
switch (type) {
case 0:
convertView = inflater.Inflate (Resource.Layout.DetailHeader, null);
TextView tv = convertView.FindViewById<TextView> (Resource.Id.Title);
tv.Text = Info.title;
ImageView iv = convertView.FindViewById<ImageView> (Resource.Id.iconImage);
iv.SetImageDrawable (Info.icon);
Button Button = convertView.FindViewById<Button> (Resource.Id.Button);
installButton.Text = "";
installButton.Click += delegate {
confirm ();
};
break;
case 1:
convertView = inflater.Inflate (Resource.Layout.DetailScroller, null);
ImageViewPager adapter = new ImageViewPager (context, appInfo.shots);
ViewPager myPager = convertView.FindViewById<ViewPager> (Resource.Id.imagepager);
myPager.Adapter = adapter;
myPager.SetCurrentItem (0, true);
break;
case 2:
convertView = inflater.Inflate (Resource.Layout.DetailInfo, null);
TextView infoView = convertView.FindViewById<TextView> (Resource.Id.textView);
infoView.Text = "Information";
break;
case 3:
convertView = inflater.Inflate (Resource.Layout.DetailInfo, null);
TextView descView = convertView.FindViewById<TextView> (Resource.Id.textView);
descView.Text = "Description";
break;
}
}
}
ImageViewPager:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
namespace EnterpriseAppstore
{
class ImageViewPager : PagerAdapter
{
Activity activity;
Android.Graphics.Drawables.BitmapDrawable[] imageArray;
public ImageViewPager(Activity act, Android.Graphics.Drawables.BitmapDrawable[] imgArray) {
imageArray = imgArray;
activity = act;
}
public override int Count {
get {
return imageArray.Length;
}
}
public override Java.Lang.Object InstantiateItem (View p0, int p1)
{
ImageView view = new ImageView(activity);
view.LayoutParameters = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
view.SetScaleType(ImageView.ScaleType.FitXy);
view.SetImageDrawable(imageArray[p1]);
((ViewPager) p0).AddView(view, 0);
return view;
}
public override bool IsViewFromObject (View p0, Java.Lang.Object p1)
{
return p0 == ((View) p1);
}
public override void DestroyItem (View p0, int p1, Java.Lang.Object p2)
{
((ViewPager) p0).RemoveView((View) p2);
}
}
}