简体   繁体   中英

accessing a view in a SimpleCursorAdapter from the ListFragment

I have a ListFragment with a SimpleCursorAdapter and want to set a longClickListener to each of the items in the list ie to one of the TextViews in each item. So I need to Access the TextView to call setOnLongClickListener on that view.

The ListFragment (where I always get null from findViewById but would like to use the setOnLongClickListener ):

 public class OverviewFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    ...

    @Override
    public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle b ) {
        View fragView = inflater.inflate( R.layout.overview_fragment, container, false );
        return fragView;
    }

    @Override
    public void onActivityCreated( Bundle state ) {
        super.onActivityCreated (state );
        getLoaderManager().initLoader( LOADER_ID_READ_OVERVIEW, null, this );
        adapter = new SimpleCursorAdapter( getActivity(), R.layout.overview_row, null, overviewDbColumns, overviewTargetViewIds, 0 );
        setListAdapter( adapter );
        TextView tv = (TextView) getListView().findViewById( R.id.overviewFooName );
        if ( tv == null ) { //is always null!!!
            Log.e( TAG, "OverviewFragment->onActivityCreated: tv == null" );
        } else {
            tv.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    if ( mActionMode != null ) { 
                        return false;
                    }
                    mActionMode = getActivity().startActionMode(mActionModeCallback);
                    view.setSelected(true);
                    return true;
                }
            });
        }
    }

The overview_fragment.xml:

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<include layout="@android:layout/list_content" />
<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:choiceMode="singleChoice" >
</ListView>
<TextView
    android:id="@android:id/empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/no_foo_in_list" 
/>

and the overview_row.xml (used by tha SimpleCursorAdapter ):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
    android:id="@+id/overviewFooName"
    android:clickable="true"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent" />
<TextView
    android:id="@+id/overviewFooType"
    android:layout_width="wrap_content"
    android:layout_height="26dp" />

<TextView
    android:id="@+id/overviewFooDbIndex"
    android:layout_width="wrap_content"
    android:layout_height="26dp" />

My idea of how android uses the view hierarchy seems to be wrong. My idea is that of one single tree, where I can access every node - as long as I know its ID - from any other node that is nearer to the root. Is this right?

If this idea is wrong, as I expect - how do I get access to the TextView (or the whole item)? And where do I place the code for the mActionModeCallback ?

Without having tried this myself I suppose that the problem here is that the ID you are giving to findViewById (R.id.overViewFooName) is ambiguous: Since every list item contains a TextView with this ID, how should the framework decide, which of these to return in findViewById?

So, I think you have two options:

  1. just use the built-in capabilities of the ListView, namely setOnItemLongClickListener:

http://developer.android.com/reference/android/widget/AdapterView.html#setOnItemLongClickListener%28android.widget.AdapterView.OnItemLongClickListener%29

That is, you set a OnItemLongClickListener on the whole ListView - it has a method:

public abstract boolean onItemLongClick (AdapterView<?> parent, View view, int position, long id)

which will be called whenever an item in the ListView is long-clicked. As you can see, the method also receives the position of the long-clicked item and you can then handle the click accordingly.

  1. If you really need to have just the TextView within each item long-clickable (and not the whole item as in solution 1.), you would need to set the listener in the getView-method of the adapter that creates the list item views.

    That is, you subclass SimpleCursorAdapter and overwrite the getView method. There you inflate your XML layout, get a reference to the TextView and set the OnLongClickListener. In this case, since you are doing this for each item seperately, the findViewById will work because you are in a subtree of the view tree where there is indeed only one View with the ID R.id.overViewFooName.

I tested this in the debugger the event fired when I long clicked the list.

public class OverviewFragment extends ListFragment implements 
LoaderManager.LoaderCallbacks<Cursor>
,OnItemLongClickListener
{

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    //notice the adapter is setup in onCreate
    adapter2 = new CustomListViewAdapter(this, R.id.list_item, summary,
            mSortOrder, tabsList);
    setListAdapter(adapter2);
}


@Override
public void onActivityCreated(Bundle savedState) {
    super.onActivityCreated(savedState);
    getListView().setOnItemLongClickListener(this);
    //registerForContextMenu(getListView());
}


@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
        int position, long id) {
    // TODO Auto-generated method stub
    return false;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM