0

This has been asked before but without an answer that works for me (and apparently one other given the comment on the accepted/only answer).

I have a ListView and I've implemented a long-press-to-copy for each item in the list. I'm filling in the list with my own adapter that sets the OnLongClickListener and it's functioning fine except that when I touch and hold on an item, it doesn't highlight at all and doesn't fade. I haven't set any events on the ListView and no other events on the View I return from my Adapter.

I've read about several fixes like not using wrap_content, setting clickable to false or removing it entirely from XML. Nothing has had an impact. I have noticed that if I remove my Long Click Listener that it will animate a click, but not a fading long click.

What can I do to preserve the long click fading animation on my ListView items?

FYI: the app is targeting Gingerbread (2.3.3)

EDIT:

I'm writing a simple hash calculator. It has one activity as follows:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:id="@+id/Input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:ems="10"
        android:inputType="text">
        <requestFocus/>
    </EditText>
    <Button
        android:id="@+id/Hash"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@id/Input"
        android:onClick="StartHashes"
        android:text="@string/HashButtonText"/>
    <ListView
        android:id="@+id/HashList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@id/Hash">
    </ListView>
</RelativeLayout>

Relevant code from my onCreate method:

    Adapter = new HashEntryAdapter(this, Entries);// Entries is Vector<HashEntry>
    ListView list = (ListView)findViewById(R.id.HashList);
    list.setAdapter(Adapter);

HashEntry is simply a class containing 2 strings: the name of the hash and the resulting output of the hash called Name and Value respectively. The HashEntryAdapter is as follows:

public class HashEntryAdapter extends ArrayAdapter<HashEntry> {

    private Context context;

    public HashEntryAdapter(Context context, List<HashEntry> objects) {
        super(context, R.layout.hashitem, objects);
        this.context = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //data from your adapter
        HashEntry entry = getItem(position);
        //we want to reuse already constructed row views...
        if(convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.hashitem, null);
            convertView.setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    HashEntry entry = (HashEntry)v.getTag();
                    ClipboardManager clipboard = (ClipboardManager)v.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
                    clipboard.setText(entry.Value);
                    Toast.makeText(context, entry.Name + " copied to clipboard", Toast.LENGTH_SHORT).show();
                    return true;
                }
            });
        }
        convertView.setTag(entry);

        TextView Name = (TextView)convertView.findViewById(R.id.HashName);
        TextView Value = (TextView)convertView.findViewById(R.id.HashValue);

        Name.setText(entry.Name);
        Value.setText(entry.Value);

        return convertView;
    }
}

And finally, hashitem.xml, a simple layout to put a grayed hash name over a black hash value:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/HashName"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="@string/HashNameFiller"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/DarkGray"/>
    <TextView
        android:id="@+id/HashValue"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/HashName"
        android:layout_centerHorizontal="true"
        android:text="@string/HashValueFiller"
        android:textAppearance="?android:attr/textAppearanceMedium"/>
</RelativeLayout>

OnCreateContextMenu for vikki:

    list.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        }
    });
Community
  • 1
  • 1
Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188
  • "Frozen Yogurt" (FroYo) is Android 2.2, not 2.3.3. – CommonsWare Oct 11 '12 at 20:15
  • Whoops... I know I targeted 2.3.3, I just slipped for a bit on what name went with it. Edited to say Gingerbread. – Corey Ogburn Oct 11 '12 at 20:17
  • You could just use `onCreateContextMenu` like the stock messaging app does in ICS when you want to delete a conversation thread. You can get the `id` and `position` just like in `onLongClickListener` if you cast `ContextMenuInfo` to `AdapterContextMenuInfo` – vikki Oct 11 '12 at 21:11
  • @vikki: it functions the same but still no animation. – Corey Ogburn Oct 12 '12 at 13:33
  • Set the `OnCreateContextMenuListener` on the listview and not on the individual views, like `listView.setOnCreateContextMenuListener(...)` – vikki Oct 13 '12 at 15:58
  • @vikki, The animation is back but now I don't get an ID or position of the touched list entry. – Corey Ogburn Oct 15 '12 at 14:06
  • post your `OnCreateContextMenuListener` – vikki Oct 16 '12 at 04:13
  • @vikki: it's empty because none of the parameters appear to have any information about which list element in the original listview was selected. But I added it anyway. – Corey Ogburn Oct 16 '12 at 13:47
  • @CoreyOgburn i've added what you'll need in my answer. – vikki Oct 16 '12 at 14:33

2 Answers2

1

You could just use onCreateContextMenu like the stock messaging app does in ICS when you want to delete a conversation thread. You can get the id and position just like in onLongClickListener if you cast ContextMenuInfo to AdapterContextMenuInfo

import android.widget.AdapterView.AdapterContextMenuInfo

...

list.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        AdapterContextMenuInfo contextInfo = (AdapterContextMenuInfo) menuInfo;
        int position = contextInfo.position;
        long id = contextInfo.id;
        // the child view who's info we're viewing (should be equal to v)
        View view = contextInfo.targetView;
    }
});
vikki
  • 2,766
  • 1
  • 20
  • 26
  • Thank you so much, sorry it took so long for me to get what you're saying. 5 days ago you put this in a comment. Works great! – Corey Ogburn Oct 16 '12 at 14:42
  • I don't know you could have been. I think I was a little too caught up on the fact that I'm not actually creating a context menu. I was quick to overlook the answer. – Corey Ogburn Oct 16 '12 at 15:25
0

set the onlongclicklistener on the listview, set it on the listview that you declare, outside of your adapter

so instead of each cell in your adapter having an onlongclicklistener, you listview does instead

listview.setOnLongClickListener(){new OnLongClickListener....
CQM
  • 42,592
  • 75
  • 224
  • 366
  • I don't know why, but the event never actually fires. For a test I threw in a Toast message and it never appears. The animation works again though. – Corey Ogburn Oct 12 '12 at 13:30
  • @CoreyOgburn post your code, the places where you declare the listview, the xml, and the place where you set up your adapter – CQM Oct 12 '12 at 13:38
  • I was hoping it's a common enough problem that I wouldn't have to, but I did. – Corey Ogburn Oct 12 '12 at 13:58