ListView onItemClickListener仅适用于自定义行的一部分

时间:2021-11-21 14:12:55

I have a custom ListView where each row consists of 3 items, a TextView (title), an ImageView (placeholder icon), and another TextView (content text). I have an OnItemLongClickListener set on the ListView and it is supposed to be that when a user clicks on the item in the ListView (which should be the entire row of 3 items all together as one), then a dialog comes up giving them the option to delete the whole item, which would then delete all 3 parts of that single list item.

我有一个自定义ListView,其中每行包含3个项目,一个TextView(标题),一个ImageView(占位符图标)和另一个TextView(内容文本)。我在ListView上设置了一个OnItemLongClickListener,它应该是当用户点击ListView中的项目时(它应该是3个项目的整个行一起作为一个),然后会出现一个对话框,为他们提供选项删除整个项目,然后删除该单个列表项目的所有3个部分。

But long clicking on the title view and the image do not trigger the listener. Only if the content TextView is long clicked, does the dialog box come up, which then deletes all 3, but clicking anywhere in the row should do that. However it doesn't. I need to find a solution because the user will not know to only click on the content TextView, they should be able to click anywhere.

但是长按标题视图和图像不会触发监听器。只有长时间单击TextView内容时,对话框才会出现,然后删除所有3,但单击行中的任何位置都应该这样做。但事实并非如此。我需要找到一个解决方案,因为用户不会知道只点击内容TextView,他们应该可以在任何地方点击。

I have looked on here to find a solution, and have tried adding these lines, but nothing has worked:

我已经在这里寻找解决方案,并尝试添加这些行,但没有任何工作:

android:descendantFocusability="blocksDescendants" added to my ListView's LinearLayout.

android:descendantFocusability =“blocksDescendants”添加到我的ListView的LinearLayout中。

android:clickable="false" to my ImageView.

android:clickable =“false”到我的ImageView。

android:focusable="false" and android:focusableInTouchMode="false" to both TextViews.

两个TextViews的android:focusable =“false”和android:focusableInTouchMode =“false”。

I don't have anything else to try. Any ideas?

我没有别的尝试。有任何想法吗?

ListView onItemClickListener仅适用于自定义行的一部分

UPDATE

When I added extra lines, like @Amrit suggested (code in his answer), the whole area when long clicked does now bring up the dialog box, but it creates this strange tint on the area I click, but only if I click the title TextView or the ImageView area. Oddly, that 2nd TextView still looks good and produces the dialog box as it should. Not sure how to get rid of this misaligned tint though:

当我添加额外的行,比如@Amrit建议(代码在他的答案中)时,长时间点击的整个区域现在会调出对话框,但它会在我点击的区域上创建这种奇怪的色调,但仅当我点击标题时TextView或ImageView区域。奇怪的是,第二个TextView看起来仍然很好,并按原样生成对话框。不知道如何摆脱这种错位色调但是:

ListView onItemClickListener仅适用于自定义行的一部分

TextTab.java

package org.azurespot.cutecollection.texttab;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

import org.azurespot.R;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;


/**
 * Created by mizu on 2/8/15.
 */
public class TextTab extends Fragment {

    private ArrayList<PoemListItem> poems = new ArrayList<>();
    private ListViewPoemAdapter adapter;
    private ListView listView;
    String[] allSDCardFiles = null;
    StringBuilder text;
    PoemListItem wordsFromFile;
    File[] files;
    PoemListItem sampleItem;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.text_tab, container, false);
        adapter = new ListViewPoemAdapter(getActivity(), poems);
        // Attach the adapter to a ListView
        listView = (ListView) v.findViewById(R.id.text_list_view);
        listView.setAdapter(adapter);

        if(adapter.getCount() == 0) {
            // load contents of SD card
            loadSDCard();
        }

        setupListViewListener();

        return v;

    }

    private void loadSDCard(){

        try {
            // gets directory CuteWords from sd card
            File cuteWordsDir = new File(Environment.getExternalStoragePublicDirectory
                    (Environment.DIRECTORY_DOCUMENTS), "/Cute Words");

            if (!cuteWordsDir.exists()){
                cuteWordsDir.mkdir();
            }

            if (cuteWordsDir.isDirectory()) {
                // lists all files in CuteWords, loads in Files[] array
                files = cuteWordsDir.listFiles();

                for (File singleFile : files) {
                    //Read text from file, put each line into StringBuilder
                    text = new StringBuilder();

                    BufferedReader br = new BufferedReader(new FileReader(singleFile));
                    String line;

                    while ((line = br.readLine()) != null) {
                        text.append(line);
                        text.append('\n');

                        // get full file name with ext. and text in file
                        wordsFromFile = new PoemListItem(singleFile.getName(), text.toString());

                        adapter.add(wordsFromFile);
                        adapter.notifyDataSetChanged();
                    }
                }
            }

            // get number of files in CuteWords directory
            allSDCardFiles =  new String[files.length];

            // create a blank String version of PoemListItem
            sampleItem = new PoemListItem(" ", " ");

            // add the default icon/lines remaining to ArrayList (through adapter),
            // if less than 9 files on SD card
            for (int i = 0; i < (9 - allSDCardFiles.length); i++) {
                adapter.add(sampleItem);
            }
            adapter.notifyDataSetChanged();

        } catch(IOException e){
                e.printStackTrace();
            }
    }

    // so you can edit any of the list items
    private void setupListViewListener() {

        // to delete a list item
        listView.setOnItemLongClickListener(new ListView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> aView, View item,
                                                        final int pos, long id) {


                if (adapter.getItem(pos) != sampleItem) {

                    new AlertDialog.Builder(getActivity())
                            .setTitle("Delete")
                            .setMessage("Delete these cute words?")
                            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    // delete from ArrayList first
                                    poems.remove(pos);
                                    adapter.notifyDataSetChanged();

                                    // get file name then delete it
                                    String name = files[pos].getName();
                                    File file = new File(Environment.getExternalStorageDirectory(),
                                            "/Documents/Cute Words/" + name);
                                    file.delete();

                                    // clear list and adapter
                                    poems.clear();
                                    adapter.clear();
                                    adapter.notifyDataSetChanged();

                                    // after each item delete, must refresh load with new arrangement
                                    loadSDCard();

                                }
                            })
                            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {

                                    // do nothing
                                    dialog.cancel();

                                }
                            })
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .show();

                    }

                return true;
            }
        });

    }
}

ListViewPoemAdapter

package org.azurespot.cutecollection.texttab;

import android.content.Context;
import android.text.InputType;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import org.azurespot.R;

import java.util.ArrayList;

/**
 * Created by mizu on 2/8/15.
 */
public class ListViewPoemAdapter extends ArrayAdapter<PoemListItem> {

    private TextView poemText;
    private TextView poemTitle;
    private ImageView poemPlaceholder;


    public ListViewPoemAdapter(Context context, ArrayList<PoemListItem> poems) {
        super(context, 0, poems);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        PoemListItem poemListItem = getItem(position);

        if (convertView == null) {
            convertView = LayoutInflater.from(getContext())
                    .inflate(R.layout.text_listview_row, parent, false);
        }

        poemTitle = (TextView) convertView.findViewById(R.id.text_title);
        poemText = (TextView) convertView.findViewById(R.id.text);
        poemPlaceholder = (ImageView)convertView.findViewById(R.id.icon_placeholder_poem);

        poemText.setInputType(InputType.TYPE_CLASS_TEXT |
                              InputType.TYPE_TEXT_FLAG_MULTI_LINE |
                              InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);

        poemText.setMovementMethod(new ScrollingMovementMethod());

        poemPlaceholder.setBackgroundResource(R.drawable.ic_poem_placeholder);
        poemPlaceholder.setScaleType(ImageView.ScaleType.CENTER_CROP);
        poemPlaceholder.setLayoutParams(new LinearLayout.LayoutParams(150, 150));

        poemTitle.setText(poemListItem.getTitle());
        poemText.setText(poemListItem.getPoem());

        return convertView;

    }


}

text_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants"
    android:background="#2198bb">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/text_list_view"
        android:layout_centerHorizontal="true"
        android:layout_margin="10dp"
        android:scrollbarStyle="outsideOverlay"
        android:verticalScrollbarPosition="right"
        android:divider="@null"/>

</LinearLayout>

text_listview_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:paddingBottom="20dp">

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

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="false"
            android:id="@+id/icon_placeholder_poem"
            android:layout_marginRight="15dp"
            android:layout_marginEnd="15dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/text_title"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:textSize="25sp"
            android:textStyle="bold|italic"
            android:hint="Title"
            android:ellipsize="start"/>


    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/text"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:gravity="top"
        android:maxLines="10"
        android:inputType="textMultiLine"
        android:scrollHorizontally="false"
        android:scrollbars="vertical"
        android:textSize="20sp"
        android:ems="10"
        android:textStyle="italic"
        android:hint="Quote or poem, here."
        android:ellipsize="start"/>

    <!--Line in-between the rows-->
    <View
        android:layout_width="fill_parent"
        android:layout_height="2dp"
        android:background="#7e8287"
        android:paddingTop="20dp" />


</LinearLayout>

4 个解决方案

#1


Set all child views inside listView items to not focusable or clickable.

将listView项目中的所有子视图设置为不可聚焦或可单击。

android:focusable="false"
android:clickable="false"

If it is not enough try setting

如果还不够,请尝试设置

android:descendantFocusability="blocksDescendants

to text_listview_row.xml linearlayout &

到text_listview_row.xml linearlayout&

android:textIsSelectable="false"

to textview's inside text_listview_row.xml

到textview的text_listview_row.xml里面

UPDATE

Actually all that I needed was that one line android:descendantFocusability="blocksDescendants" but inside of my LinearLayout parent of the text_listiew_row.xml (not needed in text_tab.xml). Thank you!

实际上,我需要的只是一行android:descendantFocusability =“blocksDescendants”,但在text_listiew_row.xml的LinearLayout父级内部(text_tab.xml中不需要)。谢谢!

#2


Try setting the below tag fro your views inside list item view xml (text_listview_row.xml)

尝试在列表项视图xml(text_listview_row.xml)中为视图设置以下标记

android:focusable="false"

so that list item click will work always perfectly

这样列表项单击将始终完美

#3


I think the problem lies in this line:

我认为问题出在这一行:

if (adapter.getItem(pos) != sampleItem) {

Add log before to verify that method was invoked successfully.

之前添加日志以验证是否已成功调用该方法。

Log.d("TextTab", "onItemLongClick");
if (adapter.getItem(pos) != sampleItem) {
    ...

#4


This isn't your case, but I had similar problem with click on a custom layout item. After a hour of looking for solution a found out that I set android:inputType to TextView inside my layout file which was blocking onClick() listener (no idea why)

这不是你的情况,但我点击自定义布局项有类似的问题。经过一个小时的寻找解决方案后发现我在我的布局文件中设置了android:inputType到TextView,这阻止了onClick()监听器(不明白为什么)

Don't use android:inputType with TextView.

不要在TextView中使用android:inputType。

It worked perfectly for me

它对我来说很完美

#1


Set all child views inside listView items to not focusable or clickable.

将listView项目中的所有子视图设置为不可聚焦或可单击。

android:focusable="false"
android:clickable="false"

If it is not enough try setting

如果还不够,请尝试设置

android:descendantFocusability="blocksDescendants

to text_listview_row.xml linearlayout &

到text_listview_row.xml linearlayout&

android:textIsSelectable="false"

to textview's inside text_listview_row.xml

到textview的text_listview_row.xml里面

UPDATE

Actually all that I needed was that one line android:descendantFocusability="blocksDescendants" but inside of my LinearLayout parent of the text_listiew_row.xml (not needed in text_tab.xml). Thank you!

实际上,我需要的只是一行android:descendantFocusability =“blocksDescendants”,但在text_listiew_row.xml的LinearLayout父级内部(text_tab.xml中不需要)。谢谢!

#2


Try setting the below tag fro your views inside list item view xml (text_listview_row.xml)

尝试在列表项视图xml(text_listview_row.xml)中为视图设置以下标记

android:focusable="false"

so that list item click will work always perfectly

这样列表项单击将始终完美

#3


I think the problem lies in this line:

我认为问题出在这一行:

if (adapter.getItem(pos) != sampleItem) {

Add log before to verify that method was invoked successfully.

之前添加日志以验证是否已成功调用该方法。

Log.d("TextTab", "onItemLongClick");
if (adapter.getItem(pos) != sampleItem) {
    ...

#4


This isn't your case, but I had similar problem with click on a custom layout item. After a hour of looking for solution a found out that I set android:inputType to TextView inside my layout file which was blocking onClick() listener (no idea why)

这不是你的情况,但我点击自定义布局项有类似的问题。经过一个小时的寻找解决方案后发现我在我的布局文件中设置了android:inputType到TextView,这阻止了onClick()监听器(不明白为什么)

Don't use android:inputType with TextView.

不要在TextView中使用android:inputType。

It worked perfectly for me

它对我来说很完美