Weird Spinner behaviour - android

I have used a custom adapter for populating my Spinner. I have overriden getDropDownView from which I return the view of each row of the dropdown list. Everything works fine except the dropdown list rendered is not getting the width of the Spinner widget. Rather it gets Like this:
So the dropdown list is missing the highlighted width. I dont know why this is happening. I want it to get the full width of the spinner.
My custom adapter:
class CategorySpinnerAdapter extends ArrayAdapter{
private Activity context;
ArrayList<Category> categoryList;
public CategorySpinnerAdapter(Activity context,int resourceID,ArrayList<Category> categoryList)
{
super(context,resourceID,categoryList);
this.context=context;
this.categoryList=categoryList;
}
#Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView==null)
{
LayoutInflater inflater=context.getLayoutInflater();
convertView=inflater.inflate(R.layout.category_spinner_row, parent,false);
}
Category currentCategory=categoryList.get(position);
TextView categoryText=(TextView) convertView.findViewById(R.id.spinnerText);
categoryText.setText(currentCategory.getCategoryName());
return convertView;
}
}
Code, where I am setting this adapter:
Spinner categorySpinner=(Spinner) getActivity().findViewById(R.id.categorySpinner);
ArrayList<Category> categoryList=populateCategoryList();
CategorySpinnerAdapter categorySpinnerAdapter=new CategorySpinnerAdapter(getActivity(), android.R.layout.simple_spinner_item,categoryList);
categorySpinner.setAdapter(categorySpinnerAdapter);
categorySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView,
int position, long id) {
// TODO Auto-generated method stub
ArrayList<Reward> modifiedList=new ArrayList<Reward>();
//test case: category OK
int categoryID=position+1;
for(int i=0;i<rewardList.size();i++)
{
if(rewardList.get(i).getCategoryID()==categoryID)
{
modifiedList.add(rewardList.get(i));
}
}
adapter.changeDataSet(modifiedList);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
//get default ELECTRONICS category 1 data to populate the list
ArrayList<Reward> defaultCategorizedList=new ArrayList<Reward>();
//test case: category OK
for(int i=0;i<rewardList.size();i++)
{
if(rewardList.get(i).getCategoryID()==1)
{
defaultCategorizedList.add(rewardList.get(i));
}
}
}
});
Declaration of the Spinner Item inside the main xml:
<Spinner
android:id="#+id/categorySpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/customerRewardPointsTextView"
android:background="#drawable/btn_dropdown"
android:spinnerMode="dropdown" />
layout for the dropdown items, category_spinner_row.xml:
<?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:background="#drawable/category_spinner_background" >
<TextView
android:id="#+id/spinnerText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:ellipsize="marquee"
android:gravity="center"
android:singleLine="true" />
</RelativeLayout>
How can I fix this issue ?

try this one:
convertView=inflater.inflate(android.R.layout.simple_list_item_1, parent,false);

The problem starts because of "android:background="#drawable/btn_dropdown"" this portion of code. When you remove this you will see the spinner is working as it is supposed to, that means btn_dropdown drawable is conflicting with your spinner's width and eventually it's popup window that's why you are seeing this weird behaviour. I would suggest you to adjust your btn_dropdown drawable so that it does not conflict with spinner's default behaviour. Take a look at these post:
how-to-design-spinner-in-android
change-spinner-background
I haven't tried those but i think you will find what you need.

Related

Aligning Selected Spinner Item

I'm trying to make a slight adjustment to the positioning of the selected item in the spinner. Not the dropdown list items, as I already have a custom view in my adapter for that, but the selected item specifically.
As you can see in the screenshot, "Any" is the currently selected item. But it is aligned oddly within the container because it has to accommodate the longest string in the dropdown, which is "Dark Purple Burnt Sienna" (or whatever). I want to align the selected text to the right so that "Any" is next to the dropdown indicator instead of way out in the middle.
I've attempted to make adjustments to my custom spinner-item view, but it doesn't have any affect on the selected item.
I've also attempted to set gravity and text alignment on the Spinner itself, but it has no effect.
Here's the image and the xml:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/default_black"
android:layout_centerVertical="true"
android:text="Color" />
<Spinner
android:id="#+id/spn_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
</RelativeLayout>
Edit: Here's my adapter:
public class ColorsAdapter<T> implements SpinnerAdapter {
ArrayList<String> mColors;
ArrayList<Integer> mValues;
Context mContext;
public ColorsAdapter(ArrayList<String> colors, ArrayList<Integer> values,
Context context) {
mContext = context;
mColors = colors;
mValues = values;
}
#Override
public int getCount() {
return mColors.size();
}
#Override
public Object getItem(int position) {
return mColors.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return R.layout.list_item_color;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(mContext);
v.setText(mColors.get(position));
return v;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE );
View row = inflater.inflate(getItemViewType(position), parent, false);
TextView tvName = (TextView)row.findViewById(R.id.tv_name);
tvName.setText(mColors.get(position));
row.setTag(mValues.get(position));
return row;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return false;
}
}
And here's the XML for the list item:
<TextView
android:id="#+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:gravity="right"/>
You can adjust the settings for selected item in getView(int position, View convertView, ViewGroup parent) method. If you just want to set the gravity and text alignment, you should set it to the TextView in the method like
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(mContext);
v.setText(mColors.get(position));
v.setGravity(Gravity.END); // OR v.setGravity(Gravity.RIGHT);
return v;
}
Or you can simply inflate custom layout if you want to make further customization:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View row = null;
if (inflater != null) {
row = inflater.inflate(R.layout.list_item_view_color, parent, false);
TextView textView = row.findViewById(R.id.textview);
textView .setText(mColors.get(position));
}
return row;
}
Where list_item_view_color.xml is your layout file for the selected value.
(NOTE: If you want to use options like autoSizeTextType, you can use them with app prefix for AppCompatTextView in xml files)
Simple solution would be to build another Custom view for the spinner TextView layout, and specify the gravity for your TextView in that. Something like :
<!--spinner_layout.xml (in layout/)-->
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
/>
Use that in initalising the ArrayAdapter of your spinner :
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this, android.R.layout.spinner_layout,
spinnerArray);
UI output :
You can creating the TextView for the getView method programmatically so no property for alignment is being set, easy thing to do is inflate it in the same way you are doing it on the getDropdownView, or simply set the proper gravity in the view you are instantiated.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(mContext);
v.setText(mColors.get(position));
v.setGravity(Gravity.RIGHT);
return v;
}
You can try this
android:autoSizeTextType="uniform"
Padding, Margins and Alignments get confusing when it comes to Spinners. I ran into a similar issue as well. But for me I wasn't using a custom view and adapter, so I managed to use styles to get around this issue.
For you since you are already using custom view and adapter, you can make the background null for the spinner so that the dropdown arrow will not be visible.
android:background="#null"
Then in the TextView, you can assign drawableRight to be the dropdown arrow.
android:drawableRight="#drawable/ic_spinner_drop_arrow_white_24dp"
The icon can be a dropdown vector drawable. Also to specify particular margin between the arrow and text, you should be able to use drawablePadding
Hope this helps.
I can give you a method that may work.
In XML
1) add a new text view called the_current_color text view
2) allign this text view above the spinner and to the start of the arrow icon
or wherever you want it to be.
In your code
1) when you listen to (on item selected ) from the spinner simply get the current text and set it in the (the_current_color) text view.
2) and try to hide the texts in the spinner by changing color to transparent.
Hope it works
Edit
I might also suggest something maybe it changes things
lets say that we have a spinner that uses this string resource file to populate its adapter
<string-array name="my_adapter">
<item>Blue </item>
<item>Red</item>
</string-array>
until now we have a spinner that shows (red item) and (blue item) at the far left from the arrow icon of the spinner.
create another string resources now like that
<string-array name="my_adapter_two">
<item> Blue </item>
<item> Red</item>
</string-array>
as you can see now the added space will give an illusion that the strings are beside the arrow icon
you can add space that fit your need and you can maybe switch the files after you click a certain item and then switch them back.
You can try the following Custom view.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/textView1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="right"
android:padding="15dp"
android:textAlignment="gravity"
android:textColor="#color/black"
android:textSize="10dp" />

Item Click event on list view [duplicate]

Activity class code:
conversationList = (ListView)findViewById(android.R.id.list);
ConversationArrayAdapter conversationArrayAdapter=new ConversationArrayAdapter(this, R.layout.conversation_list_item_format_left, conversationDetails);
conversationList.setAdapter(conversationArrayAdapter);
conversationList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Log.d("test","clicked");
}
});
The getView function in the Adapter class:
if (v == null) {
LayoutInflater vi = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(leftSideMessageNumber.equals(m.getTo())) {
v = vi.inflate(R.layout.conversation_list_item_format_left, null);
} else {
v = vi.inflate(R.layout.conversation_list_item_format_right, null);
}
}
Is there a problem with using two xmls while inflating?
I just found a solution from here, but by deep clicking.
If any row item of list contains focusable or clickable view then OnItemClickListener won't work.
The row item must have a param like
android:descendantFocusability = "blocksDescendants".
Here you can see an example of how your list item should look like.
Your list item xml should be...
row_item.xml (your_xml_file.xml)
<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>
The problem is that your layouts contain either focusable or clickable items.
If a view contains either focusable or clickable item the OnItemCLickListener won't be called.
Click here for more information.
Please post one of your layout xmls if that isn't the case.
For my lists, my rows have other things that can be clicked, like buttons, so doing a blanket blocksDescendants doesn't work. Instead I add a line in the button's xml:
android:focusable="false"
That keeps the buttons from blocking the clicks on the rows, but still lets the buttons take the clicks, too.
you need to do 2 steps in your listview_item.xml
set the root layout with: android:descendantFocusability="blocksDescendants"
set any focusable or clickable view in this item with:
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
Here is an example: listview_item.xml
<?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:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:gravity="center_vertical"
android:orientation="vertical"
android:descendantFocusability="blocksDescendants">
<RadioButton
android:id="#+id/script_name_radio_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="#000"
android:padding="5dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
/>
</LinearLayout>
use the below code inside button tag in custom row layout of listview
android:focusable="false"
android:clickable="false"
I had the same problem and I just saw I had accidentally set:
#Override
public boolean isEnabled(int position)
{
return false;
}
on my CustomListViewAdapter class.
By changing this to:
return true;
I've managed to fix the problem.
Just in case if someone has done the same mistake...
Use android:descendantFocusability
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dip"
android:background="#color/light_green"
android:descendantFocusability="blocksDescendants" >
Add above in root layout
I solved it with the help of this answer
1.Add the following in Linear Layout of list_items.xml
android:descendantFocusability="blocksDescendants"
2.Child Views of LinearLayout in list_items.xml
android:focusable="false"
if you have textviews, buttons or stg clickable or selectable in your row view only
android:descendantFocusability="blocksDescendants"
is not enough. You have to set
android:textIsSelectable="false"
to your textviews and
android:focusable="false"
to your buttons and other focusable items.
Even I was having the same problem, I am having checkbox, did the following to masker itemClickListener work,
Added the following properties to the checkbox,
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
and ItemClickListner started working.
For detailed example you can go through the link,
http://knowledge-cess.com/android-itemclicklistner-with-checkbox-or-radiobutton/
Hope it helps Cheers!!
I had the same problem and tried all of the mentioned solutions to no avail. through testing i found that making the text selectable was preventing the listener to be called. So by switching it to false, or removing it my listener was called again.
android:textIsSelectable="false"
hope this helps someone who was stuck like me.
Add this in main Layout
android:descendantFocusability="blocksDescendants"
Write this code into every button,Textview,ImageView etc which have
onClick
android:focusable="false"
android:clickable="false"
Hope it will work.
Two awesome solutions were this, if your extending ListFragment from a fragment, know that mListView.setOnItemClickListener wont be called before your activity is created, this ensured it is set when activity has been created
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) {
// Do the onItemClick action
Log.d("ROWSELECT", "" + rowId);
}
});
}
While looking at the source code for ListFragment, I came across this
public class ListFragment extends Fragment {
...........................................
................................................
final private AdapterView.OnItemClickListener mOnClickListener
= new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
onListItemClick((ListView)parent, v, position, id);
}
};
................................................................
................................................................
public void onListItemClick(ListView l, View v, int position, long id) {
}
}
An onItemClickListener object is attached and it calls onListItemClick()
As such the other similar solution, which works in the exact same way is to override onListItemClick()
#Override
public void onListItemClick(ListView l, View v, int position, long rowId) {
super.onListItemClick(l, v, position, id);
// Do the onItemClick action
Log.d("ROWSELECT", "" + rowId);
}
in my case none of xml layout properties was not helpful.
I just add a single line of code like this:
convertView.setClickable(false);
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null || convertView.getTag() == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.my_layout_id, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
...
convertView.setClickable(false);
return convertView;
}
so basically it do the same thing as setting up properties in xml layout but it was only thing which works in my case.
It is not perfect timing but maybe it will helps somebody
Happy coding
I've tried all the above and NOTHING worked.
I solved the problem as follows:
First I define a custom Button called ListButton
public class ListButton extends android.widget.Button
{
private ButtonClickedListener clickListener;
public ListButton(Context context)
{
this(context, null);
}
public ListButton(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public ListButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public void setClickListener(ButtonClickedListener listener) {
this.clickListener = listener;
}
#Override
public boolean isInTouchMode() {
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return false;
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
eventClicked();
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_MOVE:
break;
default :
}
return true;
}
private void eventClicked() {
if (this.clickListener!=null) {
this.clickListener.ButtonClicked();
}
}
}
The XML looks like:
<dk.example.views.ListButton
android:id="#+id/cancel_button"
android:layout_width="125dp"
android:layout_height="80dp"
android:text="Cancel"
android:textSize="20sp"
android:layout_margin="10dp"
android:padding="2dp"
android:background="#000000"
android:textColor="#ffffff"
android:textStyle="bold"
/>
Then I define my own ButtonClicked Listener interface:
public interface ButtonClickedListener {
public void ButtonClicked();
}
Then I use my own listener just as if it was the normal OnClickListener:
final ListButton cancelButton = (ListButton) viewLayout.findViewById(R.id.cancel_button);
cancelButton.setClickListener(new ButtonClickedListener() {
#Override
public void ButtonClicked() {
//Do your own stuff here...
}
});
I had the same issue, I was using a style for my texts in the row layout that had the "focusable" attribute. It worked after I removed it.
In my case, I had to remove the next line from the Layout
android:clickable="true"
Android:autoText attribute also makes TextView auto focusable.
If you want to use both the simple click and long click on list view items better way to implement that would be to use context menu for long click. Avoid using setItemLongClickListener especially if you have multiple row layouts for your listview.
Faced same problem, tried for hours. If you have tried all of the above than try changing layout_width of Listview and list item to match_parent from wrap_content.
All of the above failed for me. However, I was able to resolve the problem (after many hours of banging my head - Google, if you're listening, please consider fixing what I encountered below in the form of compiler errors, if possible)
You really have to be careful of what android attributes you add to your xml layout here (in this original question, it is called list_items.xml). For me, what was causing the problem was that I had switched from an EditText view to a TextView and had leftover attribute cruft from the change (in my case, inputType). The compiler didn't catch it and the clickability just failed when I went to run the app. Double check all of the attributes you have in your layout xml nodes.
private AdapterView.OnItemClickListener onItemClickListener;
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
.......
final View view = convertView;
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(null, view, position, -1);
}
}
});
return convertView;
}
public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
Then in your activity, use adapter.setOnItemClickListener() before attaching it to the listview.
Copied from github its worked for me
The thing that worked for me was to add the below code to every subview inside the layout of my row.xml file:
android:focusable="false"
android:focusableInTouchMode="false"
So in my case:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/testingId"
android:text="Name"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/dummyId"
android:text="icon"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/assignmentColor"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/testID"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:text="TextView"
//other stuff
/>
</android.support.constraint.ConstraintLayout>
And this is my setOnItemClickListener call in my Fragment subclass:
CustomListView = (PullToRefreshListCustomView) layout.findViewById(getListResourceID());
CustomListView.setAdapter(customAdapter);
CustomListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("Testing", "onitem click working");
// other code
}
});
I got the answer from here!
Had the same problem with onClick. The solution was to remove from the xml the following
android:tooltipText=""
I solved the problem by removing the clickable views from the list.

Custom adapter failing without error

issue is this:
There are 49 items in the arraylist, and the adapter is stopping at item 3 without any error notification. The app does not crash, and no textviews are displayed. Here is the adapter:
public class ExhibitorObjectAdapter extends ArrayAdapter<ExhibitorObject> {
public ArrayList<ExhibitorObject> exhibitors;
public Activity act;
public TextView tvExhibitorName;
public ImageView ivExhibitorLogo;
public ExhibitorObjectAdapter(Activity a, int layoutResourceId, ArrayList<ExhibitorObject> ex) {
super(a, layoutResourceId,ex);
this.exhibitors = ex;
this.act = a;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return exhibitors.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.single_exhibitor, null);
}
ExhibitorObject ex = exhibitors.get(position);
if (ex != null) {
//System.out.println(ex.companyName);
tvExhibitorName = (TextView) v.findViewById(R.id.textViewListExhibitorName);
tvExhibitorName.setText( ex.companyName );
}
return v;
}
}
EDIT: here is the xml containing the 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="horizontal" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:background="#134882"
android:paddingBottom="15sp"
android:paddingTop="5sp"
android:paddingLeft="5sp"
android:textColor="#FFFFFF"
android:text="Exhibitors" />
<ListView android:id="#+id/listViewExhibitors"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
I have several other adapters that are exactly like this one and they work just fine. I have wasted an entire day on this (it's probably a silly problem), any help would be appreciated. Thanks.
It is bad to save tvExhibitorName in the scope of your adapter. Make it local within getView(), or you subject yourself to all kinds of leaks. That well may be the source of your problem.
Also, it is very strange that you don't inflate your new view under the parent. May be using inflate(layout, parent , false) will help.

Adding image to listview after listview item click

I am developing an app which has a listView having 1 textView which displays the content and one imageView. What i want is, when i click the listView i want to set the imageView with the tick mark image which i have. Its working fine. Once i click the listView, the tick mark image is loaded on that listview item on which i clicked.
The problem arises when i scroll. When i scroll, i could see some other listview item down below has a tick mark loaded. not sure how the image was set on that position.
I have read somewhere that when the listView is scrolled, the view is refreshed. Is that causing the problem?
Can anyone help how can iresolve this? I want the image to be shown(loaded) on the listView item on which i clicked and now other listView item.
Below is the xml stating listView items
method_item.xml
<?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:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white"
android:text="This is a check box button which reacts upon the check that user clicks. I am testing it with the big string and checking how it looks" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_centerHorizontal="true" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/imageView1"
android:layout_alignParentRight="true"
android:layout_marginRight="34dp" />
</RelativeLayout>
Below is the part of class snippet:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.method_list_main);
final ListView list = (ListView)findViewById(R.id.listView1);
adapter=new MethodLazyAdapter(this,ARRAY.preparationSteps,ARRAY.timeToPrepare,ARRAY.arrowValue,noOfSteps,list);
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
RelativeLayout ll = (RelativeLayout) view;
ImageView image = (ImageView)ll.findViewById(R.id.imageView2);
if(tick[position]){
tick[position] = false;
image.setImageResource(0);
}
else{
tick[position] = true;
image.setImageResource(R.drawable.select_right);
}
System.out.println("Position is: "+position);
}
});
}
Initially all tick[i] value is set to false.
Below is the getView function of adapter class
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.method_item, null);
TextView text = (TextView)vi.findViewById(R.id.textView1);
text.setText(preparationSteps\[position\]);
return vi;
}
Try this to get what you want
in public area add this variable
public SparseBooleanArray checked = new SparseBooleanArray();
then in onItemClick
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
boolean stat = checked.get(position, false);
checked.put(position, !stat);
adapter.setChecked();
System.out.println("Position is: "+position);
}
});
and in Adapter Class
If adapter not sub class in activiy add variable in public area
private SparseBooleanArray checked = new SparseBooleanArray();
and add this method to class
public void setChecked(SparseBooleanArray ch){
checked = ch;
notifyDataSetChanged();
}
Or if it sub class use our cheked variable we defined it up
then in getView method
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.method_item, null);
TextView text = (TextView)vi.findViewById(R.id.textView1);
text.setText(preparationSteps\[position\]);
ImageView image = (ImageView)vi.findViewById(R.id.imageView2);
if(checked.get(position, false)){
image.setImageResource(0);
}
else{
image.setImageResource(R.drawable.select_right);
}
return vi;
}
Please let me know if this help you.
Check out this post:
android - populating ListView with data from JSONArray
the reason for that is bacouse your are using your converted view wrong.
follow the example code on the post i paste.
if you will inflate your row view every time this problem will disappear. but this implementation is not recommended.

Removing an Item with a Button in ListView with Custom ArrayAdapter

I have custom list_row :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content" android:baselineAligned="false">
<Button android:layout_width="30dip" android:layout_marginTop="7dip" android:gravity="right"
android:id="#+id/delete" android:layout_height="30dip" android:background="#drawable/delete"
android:layout_gravity="top"></Button>
<TextView android:textSize="20dip"
android:text="TextView" android:id="#+id/tavsiye" android:layout_marginTop="10dip"
android:layout_gravity="top" android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
</LinearLayout>
I have a ListView like that:
<ListView
android:id="#+id/tavsiyeler"
android:layout_height="300dip"
android:layout_width="170dip"
android:fastScrollEnabled="true"
android:scrollbars="vertical"/>
and a custom adapter which extends ArrayAdapter :
public class HekimTavsiyeleriAdapter extends ArrayAdapter<String> {
private Context context;
private int resource;
private ArrayList<String> tavsiyeler;
public HekimTavsiyeleriAdapter(Context context, int resource,
ArrayList<String> objects) {
super(context, resource, objects);
this.context=context;
this.resource=resource;
this.tavsiyeler=objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(this.resource, null);
}
if (this.tavsiyeler.size()!=0) {
TextView tavsiye = (TextView) v.findViewById(R.id.tavsiye);
Button but= (Button) v.findViewById(R.id.delete);
if (tavsiye != null) {
String st=this.tavsiyeler.get(position);
tavsiye.setText(st);
}
if( but!=null){
but.setId(position);
but.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View v) {
int id=v.getId();
tavsiyeler.remove(id);
notifyDataSetChanged();
}
});
}
}
return v;
}
I am creating adapter and fill the list like that :
eklenecekTavsiyeler=new ArrayList<String>();
adapter= new HekimTavsiyeleriAdapter(context,
R.layout.hekim_tavsiyeleri_row, eklenecekTavsiyeler);
ListView tavsiyelerListesi = (ListView)findViewById(R.id.tavsiyeler);
tavsiyelerListesi.setAdapter(adapter);
And adding new items like that:
this.adapter.add(<some-string>);
this.adapter.notifyDataSetChanged();
and my list view is seen like that:
http://imageshack.us/photo/my-images/97/listir.jpg/
Here is my question:
I am adding new items to the list. I have fixed height for the list. When I fill the list until all height is occupied, then I add one new item to the list which requires scrolling becasue overflow in list height. The last item I added gets wrong id and when I pressed the cross button, it removes wrong item. However, when the list is not overflowed, everything works fine. After overflow, the ids of buttons are set wrongly (seems randomly). By the way, for setting the button's id, I am using getView's position argument.
Thanks in advance.
I am afraid that you have flaw in the code.
You have to stop calling but.setId(). With this you are overriding internal id of the view which is the value of R.id.delete. Probably you meant to use but.setTag() / but.getTag()?

Categories

Resources