Yupi
Yupi

Reputation: 4470

ItemClick on ListView in xamarin for android

I'm developing app for android which is basically a news feed reader and got stuck. I'm parsing xml from one website and for now I have a listview in which I represented title, date, writer and so on but now when user clicks on one of the items I want to open that item and show the text (news) this is my code:`

using System;
using System.Collections.Generic;
using Android.App;
using Android.Widget;
using Android.Views;
using Android.Media;


namespace NewsFeedReader
{
public class FeedItemListAdapter : BaseAdapter<FeedItem>
{
    protected Activity context;
    protected List<FeedItem> feedList = new List<FeedItem>();
    public FeedItemListAdapter ( Activity context, List<FeedItem> feedList) : base()
    {
        this.context = context;
        this.feedList = feedList;
    }

    public override FeedItem this [int position] 
    {
        get { return this.feedList [position]; }
    }

    public override long GetItemId (int position)
    {
        return position;
    }

    public override int Count
    {
        get {
            return this.feedList.Count;
        }
    }
    public override View GetView (int position, View convertView, ViewGroup parent)
    {
        var feedItem = this.feedList [position];
        var view = convertView ?? context.LayoutInflater.Inflate (Resource.Layout.FeedLayout, parent, false) as LinearLayout;
        view.FindViewById<TextView> (Resource.Id.Title).Text = feedItem.Title.Length < 50 ? feedItem.Title : feedItem.Title.Substring (0, 50) + "..."; 
        view.FindViewById<TextView> (Resource.Id.writer).Text = feedItem.Creator;
        view.FindViewById<TextView> (Resource.Id.PubDate).Text = feedItem.PubDate.ToString ("dd/MM/yyyy HH:mm");
        var imageView = view.FindViewById<ImageView> (Resource.Id.ListviewImage);
        Koush.UrlImageViewHelper.SetUrlDrawable (imageView, feedItem.Image, Resource.Drawable.Icon);
        return view;
    }
}
}`

 using System;
 using System.Collections.Generic;
 using System.Net;
 using System.IO;
 using System.Xml;

 namespace NewsFeedReader
 {
   static internal class FeedService
  {
    internal static List<FeedItem> GetFeedItems (string url)
    {
        List<FeedItem> FeedItemList = new List<FeedItem> ();

        try
        {
        WebRequest webRequest = WebRequest.Create (url);
        WebResponse webResponse = webRequest.GetResponse();
        Stream stream = webResponse.GetResponseStream ();

        XmlDocument xmlDoc = new XmlDocument ();
        xmlDoc.Load (stream);
        XmlNamespaceManager xmlNM = new XmlNamespaceManager(xmlDoc.NameTable);
        xmlNM.AddNamespace("dc", xmlDoc.DocumentElement.GetNamespaceOfPrefix("dc"));
        xmlNM.AddNamespace("content", xmlDoc.DocumentElement.GetNamespaceOfPrefix("content"));

        XmlNodeList xmlNode = xmlDoc.SelectNodes("rss/channel/item");

            for (int i = 0; i < xmlNode.Count; i++)
            {
                FeedItem feedItem = new FeedItem();

                if (xmlNode[i].SelectSingleNode("title") != null)
                {
                    feedItem.Title = xmlNode[i].SelectSingleNode("title").InnerText;
                }
                if (xmlNode[i].SelectSingleNode("content:encoded", xmlNM) != null)
                {
                    feedItem.Content = xmlNode[i].SelectSingleNode("content:encoded", xmlNM).InnerText;
                }
                if (xmlNode[i].SelectSingleNode("link") != null) 
                {
                    feedItem.Link = xmlNode[i].SelectSingleNode("link").InnerText;
                }
                if (xmlNode[i].SelectSingleNode("pubDate") != null)
                {
                    feedItem.PubDate = Convert.ToDateTime(xmlNode[i].SelectSingleNode("pubDate").InnerText);
                }
                if (xmlNode[i].SelectSingleNode("category") != null) 
                {
                    feedItem.Category = xmlNode[i].SelectSingleNode("category").InnerText;
                }
                if (xmlNode[i].SelectSingleNode("description") != null)
                {
                    feedItem.Description = xmlNode[i].SelectSingleNode("description").InnerText;
                }
                if (xmlNode[i].SelectSingleNode("image") != null) 
                {
                    feedItem.Image = xmlNode[i].SelectSingleNode("image").InnerText;
                }
                if (xmlNode[i].SelectSingleNode("dc:creator", xmlNM) != null) 
                {
                    feedItem.Creator = xmlNode[i].SelectSingleNode("dc:creator", xmlNM).InnerText;
                }
                else
                {
                    feedItem.Content = feedItem.Description;
                }
                FeedItemList.Add(feedItem);
            }

        }

        catch(Exception) 
        {
            throw;
        }
        return FeedItemList;
    }
}
}



  using System;
  using Android.Widget;

  namespace NewsFeedReader
 {
   public class FeedItem
{
    public FeedItem ()
    {
    }

    public string Title {
        get;
        set;
    }
    public string Content {
        get;
        set;
    }
    public DateTime PubDate {
        get;
        set;
    }
    public string Creator {
        get;
        set;
    }
    public string Description {
        get;
        set;
    }
    public string Category {
        get;
        set;
    }
    public string Link {
        get;
        set;
    }
    public string Image {
        get;
        set;
    }
}

}

And now I will post part where I have problem:

 using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using Newtonsoft.Json;
 using Android.App;
 using Android.Content;
 using Android.Runtime;
 using Android.Views;
 using Android.Widget;
 using Android.OS;
 using Android.Support.V7.App;
 using ToolbarV7 = Android.Support.V7.Widget.Toolbar;
 using Android.Support.V4.Widget;

namespace NewsFeedReader
{
[Activity(Label = "Krajina.ba", MainLauncher = true, Icon = "@drawable/icon", Theme="@style/MyTheme")]
public class MainActivity : ActionBarActivity
{
    private ActionBarDrawerToggle actionBarDrawerToggle;
    Context context;
    ToolbarV7 toolbar;
    DrawerLayout drawerLayout;
    ListView leftListView;
    ListView rightListView;
    ArrayAdapter leftArrayAdapter;
    ArrayAdapter rightArrayAdapter;
    List<string> leftList;
    List<string> rightList;

    private HorizontalScrollView horizontalScroll;
    private List<FeedItem> list;
    private ListView feedItemLisView;
    private ProgressDialog progressDialog;


    public static string MTitle = "";
    public static string Pubdate = "";
    public static string Description = "";

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);
        drawerLayout = FindViewById<DrawerLayout> (Resource.Id.drawer_layout);
        leftListView = FindViewById<ListView> (Resource.Id.left_drawer);
        rightListView = FindViewById<ListView> (Resource.Id.right_drawer);
        toolbar = FindViewById<ToolbarV7> (Resource.Id.toolbar);
        leftListView.Tag = 0;
        rightListView.Tag = 1;
        actionBarDrawerToggle = new ActionBarDrawerToggle (
            this,
            drawerLayout,
            Resource.String.OpenDrawer,
            Resource.String.ClosedDrawer
        );
        this.feedItemLisView = this.FindViewById<ListView> (Resource.Id.feedItemListView);
        //this.feedItemListViewTop = this.FindViewById<ListView> (Resource.Id.feedItemListViewTop);
        this.horizontalScroll = this.FindViewById<HorizontalScrollView> (Resource.Id.myHorizontalScroll);

        leftList = new List<string> ();
        leftList.Add ("BIH");
        leftList.Add ("SPORT");
        leftList.Add ("SVIJET");
        leftList.Add ("MAGAZIN");
        leftList.Add ("SCITECH");
        leftList.Add ("ZANIMLJIVOSTI");

        leftArrayAdapter = new ArrayAdapter<string> (
            this, 
            Android.Resource.Layout.SimpleListItem1,
            leftList);
        leftListView.Adapter = leftArrayAdapter;

        rightList = new List<string> ();
        rightList.Add ("BIHAĆ");
        rightList.Add ("CAZIN");
        rightList.Add ("BOSANSKA KRUPA");
        rightList.Add ("BUŽIM");
        rightList.Add ("BOSANSKI PETROVAC");
        rightList.Add ("VELIKA KLADUŠA");
        rightList.Add ("KLJUČ");
        rightList.Add ("SANSKI MOST");

        rightArrayAdapter = new ArrayAdapter<string> (
            this, 
            Android.Resource.Layout.SimpleListItem1, 
            rightList);
        rightListView.Adapter = rightArrayAdapter;

        SetSupportActionBar (toolbar);
        drawerLayout.SetDrawerListener (actionBarDrawerToggle);
        SupportActionBar.SetHomeButtonEnabled (true);
        SupportActionBar.SetDisplayHomeAsUpEnabled (true);
        actionBarDrawerToggle.SyncState ();

        this.progressDialog = new ProgressDialog (this);
        this.progressDialog.SetMessage ("Aplikacija u pripremi...");

        GetItemList ();
    }
    private void GetItemList()
    {
        this.progressDialog.Show ();

        Task<List<FeedItem>> task = Task.Factory.StartNew (() => {
            return FeedService.GetFeedItems ("http://www.krajina.ba/feed/");
        });

        Task task2 = task.ContinueWith ((s) => {
            try {
                this.progressDialog.Dismiss ();
                this.list = s.Result;
                this.PopulateListView(this.list);
            } 

            catch (AggregateException ex)
            {
                Toast.MakeText (this, ex.InnerException.Message, ToastLength.Short).Show ();
            }
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    private void PopulateListView(List<FeedItem> listView)
    {
        var adapter = new FeedItemListAdapter (this, listView);
        this.feedItemLisView.Adapter = adapter;
        this.feedItemLisView.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) => 
        {
            var myAdpter = e.Parent.GetItemAtPosition(e.Position);
            FeedItem items = new FeedItem();
            var newsDetail = new Intent(Application.Context, typeof(FeedDetails));
            newsDetail.PutExtra(MTitle, items.Title);
            newsDetail.PutExtra(Description, items.Content);
            StartActivity(newsDetail);
            /*Intent i = new Intent(this, typeof(FeedDetails));
            i.PutExtra("item", JsonConvert.SerializeObject(items));
            StartActivity(i);*/
        };
    }

    private void PopulateLayout(List<FeedItem> feedItems)
    {
        var adapter = new MainFeedAdapter (this, feedItems);
        //this.horizontalScroll.Adapter = adapter;
    }
    public override bool OnOptionsItemSelected (IMenuItem item)
    {
        switch (item.ItemId) 
        {
        case Android.Resource.Id.Home:
            drawerLayout.CloseDrawer (rightListView);
            actionBarDrawerToggle.OnOptionsItemSelected (item);
            return true;

        case Resource.Id.action_refresh:
            return true;

        case Resource.Id.action_help:
            if (drawerLayout.IsDrawerOpen (rightListView)) {
                drawerLayout.CloseDrawer (rightListView);
            } else {
                drawerLayout.OpenDrawer (rightListView);
                drawerLayout.CloseDrawer (leftListView);
            }
            return true;
        default:
            return base.OnOptionsItemSelected (item);
        }

    }
    public override bool OnCreateOptionsMenu (IMenu menu)
    {
        MenuInflater.Inflate (Resource.Menu.action_menu, menu);
        return base.OnCreateOptionsMenu (menu);
    }

}

}

Here tried to receive data from MainActivity and open a news article:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace NewsFeedReader
{
[Activity (Label = "FeedDetails")]          
public class FeedDetails : Activity
{
    FeedItem list = new FeedItem ();
    public static string title = "";
    public static string description = "";

    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);


        // Create your application here
        SetContentView(Resource.Layout.FeedDetails);
        //FeedItem feedItem = JsonConvert.DeserializeObject<FeedItem> (Intent.GetStringExtra("item"));
        title = Intent.GetStringExtra(MainActivity.MTitle);
        description = Intent.GetStringExtra (MainActivity.Description);

        FindViewById<TextView> (Resource.Id.FeedDetailsTitle).Text = title;
        FindViewById<TextView> (Resource.Id.FeedDetailsContent).Text = description;

    }
}

}

Hope you can know what I want to accomplish and how can solve that. Thank you!

Upvotes: 1

Views: 9377

Answers (2)

jonp
jonp

Reputation: 13600

(This question was also asked on the xamarin-android gitter channel. Summarizing here.)

There are two interrelated problems with your app:

  1. Intent.PutExtra() requires that the key contain a "package prefix"
  2. You have to actually provide a value to Intent.PutExtra().

Regarding (1), recall the PutExtra() usage:

partial class MainActivity {
    public static string MTitle = "";
    public static string Description = "";

    void PopulateListView(List<FeedItem> listView)
    {
        ...
        var newsDetail = new Intent(...);
        newsDetail.PutExtra(MTitle,      items.Title);
        newsDetail.PutExtra(Description, items.Description);
    }
}

The problem is that neither MTitle nor Description contain a "package prefix." Worse, they have the same value, which means the newsDetail.PutExtra(Description, ...) call will replace the value of the prior newsDetail.PutExtra(MTitle, ...) call.

The fix is to provide unique, non-empty values, for these keys:

partial class MainActivity {
    public const string MTitle      = "your.package.name.Title";
    public const string Description = "your.package.name.Description";
}

Regarding (2), recall the newsDetail.PutExtra() code, with more context:

newsDetail = new Intent(Application.Context, typeof(FeedDetails));
FeedItem items = new FeedItem();
newsDetail.PutExtra(MTitle, items.Title);
newsDetail.PutExtra(Description, items.Content);

The problem here is that items hasn't been initialized. Conseqeuently, items.Title and items.Content will both be the empty string. To fix this, initialize those values:

var item   = adapter [e.Position];
newsDetail = new Intent(Application.Context, typeof(FeedDetails));
FeedItem items = new FeedItem() {
    Title   = item.Title,
    Content = item.Content,
};
newsDetail.PutExtra(MTitle, items.Title);
newsDetail.PutExtra(Description, items.Content);

Upvotes: 1

ClintL
ClintL

Reputation: 1453

private void PopulateListView(List<FeedItem> listView)
    {
        var adapter = new FeedItemListAdapter (this, listView);
        this.feedItemLisView.Adapter = adapter;
        this.feedItemLisView.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) => 
        {
            var myitem = adapter.GetItemAtPosition(e.Position);
            //do something with selected feeditem
        };

Upvotes: 2

Related Questions