【问题标题】:Custom Listview is not responding to the click event自定义列表视图没有响应点击事件
【发布时间】:2013-01-15 06:44:30
【问题描述】:

正如您猜想的那样,一切正常,没有触发点击事件。 在开始之前,我已经阅读了很多关于此的主题,但是我一生都无法弄清楚。这是代码。

activity_main.xml(调用列表的主布局)

<LinearLayout
    android:orientation="vertical" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

     <ListView
         android:id="@android:id/list"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"

         />

</LinearLayout>

list_mainsegments_row.xml(自定义行)

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:orientation="horizontal" 
        >

        <ImageView
            android:id="@+id/iconView"
            style="@style/generalPagesLogoStyle"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_margin="@dimen/tendpPadding"
            android:scaleType="fitCenter"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:id="@+id/titleMainSegments"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left|center_vertical"
            android:layout_weight="0.5"
            android:text="Medium Text"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textSize="@dimen/generalTextSize"
             />

        <ImageButton
            android:id="@+id/imageButton1"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="center_vertical"
            android:scaleType="fitCenter"
            android:src="@drawable/arrow" />
    </LinearLayout>

MyAdapter.java

   public class MyAdapter extends ArrayAdapter<String> {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            String[] strings) {
        super(context, resource, textViewResourceId, strings);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        // This is a single row
        View row = inflater.inflate(R.layout.list_mainsegments_row, parent,
                false);
        String[] items = getContext().getResources().getStringArray(
                R.array.segments_main);
        ImageView iv = (ImageView) row.findViewById(R.id.iconView);
        TextView tv = (TextView) row.findViewById(R.id.titleMainSegments);
        tv.setText(items[position]);
        organiseLayout(position, items, iv);
        return row;

    }

    private void organiseLayout(int position, String[] items, ImageView iv) {
        if (items[position].equals(getContext().getResources().getString(
                R.string.segment_one))) {
            iv.setImageResource(R.drawable.img1);
        }
        if (items[position].equals(getContext().getResources().getString(
                R.string.segment_two))) {
            iv.setImageResource(R.drawable.img2);
        }
    }
}

MainActivity.java

public class MainActivity extends ListActivity implements OnItemClickListener {

private MyAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mAdapter = new MyAdapter(this, android.R.layout.simple_list_item_1,
            R.id.titleMainSegments, getResources().getStringArray(
                    R.array.segments_main));

    setListAdapter(mAdapter);
    getListView().setOnItemClickListener(this);

}

public void onItemClick(AdapterView<?> parent, View view,
        int position, long id) {
    CharSequence text = "Item clicked";
    int duration = Toast.LENGTH_SHORT;
    Toast toast = Toast.makeText(this, text, duration);
    toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL,
            duration, duration);
    toast.show();
} }

没有错误,所以 logCat 日志不会有用。一切正常,但点击 ListView 时没有显示 Toast。

编辑:

style.xml:

<!-- Global styles -->
    <style name="horizLayoutHolder">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_gravity">center_horizontal</item>
    </style>

    <!-- This is for the text based pages -->
    <style name="general_pages">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:orientation">vertical</item>
        <item name="android:paddingBottom">@dimen/generalPadding</item>
        <item name="android:paddingLeft">@dimen/generalPadding</item>
        <item name="android:paddingRight">@dimen/generalPadding</item>
        <item name="android:paddingTop">@dimen/tendpPadding</item>
    </style>

    <style name="generalPagesTitleStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginBottom">@dimen/tendpPadding</item>
        <item name="android:textColor">#000</item>
        <item name="android:textSize">@dimen/generalHeadingTextSize</item>
        <item name="android:textStyle">bold</item>
    </style>

    <style name="generalPageScrollView">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
    </style>

    <style name="generalPageMainText">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#000</item>
        <item name="android:textSize">@dimen/generalSmallFontSize</item>
    </style>

    <style name="generalPagesLogoStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginBottom">@dimen/tendpPadding</item>
"                <item name="android:src">@drawable/mainlogo</item>
    </style>

    <style name="generalActionButton">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">40dp</item>
        <item name="android:layout_gravity">center_horizontal</item>
        <item name="android:textSize">@dimen/generalVerySmallFontSize</item>
        <item name="android:paddingRight">@dimen/generalPadding</item>
        <item name="android:paddingLeft">@dimen/generalPadding</item>
    </style>

    <style name="generalTextBoxes">
        <item name="android:layout_width">250dp</item>
        <item name="android:layout_height">50dp</item>
        <item name="android:layout_gravity">center_horizontal</item>
        <item name="android:ems">10</item>
        <item name="android:textSize">@dimen/generalSmallFontSize</item>
    </style>

    <!-- End of General / Full text based activities -->


    <!-- I have used this in theme.xml -->
    <style name="windowTitleBackgroundStyle">
        <item name="android:background">#CCCCCC</item>
    </style>

    <style name="windowTitleStyle">
        <item name="android:textColor">#000000</item>
        <item name="android:padding">12dip</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">16sp</item>
    </style>
    <!-- End of Theme.xml stuff -->

主题.xml

<style name="Theme.myTheme.TitleBar" parent="android:Theme">
    <item name="android:windowTitleBackgroundStyle">@style/windowTitleBackgroundStyle</item>
    <item name="android:windowTitleStyle">@style/windowTitleStyle</item>
    <item name="android:windowTitleSize">50dip</item>
    <item name="android:background">#F8C845</item>
    <item name="android:textColor">#555</item>
</style>

【问题讨论】:

  • 超出主题:您的适配器效率不高,您多次检索字符串数组(每次调用 getView 方法时),并且您没有检查是否getView 在再次膨胀新视图之前返回膨胀视图(以便您可以重用它)。考虑阅读THIS

标签: android listview listadapter onitemclicklistener


【解决方案1】:

移除 LinearLayout 属性

android:clickable="true"

来自 XML 文件 list_mainsegments_row.xml,它应该可以正常工作(我刚刚尝试过)。


编辑

当您使用 ListView 的 setOnItemClickListener 方法时,该方法具有包含 Button/ImageButton 的子项,该方法永远不会被触发,因为 Button/ImageButton 会使用该事件。

解决方案是使用 setOnClickListener(针对每个项目)而不是 setOnItemClickListener(针对 ListView)。

为此,您可以通过以下方式将 OnClickListener 传递给适配器:

适配器应该如下:

private OnClickListener callback;

public class MyAdapter extends ArrayAdapter<String> {

public MyAdapter(Context context, int resource, int textViewResourceId,
        String[] strings ,  OnClickListener callback ) {
    super(context, resource, textViewResourceId, strings);
    this.callback = callback;
}

并且在 getView 方法中,只需添加以下几行设置点击侦听器,在填充行视图之后:

// Set a click listener on the row itself
row.setOnClickListener ( callback );
// Set the position as tag so it can be retrieved from the click listener because the click listener itself does not provide the position like done in the onItemClickListener
row.setTag ( position );

现在,MainActivity 应该实现 OnClickListener 而不是 OnItemClickListener,因此删除方法 onItemClick 并从 onItemClick 中删除以下语句strong>onCreate 方法:

getListView().setOnItemClickListener(this);

并添加以下方法:

@Override
public void onClick ( View view ) {
        // view is the row view returned by getView
        // The position is stored as tag, so it can be retrieved using getTag ()
    CharSequence text = "Item clicked : " + view.getTag () ;
    int duration = Toast.LENGTH_SHORT;
    Toast toast = Toast.makeText(this, text, duration);
    toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL,
            duration, duration);
    toast.show();
}

最后,通过以下方式声明适配器:

    mAdapter = new MyAdapter(this, android.R.layout.simple_list_item_1,
            R.id.titleMainSegments, getResources().getStringArray(
                    R.array.segments_main) , this );

编辑

解释:

当您的 ListView 包含包含按钮(或类似)的项目时,您会遇到一个常见问题。

在这种情况下,如果您想单独为按钮设置一个单击事件,而为项目的其余部分设置另一个单击事件(如果用户单击项目而不是按钮),这就是问题所在hits : 按钮使用项目的 clickable 属性,这意味着如果项目不包含任何按钮,则默认情况下它是可点击的(您可以尝试删除按钮)但如果项目包含按钮,它将是可点击的,因为它有一个本身是可点击的视图。

因此,即使您设置了 OnItemClick 事件,如果项目中有按钮(或类似的东西,如图像按钮),它也不会被调用,因为它(按钮)会消耗点击事件。

所以在这种情况下,您不能使用 OnItemClick 事件(直接在 ListView 上分配)。

一种解决方案是为每个项目分配点击事件(使用 OnItemClick),而不是让 ListView 处理它(因为它不会像上面解释的那样工作)。

您将不得不直接在项目上分配 OnClick 事件(这毕竟是一个视图),这就是为什么我在适配器的 getView 方法中分配 OnClick 监听器,其中项目视图正在构建中。

到目前为止,在适配器的 getView 方法中分配的侦听器数量与屏幕上可见的项目一样多,而不是只有一个侦听器 (OnItemClick)。

如果用户单击项目视图中的任何位置,则将触发 OnClick 侦听器,除非他/她单击的位置是可单击的视图(如按钮...)。

所以通过这种方式问题解决了,你可以给按钮分配一个点击监听器,给项目视图分配一个点击监听器。

如果用户点击了item的按钮,就会执行该按钮的点击监听。 如果用户在项目视图内部单击而不是在按钮上单击,则执行项目视图的单击侦听器,因为单击侦听器是在项目视图本身上设置的。

一个小问题是,使用上面的方法,我们不能直接知道被点击的项目视图的位置,因为如果我们使用 OnItemClick 监听器,回调会在参数中提供位置,但是在OnClick 监听器,你只有被点击的视图作为参数。

为了解决这个小问题,您可以使用 view.setTag ( ... ) 将视图的位置作为标签存储在视图本身上,并使用 view.getTag ()。实际上,任何视图都可以有一个标签,该标签存储为 object,因此在检索它时,将其转换回所需的数据类型。

通过这种方式,您可以知道处理 ListView 项目上的点击事件,并知道点击项目的位置,就像您使用 OnItemClick 监听器一样。

希望对你有帮助。

【讨论】:

  • 是的,我确定。能否请您发布 @style/generalPagesLogoStyle 的内容?
  • 好了,伙计。我已经添加到问题中。再次感谢。
  • 我已经编辑了我的答案,请查看 EDIT 部分。试试看,让我知道会发生什么。
  • 谢谢伙计。有效。你能简单解释一下刚刚发生的事情吗?为什么我的方法是错误的?
  • 请参阅我回答的第二个编辑部分。
猜你喜欢
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
相关资源
最近更新 更多