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.
Related
I'm beginner in android development and i a have question about Listview and android:onclick attribute.
I try to use attribute android:onclick ="myMethod" on each element of my listview instead of define OnItemClickListener/onItemClick (too much verbose for me)
MyMethod is executed but how can i get clicked element (current context) ?
Thanks in advance
As a beginner, setting an OnItemClickListener might seem a bit scary, but it's really not a big deal at all (and a core concept you should be learning anyway!).
So if you have a simple layout with a ListView in it like this...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/containerView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/myListview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
You can set up an OnItemClickListener with just this code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_listview_layout);
listView = (ListView)findViewById(R.id.myListview);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Every time an item is clicked, you can handle it right here.
}
});
}
So every time an item in your list is clicked, the onItemClick method is fired, and you can figure out which item was clicked by using the int position argument that comes in.
If i am right your question is about implementing on click listener on each listrow item instead of list row.
If that is correct this is how you should implement:
1.In your adapter of getView() method you might be inflating a layout for list row like below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_layout, parent, false);
return convertView;
}
In the above code list_row_layout is the xml file i'm inflating.
Go to that layout and add the following line android:descendantFocusability="blocksDescendants" to the root level of the xml layout like below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="4dp"
android:descendantFocusability="blocksDescendants"<!--This is the line i'm talking about-->
android:background="#drawable/rounded_border_layout"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="40dp"
android:layout_marginRight="10dp"
android:id="#+id/review_main_user_image_layout"
android:layout_marginLeft="10dp"
android:layout_height="54dp">
<ImageView
android:layout_width="40dp"
android:id="#+id/review_main_user_image"
android:background="#drawable/reviews_x_trail_user_image_border"
android:layout_height="40dp"
android:src="#drawable/ic_help_user" />
<TextView
android:typeface="monospace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Me"
android:textSize="10sp"
android:layout_gravity="center"
android:singleLine="true"
android:id="#+id/review_main_user_name"
android:layout_below="#+id/review_main_user_image" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/review_main_user_image_layout"
android:layout_toEndOf="#+id/review_main_user_image_layout">
<TextView
android:layout_marginLeft="8dp"
android:layout_width="wrap_content"
android:textColor="#color/black"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="#+id/review_main_title"
android:text="Good Product For The Price"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:orientation="horizontal">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/review_main_rating"
android:progressDrawable="#drawable/apptheme_ratingbar_small_holo_light"
android:numStars="5"
style="?android:attr/ratingBarStyleSmall" />
<TextView
android:layout_marginLeft="8dp"
android:text="12-Jun-1993"
android:id="#+id/review_main_date"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
That't it now in your adapter getView method you can implement on click listener for each widget you have in that layout.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ReviewsXTrailViewHolder reviewsXTrailViewHolder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_row_review_main, parent, false);
TextView title = (TextView)convertView.findViewById(R.id.review_main_user_image);
//title.setOnclickListener()
return convertView;
}
In that above code i have added on click listener for textview.I hope it will work
Comment below if that doesn't work
I have created a dynamic add/removable UI where the user will enter an item's cost in a edit text, and when the user click add. The value will be saved in an ArrayList and at the same time a text view will be added with the same value in there. When the user click remove, the value will be removed from the ArrayList, and the text view will be removed as well.
So it works just the way I wanted had the user enter something like [1.00 2.00 3.00 4.00 5.00 6.00].
However if the user enter something with a duplicate value like [1.00 2.00 3.00 2.00 4.00 2.00].
If remove was clicked on one of the text view with value "2.00", then sometimes the incorrect index with "2.00" will be removed, and the sequence inside my ArrayList becomes out of sync with my text view.
I've been trying several approaches for the past 2 weeks, but just couldn't get it right. If you guys can help me out?
Below is my implementation:
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/rowLinearLayoutItem"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginRight="50dp"
android:layout_marginLeft="50dp"
android:baselineAligned="true" >
<Button
android:id="#+id/rowButtonRemove"
android:text="-"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#drawable/circle_button"/>
<TextView
android:id="#+id/rowItemCost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:inputType="numberDecimal"
android:ems="10"
android:layout_weight="1" />
<TextView
android:id="#+id/rowItemTotal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:inputType="numberDecimal"
android:ems="10"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
Fragment.java
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.advButtonAddItem:
String itemAddString = editBoxItemAdd.getText().toString();
if (itemAddString.isEmpty()){
Toast.makeText(getActivity(), "Please Enter Item Cost", Toast.LENGTH_LONG).show();
}
else {
LayoutInflater layoutInflater = (LayoutInflater) getActivity().getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View addView = layoutInflater.inflate(R.layout.row, null);
final TextView rowItemTotal = (TextView) addView.findViewById(R.id.rowItemTotal);
Button rowButtonRemove = (Button) addView.findViewById(R.id.rowButtonRemove);
rowItemTotal.setText(editBoxItemAdd.getText().toString());
itemList.add(rowItemTotal.getText().toString());
updateCost();
rowButtonRemove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((LinearLayout)addView.getParent()).removeView(addView);
itemList.remove(rowItemTotal.getText().toString()); //Remove inputted Item Cost into ArrayList itemList
updateCost();
}
});
row.addView(addView);
}
break;
}
}
((LinearLayout)addView.getParent()).removeView(addView);
it will always delets the previously added item
because addview is the lastitem you used
so change it to
((LinearLayout)addView.getParent()).removeView(v);
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 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.
Is it possible to use a OnItemClickListener on a ListView when the Items layout has a clickable/editable widget (RadioButton,EditText, or CheckBox)?
You might want to take a look at this issue. Having a focusable item in a row of a ListView causes the OnItemClickListener NOT to be invoked. However, that does not mean you cannot have focusable/clickable items in a row, there are some workarounds like this one.
Also, you can take a look at the Call Logs screen. It has a ListView with clickable item(the call icon on the right).
See Source code here
Quoting comment #31 in the link mentioned by Samuh (which solved the problem for me):
In fact you can add it to the layout XML (if inflated by one): android:descendantFocusability="blocksDescendants".
Adding here JIC that webpage is down in the future.
If any row item of list contains focusable or clickable view then OnItemClickListener won't work.
row item must be having param like android:descendantFocusability="blocksDescendants"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical" >
// your other widgets here
</LinearLayout>
Tried many complex solutions, but this was the simplest one that worked:
Just use android:focusable="false" as in:
<CheckBox
android:id="#+id/fav_check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false" />
Two best solution
Add android:descendantFocusability="beforeDescendants" to listView
in xml OR
Set given two attributes to false
like
android:focusable="false"
android:focusableInTouchMode="false"
Then it will handle the listView row item child(Button,EditText etc) events instead of listView.setOnItemClick .
I fixed my problem different , in my item I have more than one LinearLayout
so if you give id to your linearayout and setOnclickListener in adapter class it will work, only original effect of touching will dissapear.
but this link Making a LinearLayout act like an Button is usefull to make linearlaout act like button on click
item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp">
<TextView
android:id="#+id/txt_item_followers_name"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center|start"
android:paddingLeft="15dp"
android:text="Ali"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ImageView
android:id="#+id/imageView"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentStart="true"
android:layout_below="#+id/txt_item_followers_name"
android:layout_marginLeft="10dp"
android:src="#drawable/puan_icon" />
<TextView
android:id="#+id/txt_item_followers_mark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/imageView"
android:layout_toEndOf="#+id/imageView"
android:background="#color/red_400"
android:paddingLeft="10dp"
android:text="25.5"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout
android:id="#+id/linear_one"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/txt_item_followers_name"
android:background="#color/red_400"
android:orientation="vertical">
<ImageView
android:id="#+id/btn_item_followers_2b_follow"
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_marginLeft="10dp"
android:src="#drawable/follow_buton" />
</LinearLayout>
</RelativeLayout>
inside getView method
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
if (convertView == null)
view = inflater.inflate(R.layout.deneme, null);
final Followers2 myObj = myList.get(position);
LinearLayout linear_one = (LinearLayout) view.findViewById(R.id.linear_one); // HERE WE DOMUNÄ°CATE IT
linear_one.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(parentActivity, "One Two", Toast.LENGTH_SHORT).show();
}
});
TextView name = (TextView) view.findViewById(R.id.txt_item_followers_name);
TextView mark = (TextView) view.findViewById(R.id.txt_item_followers_mark);
final ImageView btn_follow = (ImageView) view.findViewById(R.id.btn_item_followers_2b_follow);
name.setText(myObj.getName());
mark.setText(myObj.getScore());
/* if (myObj.isFollow() == true) {
btn_follow.setImageResource(R.drawable.following_buton);
} else {
btn_follow.setImageResource(R.drawable.follow_buton);
}
btn_follow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Followers2 myObj = myList.get(position);
if (myObj.isFollow() == true) {
btn_follow.setImageResource(R.drawable.following_buton);
} else {
btn_follow.setImageResource(R.drawable.follow_buton);
}
}
});*/
return view;
}