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 TextView
s.
两个TextViews的android:focusable =“false”和android:focusableInTouchMode =“false”。
I don't have anything else to try. Any ideas?
我没有别的尝试。有任何想法吗?
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看起来仍然很好,并按原样生成对话框。不知道如何摆脱这种错位色调但是:
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
它对我来说很完美