Reputation: 3152
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.
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.
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:clickable="false"
to my ImageView
.
android:focusable="false"
and android:focusableInTouchMode="false"
to both TextView
s.
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:
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>
Upvotes: 1
Views: 2621
Reputation: 120
Asked by many, The TextViews in list should not have width match parent.
Even if you set the "Focusable" to false it wont work. Set the TextView Width to wrap_content
<TextView
android:id="@+id/itemchild"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
Upvotes: 0
Reputation: 11
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)
Don't use android:inputType with TextView.
It worked perfectly for me
Upvotes: 0
Reputation: 7132
Set all child views inside listView items to not focusable or clickable.
android:focusable="false"
android:clickable="false"
If it is not enough try setting
android:descendantFocusability="blocksDescendants
to text_listview_row.xml linearlayout &
android:textIsSelectable="false"
to textview's inside 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!
Upvotes: 2
Reputation: 544
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) {
...
Upvotes: 0
Reputation: 12530
Try setting the below tag fro your views inside list item view xml (text_listview_row.xml)
android:focusable="false"
so that list item click will work always perfectly
Upvotes: 0