Whats going on inside this ListView? - c#

I have a ListView that when I click on an item inside it, a dialog fragment appears with a Save and Delete button. Everything works, and it updates the adapter correctly, removing or updating the items from the ListView. Now the problem is that when I delete the top item, or the item above another item, but lets just say there are two items because its easier. When I delete the top item, it's removed from the ListView, but when I click on the same spot, because now the bottom item moves up to the top, the old item data appears in the DialogFragment. In other words, I'm selecting the old item. Here is the code:
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 ViewPlans : FragmentSuper
{
private Context mContext;
private ORM.DBRep dbr;
private static Adapters.Plan Adapter;
private static ListView listView;
private static List<ORM.Plan> plansList = new List<ORM.Plan>();
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);
plansList = dbr.GetPlans();
Adapter = new Adapters.Plan(mContext, plansList);
listView.Adapter = Adapter;
listView.ItemClick += (o, e) =>
{
Activity.RunOnUiThread(()=> {
plansList = dbr.GetPlans();
DialogViewPlan(plansList[e.Position]);
});
};
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
{
Activity.RunOnUiThread(()=> {
plansList.Remove(plan);
Adapter = new Adapters.Plan(mContext, plansList);
Adapter.NotifyDataSetChanged();
listView.Adapter = Adapter;
});
};
dialog.OnSave += delegate
{
Adapter = new Adapters.Plan(mContext, dbr.GetPlans());
Adapter.NotifyDataSetChanged();
listView.Adapter = Adapter;
};
}
}
}
}

With some help from a few links:
Android: how to remove an item from a listView and arrayAdapter
Remove ListView item by clicking button on the item
The following is your trimmed code, try it.
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 ViewPlans : FragmentSuper
{
private Context mContext;
private ORM.DBRep dbr;
private static Adapters.Plan Adapter;
private static ListView listView;
private static List<ORM.Plan> plansList = new List<ORM.Plan>();
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);
plansList = dbr.GetPlans();
Adapter = new Adapters.Plan(mContext, plansList);
listView.Adapter = Adapter;
listView.ItemClick += (o, e) =>
{
Activity.RunOnUiThread(()=> {
//plansList = dbr.GetPlans();
DialogViewPlan(plansList[e.Position]);
});
};
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
{
Activity.RunOnUiThread(()=> {
plansList.Remove(plan);
//Adapter = new Adapters.Plan(mContext, plansList);
Adapter.NotifyDataSetChanged();
//listView.Adapter = Adapter;
});
};
dialog.OnSave += delegate
{
//Adapter = new Adapters.Plan(mContext, dbr.GetPlans());
Adapter.NotifyDataSetChanged();
//listView.Adapter = Adapter;
};
}
}
}
}

Related

Move Tabs Using Fragment- Nested Tabs

I am new in android, especially in Xamarin Android C#. I have bottom navigation tabs and fragments. They are fragment_picture (tab_picture), fragment home (tab_home), fragment notifications (tab_notifications), fragment_profile (tab_profile). Inside fragment_picture (tab_picture), I have 2 tabs. They are fragment_camera(tab_camera), and fragment_gallery(tab_gallery). I want to move the tabs of fragment_picture such as when I click the tab_camera, it shows the XML of the tab_camera and when I click the tab_gallery, It shows the XML of the tab_gallery.
I don't use viewpager. I am just using fragments. The tab won't change the position to its XML. I've searched a lot in Google But, I still confused. Please help me
using System;
using Android.OS;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Support.V4.App;
using Android.Widget;
namespace MyPhotographicMemory.Droid.Fragments
{
public class Fragment_Picture : Fragment
{
TabLayout tabLayout;
private TabLayout.Tab tabGallery, tabCamera;
Fragment fragment = null;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public static Fragment_Picture NewInstance()
{
var frag2 = new Fragment_Picture { Arguments = new Bundle() };
return frag2;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
var v = inflater.Inflate(Resource.Layout.FragmentPicture, null);
tabLayout = v.FindViewById<TabLayout>(Resource.Id.pictureTabLayout);
tabLayout.TabSelected += (object sender, TabLayout.TabSelectedEventArgs e) =>
{
switch (e.Tab.Position)
{
case Resource.Layout.FragmentCamera: //Resource.Id.tabItem1
fragment = new Fragment_Camera();
TabLayout.Tab tab = tabLayout.GetTabAt(0);
tab.Select();
break;
case Resource.Layout.FragmentGallery: //Resource.Id.tabItem1
fragment = new Fragment_Gallery();
TabLayout.Tab tab1 = tabLayout.GetTabAt(1);
tab1.Select();
break;
}
};
return v;
}
}
}
Do you want to achieve the result like this GIF?
If so, you should achieve the nested tabs with fragment.
Here is my code when in my first fragment.
public class Fragment1 : Fragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public static Fragment1 NewInstance()
{
var frag1 = new Fragment1 { Arguments = new Bundle() };
return frag1;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
var view = inflater.Inflate(Resource.Layout.fragment1, null);
BottomNavigationView bottomNavigationView= view.FindViewById<BottomNavigationView>(Resource.Id.mynested_bottom_navi);
bottomNavigationView.NavigationItemSelected += BottomNavigationView_NavigationItemSelected;
LoadFragment(Resource.Id.tab_camera);
return view;
}
private void BottomNavigationView_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
LoadFragment(e.Item.ItemId);
}
//switch fragment by tab id.
void LoadFragment(int id)
{
Fragment fragment = null;
switch (id)
{
case Resource.Id.tab_gallery:
fragment = Fragment_Gallery.NewInstance();
break;
case Resource.Id.tab_camera:
fragment = Fragment_Camera.NewInstance();
break;
}
if (fragment == null)
return;
FragmentManager.BeginTransaction()
.Replace(Resource.Id.mynest_content_frame, fragment)
.Commit();
}
}
Here is my demo, you can refer to it.
https://drive.google.com/file/d/1XZE6YopdsvDHY8-DwXBxRpHz3oFlJbOR/view

Xamarin, New activity on itemClick in RecyclerView

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;

How do I update a ListView?

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

call NotifyDataSetChanged inside a nested class in my adapter

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.

Cannot access a nonstatic member of outer type... via nested type

Why do I get this error?
Error CS0038: Cannot access a nonstatic member of outer type
JsonFeedParserTabs.MainActivity' via nested type
JsonFeedParserTabs.MainActivity.SampleTabFragment' (CS0038)
(JsonFeedParserTabs)
I'm trying to put a ListView with json data inside a tab.
This is my code:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using System.Linq;
namespace JsonFeedParserTabs
{
[Activity (Label = "Feed Reader", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
ListView listView;
// ProgressBar progressBar;
RootObject result;
string url = "http://javatechig.com/api/get_category_posts/?dev=1&slug=android";
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource.
SetContentView (Resource.Layout.Main);
this.ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab (" Tab 1", new SampleTabFragment ());
// AddTab (" Tab 2", new SampleTabFragment2 ());
if (bundle != null)
this.ActionBar.SelectTab(this.ActionBar.GetTabAt(bundle.GetInt("tab")));
}
protected override void OnSaveInstanceState(Bundle outState)
{
outState.PutInt("tab", this.ActionBar.SelectedNavigationIndex);
base.OnSaveInstanceState(outState);
}
void AddTab (string tabText, Fragment view)
{
var tab = this.ActionBar.NewTab ();
tab.SetText (tabText);
// Must set event handler before adding tab.
tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) {
var fragment = this.FragmentManager.FindFragmentById(Resource.Id.fragmentContainer);
if (fragment != null)
e.FragmentTransaction.Remove(fragment);
e.FragmentTransaction.Add (Resource.Id.fragmentContainer, view);
};
tab.TabUnselected += delegate(object sender, ActionBar.TabEventArgs e) {
e.FragmentTransaction.Remove(view);
};
this.ActionBar.AddTab (tab);
}
class SampleTabFragment : Fragment
{
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.Tab, container, false);
// Initializing listView.
listView = view.FindViewById<ListView> (Resource.Id.listView); // <-- Error!
listView.ItemClick += OnListItemClick; // <-- Error!
// progressBar = view.FindViewById<ProgressBar> (Resource.Id.progressBar);
//
// // Showing loading progressBar.
// progressBar.Visibility = ViewStates.Visible;
// Download and display data in url.
downloadJsonFeedAsync (url); // <-- Error!
return view;
}
}
// class SampleTabFragment2 : Fragment
// {
// public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
// {
// base.OnCreateView(inflater, container, savedInstanceState);
//
// var view = inflater.Inflate(Resource.Layout.Tab, container, false);
// var sampleTextView = view.FindViewById<TextView>(Resource.Id.sampleTextView);
//
// sampleTextView.Text = "Sample fragment text 2.";
//
// return view;
// }
// }
public async void downloadJsonFeedAsync(String url)
{
var httpClient = new HttpClient();
Task<string> contentsTask = httpClient.GetStringAsync(url);
// Await! control returns to the caller and the task continues to run on another thread.
string content = await contentsTask;
Console.Out.WriteLine("Response Body: \r\n {0}", content);
// Convert string to JSON object.
result = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject> (content);
// Update listview.
RunOnUiThread (() => {
listView.Adapter = new CustomListAdapter(this, result.posts);
// progressBar.Visibility = ViewStates.Gone;
});
}
void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Post item = result.posts.ElementAt (e.Position);
// Passing object form one activity to other.
Intent i = new Intent(Application.Context, typeof(FeedDetailsActivity));
i.PutExtra("item", JsonConvert.SerializeObject(item));
StartActivity(i);
}
}
}
I'm stuck and need help, any ideas what I have done wrong and what to do? Thank you!
Update
Alright it works now but i think there might be a better way to do this.
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using System.Linq;
namespace JsonFeedParserTabs
{
[Activity (Label = "Feed Reader", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
ListView listView;
// ProgressBar progressBar;
RootObject result;
string url = "http://javatechig.com/api/get_category_posts/?dev=1&slug=android";
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource.
SetContentView (Resource.Layout.Main);
this.ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
AddTab (" Tab 1", new SampleTabFragment (this));
// AddTab (" Tab 2", new SampleTabFragment2 ());
if (bundle != null)
this.ActionBar.SelectTab(this.ActionBar.GetTabAt(bundle.GetInt("tab")));
}
protected override void OnSaveInstanceState(Bundle outState)
{
outState.PutInt("tab", this.ActionBar.SelectedNavigationIndex);
base.OnSaveInstanceState(outState);
}
void AddTab (string tabText, Fragment view)
{
var tab = this.ActionBar.NewTab ();
tab.SetText (tabText);
// Must set event handler before adding tab.
tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) {
var fragment = this.FragmentManager.FindFragmentById(Resource.Id.fragmentContainer);
if (fragment != null)
e.FragmentTransaction.Remove(fragment);
e.FragmentTransaction.Add (Resource.Id.fragmentContainer, view);
};
tab.TabUnselected += delegate(object sender, ActionBar.TabEventArgs e) {
e.FragmentTransaction.Remove(view);
};
this.ActionBar.AddTab (tab);
}
class SampleTabFragment : Fragment
{
private MainActivity context;
public SampleTabFragment(MainActivity _context) : base()
{
this.context = _context;
}
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.Tab, container, false);
// Initializing listView.
context.listView = view.FindViewById<ListView> (Resource.Id.listView);
context.listView.ItemClick += context.OnListItemClick;
// progressBar = view.FindViewById<ProgressBar> (Resource.Id.progressBar);
//
// // Showing loading progressBar.
// progressBar.Visibility = ViewStates.Visible;
// Download and display data in url.
context.downloadJsonFeedAsync (context.url);
return view;
}
}
// class SampleTabFragment2 : Fragment
// {
// public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
// {
// base.OnCreateView(inflater, container, savedInstanceState);
//
// var view = inflater.Inflate(Resource.Layout.Tab, container, false);
// var sampleTextView = view.FindViewById<TextView>(Resource.Id.sampleTextView);
//
// sampleTextView.Text = "Sample fragment text 2.";
//
// return view;
// }
// }
public async void downloadJsonFeedAsync(String url)
{
var httpClient = new HttpClient();
Task<string> contentsTask = httpClient.GetStringAsync(url);
// Await! control returns to the caller and the task continues to run on another thread.
string content = await contentsTask;
Console.Out.WriteLine("Response Body: \r\n {0}", content);
// Convert string to JSON object.
result = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject> (content);
// Update listview.
RunOnUiThread (() => {
listView.Adapter = new CustomListAdapter(this, result.posts);
// progressBar.Visibility = ViewStates.Gone;
});
}
void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Post item = result.posts.ElementAt (e.Position);
// Passing object form one activity to other.
Intent i = new Intent(Application.Context, typeof(FeedDetailsActivity));
i.PutExtra("item", JsonConvert.SerializeObject(item));
StartActivity(i);
}
}
}
It's telling you exactly what it can't do. The MainActivity members are not accessible from the fragment types declared within the MainActivity type. So when you try to call downloadJsonFeedAsync (url); it fails because it's not a static (class) method. The fragments (although declared within the type), do not exist within an instance of the MainActivity type.
Unless there's some compelling reason for them to remain within the MainActivity type, I'd move them out. They should also then have a reference to the MainActivity type so that you can call downloadJsonFeedAsync(string) on it.
On an unrelated note (and I appreciate this is very much uninvited commentary :) ), you may want to consider using a MVVM pattern. It looks like you're intermixing presentation, application control, and business data. If this app grows beyond the one or two pages, you will find much peace in segregating responsibilities.

Categories

Resources