处理自定义列表项单击导航抽屉 ListView 内

Posted

技术标签:

【中文标题】处理自定义列表项单击导航抽屉 ListView 内【英文标题】:Handling custom list items click inside a navigation drawer ListView 【发布时间】:2014-09-29 15:49:20 【问题描述】:

我的导航抽屉中托管了 ListView 的自定义行,当我每行只有一个简单的 TextView 时,一切正常。

然后我决定为每一行添加两个ImageButtons,显示EDIT和DISCARD ImageButtons,在这种情况下的问题是ImageButtons窃取焦点并且ListView适配器onItemClickListener不再接收onItemClick事件,所以主片段的内容可以' t 根据我在抽屉上单击的元素进行相应更改。

我使用自定义 CursorAdapter 来填充抽屉的 ListView,因此我决定为行的每个元素创建一个 OnClickListener。现在,该行的每个项目都会对单击事件做出正确反应...现在的问题是我无法将 onClick 事件从 TextView 元素传输到 ListView 以正确选择 ListView 中的项目。

custom_list_row.xml:

 <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_
        android:layout_
        android:orientation="horizontal" 
        android:clickable="true">

        <ImageButton
            android:id="@+id/drawer_list_item_discard"
            android:layout_
            android:layout_
            android:src="@drawable/ic_discard"
            android:scaleType="centerCrop"
            android:layout_alignParentRight="true"
            android:background="@null"
            android:padding="0dp"/>

        <ImageButton
            android:id="@+id/drawer_list_item_edit"
            android:layout_
            android:layout_
            android:src="@drawable/ic_edit" 
            android:scaleType="centerCrop"
            android:padding="0dp"
            android:background="@null"
            android:layout_toLeftOf="@id/drawer_list_item_discard"/>

        <TextView 
            android:id="@+id/drawer_list_item_text"
            android:layout_
            android:layout_
            android:padding="5dp"
            android:layout_centerInParent="true"
            android:textColor="#000000"
            android:textSize="20dp"
            android:layout_toLeftOf="@id/drawer_list_item_edit" 
            android:layout_alignParentLeft="true" />

    </RelativeLayout>

ProgramsCursorAdapter.java 中的bindView(...):

@Override
public void bindView(View v, Context context, Cursor c) 
    if (mContext == null) return;

    // Instances of the Views
    TextView tv_name = (TextView) v.findViewById(R.id.drawer_list_item_text);
    // Override fonts
    Typeface robotoLight = Typeface.createFromAsset(mContext.getAssets(), "fonts/Roboto-Light.ttf");
    if (tv_name != null) tv_name.setTypeface(robotoLight);
    // Retrieve values of the row
    String name = c.getString(c.getColumnIndex(DBHelper.TB_PROGRAM_NAME));
    // Assign retrieved value to the row
    tv_name.setText(name);

    tv_name.setOnClickListener(new OnClickListener() 

        @Override
        public void onClick(View v) 
            System.out.println("Program click!");
        
    );

    //Set up imagebuttons
    ImageButton edit = (ImageButton) v.findViewById(R.id.drawer_list_item_edit);
    edit.setOnClickListener(new OnClickListener() 

        @Override
        public void onClick(View v) 
            System.out.println("Edit onclick!");
        
    );

    ImageButton discard = (ImageButton) v.findViewById(R.id.drawer_list_item_discard);
    discard.setOnClickListener(new OnClickListener() 

        @Override
        public void onClick(View v) 
            System.out.println("Discard onclick!");
        
    );

我在 SO 中也看到了一些关于我此刻面临的问题的帖子,但没有人能弄清楚如何解决它,我想我正在走上好路,但我仍然无法得到它做得对。提前致谢。

【问题讨论】:

【参考方案1】:

终于让它工作了,以防其他人需要这个。我认为这是唯一可能的解决方法...

我添加了一个界面

public interface NavigationDrawerListHandler 
    /**
     * Called when an item in the navigation drawer is selected.
     */
    void selectItem(int position);

NavigationDrawerFragmentProgramsCursorAdapter 实现 NavigationDrawerListHandlerProgramsCursorAdapter 还保留了由方法传递给它的 NavigationDrawerListHandler 类型的引用

ProgramsCursorAdapter.java

public void attach(NavigationDrawerFragment f) 
    try 
        mCallbacks = (NavigationDrawerListHandler) f;
     catch (ClassCastException e) 
        throw new ClassCastException(
                "Fragment must implement NavigationDrawerListHandler.");
    

ProgramsCursorAdapter 的新实例绑定到抽屉的 ListView 时调用,如下所示:

NavigationDrawerFragment.java

// Set up adapter and bind it to the list
ProgramsCursorAdapter adapter = new ProgramsCursorAdapter(getActionBar()
                .getThemedContext(), database.getPrograms(), CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
mDrawerListView.setAdapter(adapter);
// Attach this fragment to the adapter
adapter.attach(this);

这样适配器可以直接访问属于 NavigationDrawerFragment 的 setItem(int position) 方法,并且可以像这样从 onClick(View v) 调用 setItem(int position):

ProgramsCursorAdapter.java

@Override
public void bindView(View v, Context context, Cursor c) 
    /* ... */

    // Get the position of the clicked view
    final int p = c.getPosition();

    tv_name.setOnClickListener(new OnClickListener() 

        @Override
        public void onClick(View v) 
            System.out.println("Program click!");
            selectItem(p);
        
    );

    /* ... */


@Override
public void selectItem(int position) 
    mCallbacks.selectItem(position);

希望这会有所帮助!

【讨论】:

以上是关于处理自定义列表项单击导航抽屉 ListView 内的主要内容,如果未能解决你的问题,请参考以下文章

设置颜色项listview xml

在导航抽屉项目单击时,导航抽屉中的新列表视图

单击抽屉的任何项目而不在android中关闭时更改导航抽屉内的视图和内容

Android片段中的问题:仍然单击上一个片段

Android:如何使用自定义布局创建导航抽屉

如何获取 AlertDialog 中自定义列表视图的单击项的值?