Custom ListView and context menu. How to get it?

Georgy Gobozov picture Georgy Gobozov · Oct 19, 2010 · Viewed 37.7k times · Source

I have a two layouts files in my app. Also I have Activity extends ListActivity. Every item of this activity looks consider item.xml layout file. I am trying to get context menu when make long presss on item, but I don't see it.

In my activity I trying to registerForContextMenu(getListView()) and override two methods

  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = this.getIntent().getExtras();
        registerForContextMenu(getListView());
        new PopulateAdapterTask().execute(ACTION_SELECT);   
     }

    @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.context_menu, menu);
        }


        @Override
        public boolean onContextItemSelected(MenuItem item) {
            AdapterView.AdapterContextMenuInfo info;
            try {
                info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
            } catch (ClassCastException e) {
                return false;
            }
            long id = getListAdapter().getItemId(info.position);
            Log.d(TAG, "id = " + id);
            return true;
        }

Main.xml

    <?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@android:id/tabhost"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent">
    <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp">
        <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"/>
        <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:padding="5dp">
            <ListView
                    android:id="@+id/list"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    />

        </FrameLayout>

    </LinearLayout>

</TabHost>

Item.xml

<?xml version="1.0" encoding="utf-8"?>
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
        >
    <ImageView
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    <TextView
            android:id="@+id/info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="15sp"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:scrollHorizontally = "true"
            android:maxWidth="200dp"
            />


    <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="fill_parent"
             android:gravity="right"
            >
        <ImageButton
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:background="@null"
                android:paddingRight="10dp"                
                android:paddingLeft="10dp"


                />
    </LinearLayout>

</LinearLayout>

All this doesn't work. Maybe the reason is in LinearLayout? I also find similar topic Android: Context menu doesn't show up for ListView with members defined by LinearLayout? but I have more complicated list item.

How to get context menu in my case?

Also in my activity I have inner class extends ArrayAdapter. In this class in getView method I can set OnCreateContextMenuListener on every View, after that context menu is appears, but I don't know how to handle items clicks. If I am trying to do this in method onContextItemSelected, item.getMenuInfo() object always is null and i can't to get some information from it.

private class ChannelAdapter extends ArrayAdapter<Channel> {

        private List<Channel> channels;

        public ChannelAdapter(Context context, int textViewResourceId, List<Channel> objects) {
            super(context, textViewResourceId, objects);
            this.channels = objects;
        }


        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.station_item, null);
            }


                v.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
                    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
                        MenuInflater inflater = getMenuInflater();
                        inflater.inflate(R.menu.context_menu, menu);
                    }
                });

Thanks. Hope for your help.

Answer

Georgy Gobozov picture Georgy Gobozov · Oct 22, 2010

I got solution, my friend helped me! Hope this information will helpful to someone. This is complete class code with ArrayAdapter and complex list layout and context menu.

   public class ComplexListActivity extends ListActivity {
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setListAdapter(new ComplexObjectAdapter(this, R.layout.item, getComplexObjects()));
        registerForContextMenu(getListView());
    }

    private List getComplexObjects() {
        List<ComplexObject> list = new ArrayList<ComplexObject>();
        list.add(new ComplexObject("1", "1", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("2", "2", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("3", "3", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("4", "4", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("5", "5", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("6", "6", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("7", "7", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("8", "8", getResources().getDrawable(R.drawable.icon)));
        list.add(new ComplexObject("9", "9", getResources().getDrawable(R.drawable.icon)));
        return list;
    }


    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);
    }


    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info;
        try {
            info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        } catch (ClassCastException e) {
            Log.e("", "bad menuInfo", e);
            return false;
        }
        long id = getListAdapter().getItemId(info.position);
        Log.d("", "id = " + id);
        Toast.makeText(this, "id = " + id, Toast.LENGTH_SHORT).show();
        return true;
    }

    private class ComplexObjectAdapter extends ArrayAdapter<ComplexObject> implements View.OnCreateContextMenuListener {

        private List<ComplexObject> objects;

        public ComplexObjectAdapter(Context context, int textViewResourceId, List<ComplexObject> objects) {
            super(context, textViewResourceId, objects);
            this.objects = objects;
        }


        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.item, null);
            }
            final ComplexObject o = objects.get(position);
            if (o != null) {

                TextView textlInfo = (TextView) v.findViewById(R.id.info);
                textlInfo.setText(o.getName());

                ImageView channelIcon = (ImageView) v.findViewById(R.id.icon);
                channelIcon.setAdjustViewBounds(true);
                channelIcon.setMaxHeight(30);
                channelIcon.setMaxWidth(30);
                channelIcon.setImageDrawable(o.getLogo());


                ImageButton button = (ImageButton) v.findViewById(R.id.button);
                button.setImageResource(R.drawable.icon);
                v.setOnCreateContextMenuListener(this);

            }
            return v;
        }

         public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
          // empty implementation
        }

    }
}

let me know if someone will find better approach. Thanks!