简体   繁体   English

自定义列表视图不响应click事件

[英]Custom Listview is not responding to the click event

As you would guess everything loads fine, no click event get triggered. 正如您猜测一切正常,没有触发点击事件。 Before I start I have read so many thread about this however I for the life of me I cant figure it out. 在我开始之前,我已经阅读了很多有关此事的帖子,但是对于我的生活,我无法弄明白。 Here is the code. 这是代码。

activity_main.xml (Main Layout to call the list) 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 (Custom Row) 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 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 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();
} }

There is no error so the logCat log is not going to be useful. 没有错误,因此logCat日志不会有用。 All comes up well but no Toast is showing when ListView is tapped. 一切顺利,但点击ListView时没有Toast显示。

Edit: 编辑:

style.xml: 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 -->

themes.xml 的themes.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>

Remove the LinearLayout attribute 删除LinearLayout属性

android:clickable="true"

from the XML file list_mainsegments_row.xml and it should work fine (I have just tried it). 从XML文件list_mainsegments_row.xml ,它应该工作正常(我刚刚尝试过)。


EDIT 编辑

When you use the setOnItemClickListener method of the ListView having childs that contain a Button/ImageButton, the method is never fired because the Button/ImageButton consumes the event. 当您使用具有包含Button / ImageButton的子项的ListView的setOnItemClickListener方法时,永远不会触发该方法,因为Button / ImageButton使用该事件。

The solution is to use setOnClickListener (for every item) instead of setOnItemClickListener (for the ListView). 解决方案是使用setOnClickListener (对于每个项目)而不是setOnItemClickListener (对于ListView)。

In order to do that, you can pass the OnClickListener to the adapter in the following manner : 为此,您可以通过以下方式将OnClickListener传递给适配器:

The adapter should be as follows : 适配器应如下:

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;
}

And in the getView method, just add the following lines that set the click listener, after inflating the row view : 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 );

And now, the MainActivity should implement OnClickListener instead of OnItemClickListener , so remove the method onItemClick and also remove the following statement from the onCreate method : 现在,MainActivity应该实现OnClickListener而不是OnItemClickListener ,因此删除方法onItemClick并从onCreate方法中删除以下语句:

getListView().setOnItemClickListener(this);

And add the following method : 并添加以下方法:

@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();
}

And finally, declare the Adapter in the following manner : 最后,按以下方式声明适配器:

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

EDIT 编辑

Explanation : 说明:

What happened with you is a common issue that occurs when you have a ListView with items that contain buttons (or the like). 发生在你身上的事情是一个常见的问题,当你有一个包含按钮 (或类似物品)的项目的ListView时。

In this case, if you want to have a click event for the button alone, and another click event for the rest of the item (if the user clicks in the item but not on the button), this is where the problem hits : the botton consumes the clickable attribute of the item, meaning that if the item does not contain any buttons it will be clickable by default (you can try to remove the button) but if the item contains a button, it will be clickable because it has a view that itself is clickable. 在这种情况下,如果您希望单独为按钮设置单击事件,并为项目的其余部分设置另一个单击事件(如果用户单击该项而不是按钮),则问题就出现了: botton消耗该项目的可点击属性,这意味着如果该项目不包含任何按钮,则默认情况下它将是可点击的(您可以尝试删除该按钮)但如果该项目包含按钮,则​​该项目将是可点击的,因为它具有查看本身是可点击的。

Therefore, even if you set the OnItemClick event, it will NOT be called if the item HAS a button (or something similar, like an image button) in it, because it (the button) will consume the click event. 因此,即使您设置OnItemClick事件,如果项目中有一个按钮(或类似的图像按钮),也不会调用它,因为它(按钮)将消耗click事件。

So in this case you cannot use the OnItemClick event (which is assigned on the ListView directly). 因此,在这种情况下,您无法使用OnItemClick事件(直接在ListView上分配)。

A solution would be to assign the click event on each item (using OnItemClick) instead of letting the ListView handling it (because it will not work as explained above). 解决方案是在每个项目上分配click事件(使用OnItemClick)而不是让ListView处理它(因为它不会像上面解释的那样工作)。

You will have to assign the OnClick event directly on the item (which is a view after all), this is why I assigned the OnClick listener in the getView method of the Adapter, where the item view is being constructed. 您必须直接在项目上分配OnClick事件(毕竟这是一个视图),这就是为什么我在适配器的getView方法中分配了OnClick侦听器,其中正在构建项目视图。

So far, instead of having just one listener (OnItemClick), there is as many listeners as items that are visible on the screen, assigned in the getView method of the adapter. 到目前为止,不是只有一个监听器(OnItemClick),而是在屏幕上可见的项目,在适配器的getView方法中分配的监听器数量。

The OnClick listener will be fired if a user clicks anywhere in the item view EXCEPT if where he/she clicks there is a clickable view (like a button ...). 如果用户单击项目视图中的任何位置,将触发OnClick侦听器,除非他/她单击其中有可点击的视图(如按钮...)。

So in this manner the problem is solved, you can assign a click listener to the button and a click listener to the item view. 因此,通过这种方式问题得以解决,您可以为按钮分配单击侦听器,并为项目视图分配单击侦听器。

If the user clicks on the button of the item, the click listener of the button is executed. 如果用户单击该项的按钮,则执行该按钮的单击监听器。 If the user clicks insides the item view but not on the button, the click listener of the item view is executed because the click listener is set on the item view itself. 如果用户单击项目视图但不在按钮上,则执行项目视图的单击侦听器,因为在项目视图本身上设置了单击侦听器。

One small issue is that, using the approach above, we cannot directly know what is the position of the clicked item view, because if we were using the OnItemClick listener, the call back provides the position in the argument, however in the OnClick listener, you only have the View which was clicked as argument. 一个小问题是,使用上面的方法,我们无法直接知道被点击的项目视图的位置,因为如果我们使用OnItemClick侦听器,则回调提供参数中的位置,但是在OnClick侦听器中,你只有被点击的视图作为参数。

In order to solve this small issue, you can store the position of the view as a tag on the view itself using view.setTag ( ... ) and retrieve what you previously stored using view.getTag () . 为了解决这个小问题,您可以使用view.setTag(...)将视图的位置作为标记存储在视图本身上,并使用view.getTag()检索先前存储的内容 Actually any view can have a tag, which is stored as object , so while retrieving it, cast it back to the required data type. 实际上,任何视图都可以有一个标记,它存储为对象 ,因此在检索它时,将其强制转换为所需的数据类型。

In this manner, you can know handle click events on ListView items, and know the position of the click item, just like as if you were using a OnItemClick listener. 通过这种方式,您可以了解ListView项目上的句柄点击事件,并了解点击项目的位置,就像您使用OnItemClick侦听器一样。

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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