android xamarin 中 ListView 上的 ItemClick

ItemClick on ListView in xamarin for android

我正在为 android 开发应用程序,它基本上是一个新闻提要 reader 并且卡住了。我正在从一个网站解析 xml,现在我有一个列表视图,其中我代表标题、日期、作者等,但现在当用户单击其中一个项目时,我想打开该项目并显示文本(新闻)这是我的代码:`

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

}

现在我将 post 遇到问题的部分:

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

}

}

这里尝试从MainActivity接收数据并打开一篇新闻文章:

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;

    }
}

}

希望你能知道我想要完成什么以及如何解决。谢谢!

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

(这个问题在 xamarin-android gitter channel 上也有人问过。这里总结一下。)

您的应用存在两个相互关联的问题:

  1. Intent.PutExtra() 要求 密钥包含 "package prefix"
  2. 您实际上必须向 Intent.PutExtra() 提供

关于 (1),回忆 PutExtra() 用法:

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

问题是 MTitleDescription 都不包含 "package prefix." 更糟糕的是,它们具有 相同的值 ,这意味着 newsDetail.PutExtra(Description, ...) 调用将 替换 先前 newsDetail.PutExtra(MTitle, ...) 调用的值。

解决方法是为这些键提供唯一的非空值:

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

关于 (2),回忆一下 newsDetail.PutExtra() 代码,更多上下文:

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

这里的问题是items 还没有初始化。因此,items.Titleitems.Content 为空字符串。要解决此问题,请初始化这些值:

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