How to access listview items generated by arrayadapter - android

I have tied my application to Firebase database and after being able to display them I also want to be able to select them and access their textview values. However .getValue() does not work for views. I know that my code is very messy and my selector is only working one way, but can you help me to find out what is going on. I will add a screenshot to make things more clear. At the moment when clicking on one of the items int num = Integer.parseInt(text) gives an error and the app will crash because the value I get from view is "Android.widget...", not what I want to get.
Screenshot pic:
Orders.java
public class Orders extends ActionBarActivity {
public final static String TOTAL_SUM = "com.nordscript.checkmate.SUM";
// Declare the UI components
private ListView foodList;
// Declare an ArrayAdapter that we use to join the data set and the ListView
// is the way of type safe, means you only can pass Strings to this array
//Anyway ArrayAdapter supports only TextView
private ArrayAdapter arrayAdapter;
private Firebase ref;
private Orders activ;
private ArrayList<String> dishes;
public int total;
#Override
protected void onCreate(Bundle savedInstanceState) {
activ = this;
dishes = new ArrayList<String>(20);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_orders);
// Initialize the UI components
foodList = (ListView)findViewById(R.id.listView1);
// Create a reference to a Firebase location
ref = new Firebase("https://xxxxxxxxxx.firebaseio-demo.com/Restaurants/Restaurant 2/Tables/Table 2/Orders");
// Read data and react to changes
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
Map s = snapshot.getValue(Map.class);
dishes.add(snapshot.getName() + " " + ((Map)snapshot.getValue(Map.class)).get("Price"));
Log.i("Test", dishes.toString());
arrayAdapter = new ArrayAdapter(activ, android.R.layout.simple_list_item_1, dishes.toArray());
// By using setAdapter method, you plugged the ListView with adapter
foodList.setAdapter(arrayAdapter);
}
#Override public void onChildChanged(DataSnapshot snapshot, String previousChildName) { }
#Override public void onChildRemoved(DataSnapshot snapshot) {
Map s = snapshot.getValue(Map.class);
dishes.remove(snapshot.getName() + " " + ((Map)snapshot.getValue(Map.class)).get("Price"));
Log.i("Test", dishes.toString());
arrayAdapter = new ArrayAdapter(activ, android.R.layout.simple_list_item_1, dishes.toArray());
// By using setAdapter method, you plugged the ListView with adapter
foodList.setAdapter(arrayAdapter);
}
#Override public void onChildMoved(DataSnapshot snapshot, String previousChildName) { }
#Override
public void onCancelled(FirebaseError arg0) { }
});
foodList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setBackgroundColor(Color.GREEN);
String text = view.toString();
text.replaceAll("[^\\d.]", "");
int num = Integer.parseInt(text);
total += num;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.orders, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void toPayment(View view) {
Intent pay = new Intent(this, PaymentMethod.class);
pay.putExtra(TOTAL_SUM, total);
startActivity(pay);
}
}

What i understand from your question : Suppose when you click on 3rd item i.e "pudding 8", you want this value "pudding 8"(textview value). right??
If that so than you just have to get values from your ArrayList which you pass to the adapter on first place with the help of position attribute inside your setOnItemClickListener like this :
foodList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setBackgroundColor(Color.GREEN);
String text = dishes.get(position);
// do what you want to do with this value.
}
});

Change your onClickListener() like that:
foodList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setBackgroundColor(Color.GREEN);
String text = (String)parent.getItemAtPosition(position);
text.replaceAll("[^\\d.]", "");
int num = Integer.parseInt(text);
total += num;
}
});
Or you can use SimpleAdapter for displaying string and integer values separately using two textviews in a separate xml layout. Using that you can get values on onclick() in a better way.

You need to gettext of that particular view, view.getText().toString();
foodList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setBackgroundColor(Color.GREEN);
String text = view.getText().toString();
text.replaceAll("[^\\d.]", "");
int num = Integer.parseInt(text);
total += num;
}
});

It may help you, but it is bad way:
foodList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = (String) arrayAdapter.getItem(position);
String[] split = item.split(" ");
int num = Integer.parseInt(split[1]);
total += num;
}
});
But it is very urge...
As for me, you need to extends Adapter, to collect into it your custom items, and after clicking gets it and takes integer value you need.

I know this might become a little too late but, hope this
helps someone who was looking for similar solution to Custom ArrayAdapter with multiple values.
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ListItems item = (ListItems) parent.getItemAtPosition(position);
System.out.println("Item: "+item.getName());
}
});

Related

Can AutoCompleteTextView return an ID?

AutoCompleteTextView lets users choose a string from a list of valid values. Like, I imagine, every developer who wants to use this yoke, I am much more interested in the id of the user's selection than its string label. Is there any way to retrieve the id property of a chosen object, or its index in the source array?
The following C# code let's users pick from a list of SomeObject. I'm working in Xamarin, but don't let this put you off. Fix my problem in java and I'll happily make it work in C#
public class AutoCompleteField : PhysicalField
{
protected AutoCompleteTextView actv;
public AutoCompleteField(IList<SomeObject> choices, LogicalField logical, string id)
: base(logical, id)
{
_choices = choices;
}
protected ArrayAdapter<SomeObject> _adapter;
public override void addToView(LayoutInflater inflater)
{
var ctx = App_NotMobility.CurrentActivity;
actv = new AutoCompleteTextView(ctx);
actv.Id = _form.generateId();
// test choices
var _choices = new List<SomeObject>();
_choices.Add(new SomeObject(234, "Oranges"));
_choices.Add(new SomeObject(456, "Apples"));
_choices.Add(new SomeObject(789, "Bananas"));
_adapter = new ArrayAdapter<SomeObject>(ctx, Android.Resource.Layout.SimpleDropDownItem1Line, _choices);
actv.Adapter = _adapter;
actv.ItemClick += delegate(object sender, AdapterView.ItemClickEventArgs e)
{
// HOW DO I ACCESS THE ID OR THE INDEX OF USER'S SELECTION ?????????????????
};
_form.AddView(actv);
}
}
public class SomeObject
{
public int Id { get; set; }
public string Label { get; set; }
public SomeObject(int id, string label)
{
Id = id;
Label = label;
}
public override string ToString()
{
return Label;
}
}
Once you have initialized the adapter and overdid the item click, all you need to do is get the particular object from your adapter at that particular position of item which you clicked.
In java it would be somewhat similar to,
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SomeObject someObject = (SomeObject) adapter.getItem(position);
int id = someObject.getId();
}
Thats all you would need. I am not sure about your code in xamarin, how you would get the position because i don't see any method where the position is input variable, may be you could add the tag to your view and can get the tag on your click method.
var position = ((View)sender).Tag;
But i would recommend , if you can create a class extend the base adapter, that way you will the method GetView to override and can easily do what you are looking for. You constructor could be like this for start,
List<SomeObjects> items;
Activity context;
public CustomAdapter(Activity context, List<SomeObjects> items)
: base()
{
this.context = context;
this.items = items;
}
Ankush's answer worked. I'm posting the C# code here because there are some subtleties with casting and generics...
public class myActv : AutoCompleteTextView, AdapterView.IOnItemClickListener
{
PhysicalField _physical;
public myActv(Activity ctx, PhysicalField physical) : base(ctx)
{
OnItemClickListener = this;
_physical = physical;
}
public void OnItemClick(AdapterView parent, View view, int position, long id)
{
// This is the punchline...
SomeObject whatIwant = ((ArrayAdapter<SomeObject>)this.Adapter).GetItem(position);
}
}
Here searchText is an Autocompletetextview..
searchText.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
{
int position = position; //Adapter selection position
}
});

Save spinner state even moved to another activity with Android

I want to save my spinner state even when I move to a different activity and come back to the page with the spinner, the state should be the same. I have no idea how to do it, I saw some examples on other threads on stack overflow but I don't understand them.
Here's my code:
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
index = arg0.getSelectedItemPosition();
// storing string resources into Array
lang_list = getResources().getStringArray(R.array.language_list);
Toast.makeText(getBaseContext(), "You have selected : " + lang_list[index],
Toast.LENGTH_SHORT).show();
choice = spinner.getSelectedItem().toString();
// edit_cate.setText(choice);
final ImageView country_flag = (ImageView)findViewById(R.id.country);
String s=((TextView)arg1).getText().toString();
if(s.equals("English"))
country_flag.setImageDrawable(getResources().getDrawable(R.drawable.eng_spinner));
if(s.equals("German"))
country_flag.setImageDrawable(getResources().getDrawable(R.drawable.german_spinner));
if(s.equals("French"))
country_flag.setImageDrawable(getResources().getDrawable(R.drawable.french_spinner));
if(s.equals("Spanish"))
country_flag.setImageDrawable(getResources().getDrawable(R.drawable.spanish_spinner));
}
Thanks for the help.
You need to save state of your spinner so this would be helpful to you.
1.) Apply this after creating spinner object
spinner.setSelection(getPersistedItem());
2.) Create these methods according to you to save the state of your spinner selected item
private int getPersistedItem() {
String keyName = makePersistedItemKeyName();
return PreferenceManager.getDefaultSharedPreferences(this).getInt(keyName, 0);
}
protected void setPersistedItem(int position) {
String keyName = makePersistedItemKeyName();
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(keyName, position).commit();
}
private String makePersistedItemKeyName() {
return currentUserName + "_your_key";
}
3.) Set its state as the spinner selection changed:
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View view, int position, long itemId) {
setPersistedItem(position);
} #Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
} });

Getting ID value when clicking on listview

I'm having some trouble getting the correct id value when clicking on the listview.
I made a custom adapter since I'm drawing from SQLite data, I get the right text back but when I click on a row, I get a 0 index id back, which is not what I want.
I'm also using Sugar ORM, so I'm not sure if that requires some special work from me to get the id field.
I'm not sure what I should show you in terms of code, so whatever you think will help you, let me know and I'll post it.
Thanks
BoardArrayAdapter adapter = new BoardArrayAdapter(this, boards);
setListAdapter(adapter);
ListView lv = getListView();
registerForContextMenu(lv);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), "Board ID " + id, Toast.LENGTH_SHORT).show();
}
});
You need to override the getItemId() method in your adapter.
According to the SugarORM docs you can call getid()to return the db id.
ArrayList<Object> data;
#Override
public long getItemId(int position) {
return data.get(position).getid();
}
This is how I am using on my project (with SQLite and CustomListView).
getData method
public void getData(View view, long id)
{
//storing the ID into a public static variable and converting to int
CLIENTE_ID = (int)id;
//When the user touches on the field in the listview, I get the touched field's name and email
TextView textViewnome = (TextView) view.findViewById(R.id.tv_cliente_nome);
TextView textViewemail = (TextView) view.findViewById(R.id.tv_cliente_email);
//Stores both name and email of the touched field
String nome = textViewnome.getText().toString();
String email = textViewemail.getText().toString();
//store into static variable
CLIENTE_NOME = nome;
CLIENTE_EMAIL = email;
}
within onCreate:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
getData(view, id);
Log.d("myClass", "ID: " + view.getId());
}
});
I hope it helps! :)

Odd Android Spinner behavior

This is the code to populate my spinner.
The code:
String[] rcs = new String[review_cycles.length];
for (int i = 0; i < review_cycles.length; i++)
rcs[i] = review_cycles[i].ReviewCycleName;
ArrayAdapter<String> rc_spinnerAdapter = new ArrayAdapter<String>(
ActivityManagementReview.this,
R.layout.simple_spinner_item,
rcs);
sp_review_cycle.setAdapter(rc_spinnerAdapter);
sp_review_cycle.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
DtoMrReviewCycleVersion selected_review_cycle_version = review_cycles[position];
if (selected_review_cycle_version != latest_review_cycle_version) {
latest_review_cycle_version = selected_review_cycle_version;
int mr_version_id = latest_review_cycle_version.MrdVersionId;
_URL_version = _url_base + "MrVersion/" + Integer.toString(mr_version_id);
new GetMrVersionInfoAsyncTask().execute();
}
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
return;
}
});
When I select a value from the spinner, the code is executed twice. Once with the selection I made and then right afterward, the first item in the list is executed again bringing me back to where I started.
How can I prevent this from happening?
Thanks.
When I select a value from the spinner, the code is executed twice.
As I reminded you in the comments, Spinners call onItemSelected() when they load the default value. This feature is useful when you know about it, but since it is not what the average developer expects it is problematic as well.
The Spinner will also call onItemSelected() when the user re-selects the current value... When I want to avoid both of these false alarms I use something like this:
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
int previous = -1;
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(previous != position && previous < -1) {
Log.v("Example", "Selected: " + position);
// Do something
}
previous = position;
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});

How to refer to the original position of a list item when text filter is enabled?

When I use edit text to filter the items, the list positions get all messed up and the items no longer call the proper intent. Any help is appreciated
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String mName = filteredValues.get(position).getName().toString();
String mWeb = filteredValues.get(position).getWebsite().toString();
Intent openDetails = new Intent(Test.this, ResourceDetails.class);
Bundle b = new Bundle();
b.putString("name", mName);
b.putString("web", mWeb);
openDetails.putExtras(b);
startActivity(openDetails);
}
});
private TextWatcher filterTextWatcher = new TextWatcher(){
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
adapter.notifyDataSetChanged();
}
public void afterTextChanged(Editable s) {
}
};
flashsearchList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Integer temp=flashSearchNameMap.get(adapter.getItem(position));
navigateSearch(temp);
}
});
(adapter.getItem(position) will return you the exact list name and in flashSearchNameMap i have stored names and position at beginning from oncreate before applying filtering.So you can get exact position by this
if you use ViewHolder in Adapter just define a realPosition variable in holder class and set it in YourAdapter.getView
and in listClick Listener
ContactAdapter.ViewHolder holder = (YourAdapter.ViewHolder) view.getTag();
holder.realPosition
The item position is not reliable when using lists. I recommend you to use view.setTag(Object) to assign an identifier to each item when attaching the content. This could be a number, string or anything. Then you can just access it with view.getTag() inside the click listener.
Assuming you are using a custom bean object to store your name & website values and an ArrayAdapter to show them in your ListView, like so
public class NamedLink {
final String mName;
final String mWebsite;
public NamedLink(String name, String website) {
mName = name;
mWebsite = website;
}
#Override
public String toString() {
return mName;
}
}
With an adapter, defined something like this:
mAdapter = new ArrayAdapter<NamedLink>(this, android.R.layout.simple_list_item_2, mLinks) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(WhateverYourActivityIsNamed.this).inflate(android.R.layout.simple_list_item_2, null);
}
NamedLink link = getItem(position);
// This probably deserves a ViewHolder
((TextView) convertView.findViewById(android.R.id.text1)).setText(link.getName());
((TextView) convertView.findViewById(android.R.id.text2)).setText(link.getWebsite());
return convertView;
}
};
When you filter the array adapter it will match against the beans #toString(), which in this case returns the name. When filtered, the array adapter maintains a properly indexed copy of your list of beans internally - i.e. you can use the position you get in the click listener like this:
getListView().setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// getItemAtPosition() will return a NamedLink from the filtered
// list maintained inside the ArrayAdapter
NamedLink link = (NamedLink) parent.getItemAtPosition(position);
Intent openDetails = new Intent(Test.this, ResourceDetails.class);
Bundle b = new Bundle();
b.putString("name", link.getName());
b.putString("web", link.getWebsite());
openDetails.putExtras(b);
startActivity(openDetails);
}
});

Categories

Resources