I have a custom ListView with a radiogroup in each row.
When I change the checked radio button, I call a dialog with some edittext fields (using the onCheckedChanged() method). But, when i focused an edittext to write something, I lose all the checked radiobuttons which are covered by keyboard, and the group returns to the default option selected.
can someone help me?
List adapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ContractItemHolder cih = new ContractItemHolder();
if (row == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.row_proposals_item, parent, false);
cih.setTvItemTitle((TextView)row.findViewById(R.id.textViewItemTitle));
cih.setRgItemStatus((RadioGroup)row.findViewById(R.id.radioGroupStatus));
row.setTag(cih);
}else {
cih=(ContractItemHolder)row.getTag();
}
final ContractItem ci = list.get(position);
cih.getRgItemStatus().setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
groupSel = group;
int selected = group.getCheckedRadioButtonId();
Dialog d;
switch (selected) {
case R.id.radioAccepted:
d = createDialog(context, ACCEPTED_CODE, ci, selected);
d.show();
break;
case R.id.radioRefused:
d = createDialog(context, REFUSED_CODE, ci, selected);
d.show();
break;
default:
break;
}
}
});
cih.getTvItemTitle().setText(ci.getDescItem());
return row;
}
List item layout (the row..)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp"
android:gravity="center">
<TextView
android:id="#+id/textViewItemTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Large Text"
android:layout_weight="3"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<RadioGroup
android:id="#+id/radioGroupStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1"
android:showDividers="middle">
<RadioButton
android:id="#+id/radioNull"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Non Proposto"
android:checked="true"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<RadioButton
android:id="#+id/radioPending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="In trattativa"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/Blue"/>
<RadioButton
android:id="#+id/radioAccepted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Accettato"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/Green"/>
<RadioButton
android:id="#+id/radioRefused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rifiutato"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/Red"/>
</RadioGroup>
</LinearLayout>
Dialog impl
private Dialog createDialog(Context context, final int code, ContractItem item,final int selected){ //type: refused, accepted
d = new Dialog(context);
d.setTitle(item.getDescItem());
d.setContentView(R.layout.layout_dialog_prop);
d.getWindow().setLayout(900, LayoutParams.WRAP_CONTENT);
d.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
Button btnOK = (Button)d.findViewById(R.id.buttonPropOK);
Button btnCancel = (Button)d.findViewById(R.id.buttonPropCancel);
btnCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d.dismiss();
}
});
btnOK.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d.dismiss();
}
});
return d;
}
Dialog layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="50dp" >
<EditText
android:id="#+id/editTextDiscount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:ems="10"
android:hint="Sconto proposto"
android:inputType="number"
android:textAppearance="?android:attr/textAppearanceLarge" >
<requestFocus />
</EditText>
<Spinner
android:id="#+id/spinnerScuse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:visibility="gone" />
<EditText
android:id="#+id/editText1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp"
android:ems="10"
android:gravity="top"
android:hint="Note"
android:inputType="textMultiLine"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<View
android:id="#+id/view2"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="30dp"
android:background="#android:color/holo_blue_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="#+id/buttonPropCancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#android:color/transparent"
android:text="Annulla"
android:textColor="#android:color/holo_blue_light" />
<View
android:id="#+id/view1"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#android:color/holo_blue_light" />
<Button
android:id="#+id/buttonPropOK"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#android:color/transparent"
android:text="Ok"
android:textColor="#android:color/holo_blue_light" />
</LinearLayout>
</LinearLayout>
You are partially aware of the list-item view recycling process.
The ListView component doesn't generate view for each item in the list. So, there won't be 15 of them in your case. There will be just as many as can fit on the screen. When you scroll the list, the old items, which are no longer visible, are recycled. The getView is then called with convertView != null and the adapter is giving you an opportunity to update this recycled item view. This is done for performance reasons - just imagine an adapter having 10000 items (not a rare thing in commercial applications). Should it create all 10000 list item views? Imagine the performance you would have while scrolling such a list...
In your getView() code, you update an item view only partially - you always set item title in this line:
cih.getTvItemTitle().setText(ci.getDescItem());
When an fresh item view is created (i.e. the convertView == null) the radio group has a default selection, which may be fine in your case.
However, when the item view is recycled (i.e. the convertView != null), then you:
set a change listener in this line:
cih.getRgItemStatus().setOnCheckedChangeListener(...);
set item title:
cih.getTvItemTitle().setText(ci.getDescItem());
But you never set the checked radio group item. That means, it will have a value which was last set for this instance of item view - not for that position. You should store that information - probably in ContractItem, update it when the radio group item is selected and finally - retrieve it when convertView != null and set selected item of the radio group to the correct value.
You probably see this defect when you open up a dialog - the visible area of a ListView becomes smaller as the soft keyboard opens. This causes the ListView to remove unnecessary (technically: no longer visible) item views. When you hide the soft keyboard, the ListView area becomes larger again thus causing it to create missing item views. Unfortunately, you don't save and restore the last selected item of the radio group and so, after creation the newly visible items have the default item selected in the radio group.
Related
My app utilizes RecyclerView. Here's the xml for the content of each item in the RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cvExpenses"
android:layout_height="wrap_content"
android:layout_width="match_parent"
card_view:cardCornerRadius="5dp"
android:layout_margin="5dp"
card_view:cardBackgroundColor="#009dde"
>
<LinearLayout
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dip">
<TextView
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0"
android:visibility="gone"
android:id="#+id/tvGuestID" />
<TextView
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:id="#+id/tvGuestName"
android:textColor="#ffffff" />
<Switch
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.3"
android:id="#+id/swCheckIn"
android:clickable="true"
android:textOff="no"
android:textOn="yes" />
</LinearLayout>
</android.support.v7.widget.CardView>
Now I got the index of the item in my RecyclerView that I want to toggle it's switch, so here's how I did it:
indexOfGuestIdToCheckIn = listGuestID.indexOf(guestIdToCheckIn);
View view = rvGuestList.getChildAt(indexOfGuestIdToCheckIn);
Switch swCheckIn = (Switch) view.findViewById(R.id.swCheckIn);
swCheckIn.setChecked(true);
I thought the code above would toggle the switch of the selected item in my recyclerview, but instead it returns NullPointerException at Switch swCheckIn = (Switch) view.findViewById(R.id.swCheckIn);
Your views are not inflated yet if they are not visible on screen As this answer has stated. The link also provides an interesting solution you can check.
For your case you should track your models/objects inside on the adapters getView() and decide if it should be checked or not by checking it against a list of your IDs and what values that it should have.
HashMap<Long, Boolean> hashMap = new HashMap<>();
// put values on hashmap
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final <OBJECT> item = getItem(position);
Switch swCheckIn = (Switch) view.findViewById(R.id.swCheckIn);
Boolean isChecked = hashMap.get(item.getId())
if(isChecked != null && isChecked) {
swCheckIn.setChecked(isChecked);
}
}
I have custom template with edittext field. When I click on "next" button on softkeyboard it move focus only two time - than button changed to "OK". List have 12 items.
Any way to navigate to all items, not only 2?
Can you help me please?
Im use this template for listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="3dp" >
<TextView
android:id="#+id/head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:paddingBottom="3dp"
android:paddingTop="3dp" >
<EditText
android:id="#+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:gravity="left"
android:inputType="number" >
<requestFocus />
</EditText>
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceSmall"
android:width="100dp" />
</LinearLayout>
</LinearLayout>
And this xml for listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/calk_1"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="382dp"
android:divider="#color/reddivider"
android:dividerHeight="#dimen/twodp"
android:focusable="true"
android:focusableInTouchMode="true"
android:smoothScrollbar="true" >
</ListView>
</LinearLayout>
Also, here my adapter right now:
public View getView(int position, View convertView, ViewGroup parent){
// assign the view we are converting to a local variable
View v = convertView;
// first check to see if the view is null. if so, we have to inflate it.
// to inflate it basically means to render, or show, the view.
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.list_view, null);
}
/*
* Recall that the variable position is sent in as an argument to this method.
* The variable simply refers to the position of the current object in the list. (The ArrayAdapter
* iterates through the list we sent it)
*
* Therefore, i refers to the current Item object.
*/
CalcItem i = objects.get(position);
int last=getCount()-1;
if (i != null) {
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView hd = (TextView) v.findViewById(R.id.head);
TextView tx = (TextView) v.findViewById(R.id.text);
TextView ds = (TextView) v.findViewById(R.id.description);
EditText vl = (EditText) v.findViewById(R.id.value);
if (position==0){
vl.setNextFocusUpId(last);
vl.setNextFocusDownId(1);
} else if (position==last){
vl.setNextFocusDownId(0);
} else {
vl.setNextFocusDownId(position+1);
}
if (hd != null){
hd.setText(i.getHead());
}
if (tx != null){
tx.setText(i.getText());
}
if (ds != null){
ds.setText(i.getDescription());
}
if (vl != null){
vl.setText(Integer.toString(i.getValue()));
}
}
// the view must be returned to our activity
return v;
}
Use android:nextFocusUp="id" and android:nextFocusDown="id" - as described in the documentation.
Here's an example from the docs:
<LinearLayout
android:orientation="vertical"
... >
<Button android:id="#+id/top"
android:nextFocusUp="#+id/bottom"
... />
<Button android:id="#+id/bottom"
android:nextFocusDown="#+id/top"
... />
</LinearLayout>
As far as I know, Edit texts doesnt work well in ListViews and Recycler views,
I'll Recommend you to inflate separate views multiple times instead of making a ListView if you are dealing with edit texts.
I have ListView which I populate with AutoCompleteTextView and EditText. User can add programatically new rows and edit them. However, when I add two or more rows I cannot type inside second/third and so on AutoCompleteTextView - when I touch the TextView the keyboard appears but I can't type anything because it loses focus on AutoCompleteTextView. Here is my adapter getView and xml with design of row.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
convertView = mInflater.inflate(R.layout.add_meal_activity_list_view_row, null);
holder = new ViewHolder();
holder.productNameTextView = (AutoCompleteTextView) convertView.
findViewById(R.id.mealPartAutoCompleteTextView);
holder.foodQuantityEditText = (EditText) convertView.
findViewById(R.id.mealQuantityEditText);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.foodQuantityEditText
.setText(Utilities.trimDecimalsToString(_mealParts.get(position).foodQuantity));
holder.foodQuantityEditText.addTextChangedListener(new FoodQuantityTextWatcher(position, holder.foodQuantityEditText));
//TODO here fetch real product names from web API
//TODO on item selected - pass to mealPart proudctId of chosen product
ArrayAdapter<String> productNamesAdapter = new ArrayAdapter<String>(_context, android.R.layout.simple_list_item_1, DATA);
holder.productNameTextView.setAdapter(productNamesAdapter);
holder.productNameTextView.addTextChangedListener(new ProductNameTextWatcher(position,holder.productNameTextView));
return convertView;
}
Here is row definition.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:padding="5dp"
android:focusable="true"
android:focusableInTouchMode="true" >
<AutoCompleteTextView
android:id="#+id/mealPartAutoCompleteTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"
android:completionThreshold="2"
android:inputType="textNoSuggestions"
android:textSize="15sp"
style="#style/ListTextView" />
<EditText android:id="#+id/mealQuantityEditText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:inputType="number"
android:textSize="15sp"
style="#style/ListTextView"
/>
</LinearLayout>
And here is activity in which rows of a list are populated.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
style="#style/ListViewStyle"
android:focusableInTouchMode="true"
android:focusable="true">
<EditText android:id="#+id/mealNameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/mealNameTextViewHint"
style="#style/TitleTextViewStyle" />
<ListView android:id="#+id/mealPartsListView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<ImageButton
android:id="#+id/okMealButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="left"
android:src="#drawable/ic_action_accept"
android:contentDescription="#string/addMealPartButtonContentDescription"
android:onClick="onOkMealClick"
android:background="?android:selectableItemBackground"
android:padding="5dp">
</ImageButton>
<ImageButton
android:id="#+id/addMealPartButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="left"
android:src="#drawable/ic_action_new"
android:contentDescription="#string/addMealPartButtonContentDescription"
android:onClick="onAddMealPartButtonClick"
android:padding="5dp"
android:background="?android:selectableItemBackground">
</ImageButton>
<ImageButton
android:id="#+id/addFavouriteMeal"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="left"
android:src="#drawable/ic_action_favorite"
android:contentDescription="#string/addMealPartButtonContentDescription"
android:onClick="onAddMealPartButtonClick"
android:padding="5dp"
android:background="?android:selectableItemBackground">
</ImageButton>
</LinearLayout>
</LinearLayout>
UPDATE
I have looked at LogCat and when I click on AutoComplete that I can't get focus on it logs somethins like this:
01-07 12:35:08.685: E/SpannableStringBuilder(29361): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
This appears to be a Keyboard error for your particular device. See Android - SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
Have you tried testing on the emulator or on other devices?
Additionally, some report that changing the inputType setting has fixed the issue. Try some different options. Since the options for your AutoCompleteTextView are downloaded, you may try setting this field to none:
android:inputType="none"
This is used to answer Android Google Analytics SDK show "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length"
You can get edittext focus using this-
holder.foodQuantityEditText = (EditText) convertView. findViewById(R.id.mealQuantityEditText);
holder.foodQuantityEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(final View v, boolean hasFocus)
{
v.post(new Runnable()
{
#Override
public void run()
{
if (!v.hasFocus()) {
v.requestFocus();
v.requestFocusFromTouch();
}
}
});
}
});
Try some thing like
EditText etselect;
etselect.requestFocus(); // This will provide focus on that.
Hope it helps you some how.!
AutoCompleteTextView will not work with ListView.
When the keyboard is shown, the layout will be either resized or pan(scroll) to fit the keyboard and your AutoCompleteTextView. Due to this the ListView has to refresh itself which make the AutoCompleteTextView to lose focus and the dropdown will never be shown.
I would suggest you to use a ScrollView instead.
I am not sure, but I think if your adapter uses a stable item id then ListView will reuse the same view for particular item and may be AutoCompleteTextView will not lose the focus.
I've created a popup window and put a spinner inside it. But I can't get values when an item is selected from it.
My code to create popup:
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
popwindow=new PopupWindow(inflater.inflate(R.layout.addpain, null,false),300,350,true);
popwindow.showAtLocation(this.findViewById(R.id.tabHost), Gravity.CENTER, 0, 0);
XML file of PopUp
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#A0BBBBBB">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#A0BBBBBB" >
<TextView
android:id="#+id/addpaintext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/addpain"
android:textColor="#000000"
android:textSize="18dp"
android:typeface="serif" />
<EditText
android:id="#+id/statustbox"
android:layout_width="fill_parent"
android:layout_height="150dp"
android:layout_alignParentLeft="true"
android:layout_below="#+id/addpaintext"
android:layout_marginTop="17dp"
android:hint="#string/addpain"
android:inputType="textMultiLine"
android:textColor="#000000"
android:textSize="20dp"
android:typeface="serif" />
<Button
android:id="#+id/addpainbutton"
android:layout_width="80dp"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_below="#+id/statustbox"
android:layout_marginLeft="18dp"
android:layout_marginTop="98dp"
android:onClick="statusupload"
android:text="#string/statusupload" />
<Button
android:id="#+id/cancelbutton"
android:layout_width="80dp"
android:layout_height="45dp"
android:layout_alignBaseline="#+id/addpainbutton"
android:layout_alignBottom="#+id/addpainbutton"
android:layout_alignParentRight="true"
android:layout_marginRight="18dp"
android:onClick="canceladdpain"
android:text="#string/cancel" />
<Spinner
android:id="#+id/spinner_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/addpainbutton"
android:layout_alignRight="#+id/cancelbutton"
android:layout_below="#+id/statustbox"
android:layout_marginTop="20dp"
android:prompt="#string/testtxt"
android:entries="#array/list"/>
</RelativeLayout>
</LinearLayout>
My StatusUpload Function:
public void statusupload(View view)
{
EditText status=(EditText) popwindow.getContentView().findViewById(R.id.statustbox);
Spinner spinner=(Spinner) popwindow.getContentView().findViewById(R.id.spinner_list);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,long id)
{
category=parent.getSelectedItem().toString();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
category="Miscellaneous";
}
});
Toast.makeText(getBaseContext(),category, Toast.LENGTH_LONG).show();
}
What happens is the vraible category isnt getting any values !! IT's just blank.
you're not seeing the results you want because everything hinges on the button to turn on your spinner listener. thus you have have to click the button, make a spinner selection, and then click the button again. I'd seriously reconsider the design. For instance, are you aware that you don't need the listener on to get the item selected? you could just use:
public void statusupload(View view)
{
EditText status=(EditText) popwindow.getContentView().findViewById(R.id.statustbox);
Spinner spinner=(Spinner) popwindow.getContentView().findViewById(R.id.spinner_list);
category = spinner.getSelectedItem().toString();
Toast.makeText(getBaseContext(),category, Toast.LENGTH_LONG).show();
}
I realize there are a ton of questions regarding this issue, but the solution of setting every view in the row.xml to focusable="false" and focusableInTouchMode="false" do not work, nor does getting the ListView from the ListActivity and setting setItemsCanFocus(false).
Weirdly, when registered for a context menu, the long tap works. The regular tap though? Nope. I tried setting listeners like OnItemClickListener to no avail.
I read somewhere that I might be able to remedy this by overriding getView() in my Adapter? I'm not too sure how that works though. Note, I don't want to know what view the user has clicked; I just care about the list row being clicked to initiate the corresponding code in onListItemClick().
Maybe there's something in my row.xml that's all wrong? Or is it affected by the way I set my ListView's adapter (placed in onResume() instead of onCreate() to update information)?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusable="false"
android:focusableInTouchMode="false">
<TextView style="?android:attr/listSeparatorTextViewStyle"
android:id="#+id/listSectionHeader"
android:layout_width = "fill_parent"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="5dp"
android:textColor="#android:color/white"
android:visibility="gone"
android:focusable="false"
android:focusableInTouchMode="false"/>
<RelativeLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="70dp"
android:background="#drawable/list_button"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="true"
android:longClickable="true"
>
<TextView android:id="#+id/itemID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:textStyle="bold"
android:layout_alignParentLeft="true"
android:focusable="false"
android:focusableInTouchMode="false"/>
<CheckBox
android:id="#+id/returnedCheckbox"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:checked="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
/>
<LinearLayout
android:layout_toRightOf="#id/returnedCheckbox"
android:layout_margin="5dp"
android:layout_centerVertical="true"
android:orientation="vertical"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false">
<TextView
android:id="#+id/stuffName"
android:layout_width="fill_parent"
android:lines="1"
android:layout_height="wrap_content"
android:ellipsize="end"
android:scrollHorizontally="true"
android:text="Hey there"
android:textSize="25sp"
android:textColor="#FFF"
android:shadowColor="#000"
android:focusable="false"
android:focusableInTouchMode="false"
/>
<RelativeLayout
android:id="#+id/detailsLayout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false">
<TextView
android:id="#+id/dueListItem"
android:layout_width="wrap_content"
android:lines="1"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="#string/dueListing"
android:focusable="false"
android:focusableInTouchMode="false"/>
<TextView
android:id="#+id/dueDate"
android:layout_toRightOf="#id/dueListItem"
android:layout_marginLeft="2dp"
android:layout_width="90dp"
android:lines="1"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="HEHEHE"
android:focusable="false"
android:focusableInTouchMode="false"/>
<ImageView
android:id="#+id/starMark"
android:layout_alignRight="#id/detailsLayout"
android:layout_toRightOf="#id/dueDate"
android:layout_marginLeft="10dp"
android:layout_marginTop="2dp"
android:layout_height="15dp"
android:layout_width="15dp"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:src="#drawable/list_starred"
android:visibility="invisible"
android:focusable="false"
android:focusableInTouchMode="false"/>
</RelativeLayout>
</LinearLayout>
<ImageView
android:id="#+id/contactPic"
android:layout_alignParentRight="true"
android:layout_height="48dp"
android:layout_width="48dp"
android:background="#FFF"
android:layout_margin="10dp"
android:layout_centerVertical="true"
android:scaleType="fitCenter"
android:padding="3dp"
android:focusable="false"
android:focusableInTouchMode="false"
/>
<ImageView
android:id="#+id/lentArrow"
android:visibility="invisible"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/indicator_lent"
android:layout_marginTop="42dp"
android:layout_marginRight="1dp"
android:focusable="false"
android:focusableInTouchMode="false"/>
</RelativeLayout>
</LinearLayout>
The Onlistitemclick will never be called because there is a clickable view in your list item. Remove the checkbox and see if you are able to get the clicks.
There is an alternative to using using a checkbox directly in your item layout. Use android:choiceMode="multipleChoice" for listview if it suits your needs.
Take a look at this link in how to create a custom adapter:
http://android-er.blogspot.com/2010/06/using-convertview-in-getview-to-make.html
In the Override getView() method, you could just set the row.setOnClickListener() to do what you needed to do when that list item is clicked.
Ideally, you would use convertView to fill a ViewHolder class so that you aren't recreating list items when they have already been created, but that's a different question.
Edit
Here's a slimmed down custom implementation of extending a SimpleCursorAdapter:
public class CatchCursorAdapter extends SimpleCursorAdapter {
private final Context mContext;
private final Cursor mCursor;
private final int layout;
private final LayoutInflater inflater;
private final class ViewHolder {
public ImageView catchImage;
public ImageView catchStar;
public TextView catchSpecies;
}
public CatchCursorAdapter(Context context, int layout, Cursor cursor) {
super(context, layout, cursor, new String[] { }, new int[] { });
this.mContext = context;
this.mCursor = cursor;
this.inflater = LayoutInflater.from(context);
this.layout = layout;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(layout, parent, false);
viewHolder = new ViewHolder();
viewHolder.catchImage = (ImageView)convertView.findViewById(R.id.catch_image);
viewHolder.catchSpecies = (TextView)convertView.findViewById(R.id.catch_species);
viewHolder.catchStar = (ImageView)convertView.findViewById(R.id.catch_starfavorite);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}
convertView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//Perform an action when this list item is clicked
}
});
viewHolder.catchStar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//You can also have buttons within your list item that can be clicked
//independently of the parent list item.
}
});
//Set the rest of your views
return convertView;
}
}
I didn't have to do anything to my adapter; onListItemClick() just miraculously worked on its own for some reason. I'm scratching my head even more right now.
Incidentally, I extended CursorAdapter, not SimpleCursorAdapter, which I understand is sort of different. From what I read, CursorAdapter extension requires only overriding the newView() and bindView() instead of the usual getView() based on this http://www.workreloaded.com/2011/02/android-extending-cursoradapter-for-custom-listview/.