Unable to get listView.ItemClick to be called in M

2019-01-27 07:15发布

问题:

I have the following code:

protected override void OnCreate (Bundle bundle)
{
    progress = ProgressDialog.Show(this, "", "Loading...");
    progress.SetProgressStyle(ProgressDialogStyle.Spinner);

    base.OnCreate (bundle);

    //Set the Activity's view to our list layout        
    SetContentView(Resource.Layout.LawsAndRegsList);

    new Thread(new ThreadStart(() => {
        //Create our adapter
        listAdapter = new LawsAndRegsListAdapter(this);
        this.RunOnUiThread ( () => {
            //Find the listview reference
            listView = FindViewById<ListView>(Resource.Id.listView);

            //Hook up our adapter to our ListView
            listView.Adapter = listAdapter;

            //Wire up the click event
            //listView.ItemClick += new EventHandler<ListView.ItemClickEventArgs>(listView_ItemClick);
            listView.ItemClick += listView_ItemClick;

            listAdapter.NotifyDataSetChanged(); 

            progress.Dismiss();
        });
    })).Start();
}

void listView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
    //Get our item from the list adapter
    var item = this.listAdapter.GetItemAtPosition(e.Position);

    //Make a toast with the item name just to show it was clicked
    Toast.MakeText(this, item.Name + " Clicked!", ToastLength.Short).Show();
}

Can anyone tell me why the ItemClick would not get called?

It looks like what I have read and examples I have seen so what am I doing wrong? thanks for the help.

UPDATE:

Here are the two layouts I have:

LawsAndRegsList:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget28"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/topLevelMenuBackground"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnAddExpense"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@string/ButtonHome"
            android:layout_centerVertical="true" />
        <TextView
            android:id="@+id/lblExpenseCancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="15dp"
            android:text="@string/LawsAndRegs"
            android:textColor="#ffffffff"
            android:textSize="20sp"
            android:layout_centerVertical="true" />
    </RelativeLayout>
    <ListView
        android:id="@+id/listView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

LawsAndRegsListItem:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget28"
    android:layout_width="fill_parent"
    android:background="@drawable/topLevelMenuCellBackground"
    android:layout_height="40px">
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/imageItem"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical" />
        <TextView
            android:id="@+id/textTop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:textColor="#111479"
            android:text="hello"
            android:layout_toRightOf="@+id/imageItem"
            android:textStyle="bold"
            android:layout_marginLeft="10dp" />
        <ImageButton
            android:src="@drawable/OrangeAccessoryButton"
            android:layout_width="wrap_content"
            android:layout_height="25dp"
            android:layout_alignParentRight="true"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="15dp"
            android:layout_centerVertical="true"
            android:id="@+id/imageButton1"
            android:background="@android:color/transparent" />
    </RelativeLayout>
</LinearLayout>

UPDATE #2:

Added my LIstAdapter code:

public class LawsAndRegsListAdapter : BaseAdapter { Activity context;

public List<LawsAndRegs> items;

public LawsAndRegsListAdapter (Activity context) //We need a context to inflate our row view from
{
    this.context = context;

    MY_SEB_SERVICE_ContentWS.ContentWS contentWS = new MY_WEB_SERVICE_ContentWS.ContentWS ();
    string sMenu = contentWS.GetMenuXML (146, 1, "", 0, 1033);

    XmlRootAttribute r = new XmlRootAttribute ("Item");
    var ser = new XmlSerializer (typeof(Item), r);
    StringReader stringReader;
    stringReader = new StringReader (sMenu);
    Item obj = (Item)ser.Deserialize (stringReader);
    ItemMenuItem[] m = obj.Menu.Item;
    ItemMenuItem larMenu = null;
    foreach (ItemMenuItem mnu in m)
    {
        if (mnu.ItemID == 155)
        {
            if (this.items == null)
                this.items = new List<LawsAndRegs> ();
            larMenu = mnu;
            break;
        }
    }

    if (larMenu != null)
    {
        foreach (ItemMenuItemMenuItem imimi in larMenu.Menu.Item)
        {
            LawsAndRegs lar = new LawsAndRegs();
            lar.Name = (string)imimi.Items[2];
            lar.Image = (string)imimi.Items[3];
            this.items.Add (lar);
        }
    }
}

public override int Count
{
    get { return items.Count; }
}

public override Java.Lang.Object GetItem(int position)
{
    return position;
}

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

public LawsAndRegs GetItemAtPosition(int position)
{
    return items[position];
}

public override View GetView(int position, View convertView, ViewGroup parent)
{
    //Get our object for this position
    var item = items[position];         

    //Try to reuse convertView if it's not  null, otherwise inflate it from our item layout
    // This gives us some performance gains by not always inflating a new view
    // This will sound familiar to MonoTouch developers with UITableViewCell.DequeueReusableCell()
    var view = (convertView ?? context.LayoutInflater.Inflate(Resource.Layout.LawsAndRegsListItem, parent, false)) as LinearLayout;

    //Find references to each subview in the list item's view
    ImageView imgView = (ImageView)view.FindViewById(Resource.Id.imageItem);
    imgView.Clickable = true;
    TextView textTop = (TextView)view.FindViewById(Resource.Id.textTop);
    textTop.Clickable = true;

    var bm = BitmapFactory.DecodeStream(
        new Java.Net.URL("http://www.SOME_SITE.com/" + item.Image).OpenStream());
    imgView.SetImageBitmap(bm);

    //Assign this item's values to the various subviews
    textTop.SetText(item.Name, TextView.BufferType.Normal);

    view.Clickable = true;

    //Finally return the view
    return view;
}

}

I added the view.clickable code in trying to get this to work.

回答1:

Finally!! I found out my issue... it turned out that the problem was my ImageButton in the ListView. It was stealing the focus and consuming the touch events. So in my custom Adapter, in the GetView I needed to do something like the following:

var imageButton = view.FindViewById<ImageButton>(Resource.Id.imageButton1);
imageButton.Focusable = false;
imageButton.FocusableInTouchMode = false;
imageButton.Clickable = true;

imageButton.Click += (sender, args) => Console.WriteLine("ImageButton {0} clicked", position);

That removes the focus from the image button. The solution was given to me here: http://forums.xamarin.com/discussion/871/how-do-i-get-itemclick-of-a-listview-to-get-called-not-sure-what-have-wrong#latest by Cheesebaron. Thank you Cheesebaron!!!

I hope this may help another newbie with a similar issue!!



回答2:

Put android:descendantFocusability="blocksDescendants" in your linear layout of LawsAndRegsListItem, because Android doesn't allow any items to be focusable in listview. Instead of setting every control in your listview to android:focusable="false", the easiest way doing it is setting its root ViewGroup to android:descendantFocusability="blocksDescendants", so it will block every control of it getting focused.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget28"
    android:layout_width="fill_parent"
    android:background="@drawable/topLevelMenuCellBackground"
    android:layout_height="40px"
    android:descendantFocusability="blocksDescendants">
    ...
</LinearLayout>

Also, don't set the LinearLayout's Clickable to true. If so, it will gain focused even though its child won't get focused and thus the listview will block any clicking event.

References:

ListView Tips & Tricks #4: Add several clickable areas

Android Documentation on descendantFocusability



回答3:

I also managed to get though this problem by setting the "view.Click" handler inside the adapter::GetView function. Seems to work as well.

public class TaskListAdapter : BaseAdapter<Task> {
    Activity context = null;
    IList<Task> tasks = new List<Task>();

    public TaskListAdapter (Activity context, IList<Task> tasks) : base ()
    {
        this.context = context;
        this.tasks = tasks;
    }

    [...]

    public override Android.Views.View GetView (int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
    {


        var view = (convertView ??
            context.LayoutInflater.Inflate(...));
        view.FindViewById<..>(Resource.Id.NameText).SetText ("...", TextView.BufferType.Normal);

        view.Click += (sender, e) => 
        {
            int a=0;
            a++; //breakpoint location is being hit.

        };
        return view;
    }
}
}