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
}
});
Related
Im fairly new to Android development. I have a custom ListView that is populated with data from a DatabaseTable. The ListView-items consist of CATEGORY, DATE, TITLE and AMOUNT.
private class lvIncomeListener implements AdapterView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = ???;
displayItemClicked("List-item Clicked:",item);
}
}
Now, I want to add an OnItemClickListener to the ListView, so that when an item in the list is clicked, a DialogFragment will display the data from that particular row in the Database that is shown in the ListView, like
"Item Clicked: Category: food, Date: 17/10/25, Title: Restaurant, Amount: 20sek"
... how is the best way to go about to achieve this?
Since you have a custom adapter, I assume you have a custom class where you store your list data maybe like this:
public class YourListData {
private String catagory;
private String date;
public YourListData(){
}
public void setCatagory(String cat){ this.catagory = cat; }
public void setDate(String date){ this.date = date; }
public String getCatagory(){ return this.catagory; }
public String getDate() { return this.date; }
}
Now in your onItemClick method in your Activity get the list data like this:
mYourListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
YourListData data = (YourListData) parent.getItemAtPosition(position);
String cat = data.getCatagory();
String date = data.getDate();
//...
//Send data to your fragment
}
});
I'm a little lost here. I'm trying to add a custom object(with 3 integers, 1 double, and 1 date) to an arraylist when a button is clicked. I want the arraylist to be shown in another classes listview. So far this is what I have for the custom class:
ublic class Record {
private Integer squat, bench, dead;
private double total;
private Date dateTime;
public Record(int squat, int bench, int dead, double total, Date date) {
this.bench = bench;
this.dateTime = date;
this.dead = dead;
this.squat = squat;
this.total = total;
}
public Integer getSquat() {
return squat;
}
public void setSquat(Integer squat) {
this.squat = squat;
}
public Integer getBench() {
return bench;
}
public void setBench(Integer bench) {
this.bench = bench;
}
public Integer getDead() {
return dead;
}
public void setDead(Integer dead) {
this.dead = dead;
}
public Double getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public Date getDateTime() {
return dateTime;
}
public void setDateTime(Date dateTime) {
this.dateTime = dateTime;
}
}
EDIT: Classname: MyMaxes.class : In the class where the button is clicked, I have this(I'm not sure how to get the current date when button is clicked):
public ArrayList<Record> records = new ArrayList<>();
maxTotal = maxDead + maxBench + maxSquat;
int maxDead = Integer.parseInt(mEditTextDead.getText().toString());
int maxSquat = Integer.parseInt(mEditTextSquat.getText().toString());
int maxBench = Integer.parseInt(mEditTextBench.getText().toString());
records.add(new Record(maxSquat, maxBench, maxDead, maxTotal, ));
Edit: Class name = MyProgress.class : And in the class I want to set the listview to this arraylist(I'm not sure how to get the arraylist from the other class):
RecordAdapter adapter = new RecordAdapter(getApplicationContext(),R.layout.custom_record);
ListView listViewRec = (ListView) findViewById(R.id.listViewRecord);
}
This is my RecordAdapter class, but im not sure what to add there either:
public class RecordAdapter extends ArrayAdapter<Record> {
public RecordAdapter(Context context, int resource) {
super(context, resource);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position, convertView, parent);
}
}
Thanks for any help
I think the problem is that you have two different adapters:
RecordAdapter adapter = new RecordAdapter(getApplicationContext(),R.layout.custom_record);
ArrayAdapter<Record> arrayAdapter = new ArrayAdapter<Record>(this, R.layout.custom_record, records);
You should use one or the other, not both. It appears that arrayAdapter should work. So change all of your code to use it.
Alternatively, you can use your custom RecordAdapter. If you do this, then you should create the ArrayList inside this class. Then when the user clicks a button, you send the new Record object to the RecordAdapter instance. The easiest way to do this is to add a addRecord() method to RecordAdapter.
Get Current Date:
All you need to do is create a new Date object:
Date currentDate = new Date();
See the linked javadocs for details about how to use Date.
You do not need the custom RecordAdapter. Nor do you need the ArrayList. You can treat your ArrayAdapter as an ArrayList that feeds into your ListView. All you need to do is create an ArrayAdapter and populate it the same way you do with the ArrayList:
public ArrayAdapter<Record> records = new ArrayAdapter<>(getApplicationContext(), R.layout.custom_record);
maxTotal = maxDead + maxBench + maxSquat;
int maxDead = Integer.parseInt(mEditTextDead.getText().toString());
int maxSquat = Integer.parseInt(mEditTextSquat.getText().toString());
int maxBench = Integer.parseInt(mEditTextBench.getText().toString());
records.add(new Record(maxSquat, maxBench, maxDead, maxTotal ));
Then, whenever you want to add a record to you listview, use this:
records.add(new Record(maxSquat, maxBench, maxDead, maxTotal));
EDIT:
Forgot a very important part. You need to get your ListView and set the ArrayAdapter to populate it.
ListView listViewRec = (ListView) findViewById(R.id.listViewRecord);
listViewRec.setAdapter(records);
I have two classes that I'm working with. Contacts and CustomAdapter. In my Contacts Class I have an onActivityResult() method, which gets data from a different activity and places it in a Custom ListView using my CustomAdapter Class. The data gets added fine. Each row consists of a name, email, phone number AND a Button Widget. My question is, I would like to be able to press this Button and have that specific row be deleted. I've tried a number of different things but nothing seems to be working.
I placed the code below. If anyone has any suggestions on the best way to do this, I would greatly appreciate it. Thank you.
onActivityResult in Contacts Class:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_CODE){
if(resultCode == RESULT_OK){
String name = data.getStringExtra("name");
String phone = data.getStringExtra("phone");
final String email = data.getStringExtra("email");
//These are array lists declared earlier
phoneNums.add(phone);
names.add(name);
emails.add(email);
customAdapter = new CustomAdapter(Contacts.this,names,phoneNums,emails);
contactList.setAdapter(customAdapter);
contactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
names.remove(position);
phoneNums.remove(position);
phoneNums.remove(position);
//This method is still not being recognized
contactList.getAdapter().notifyDataSetChanged()
//This one is but the app is crashing when I click on any of the rows
contactList.getAdapter().notify()
}
});
}
}
}
Custom Adapter Entire Class:
public class CustomAdapter extends BaseAdapter implements View.OnClickListener {
private Context context;
private ArrayList<String>phoneNumbers;
private ArrayList<String>names;
private ArrayList<String>emails;
private static LayoutInflater inflater = null;
public CustomAdapter(Context c,ArrayList<String>n,ArrayList<String>nums,ArrayList<String>e){
context = c;
phoneNumbers = nums;
names = n;
emails = e;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return names.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return (long)position;
}
#Override
public View getView(final int position, final View convertView, ViewGroup parent) {
View view = convertView;
if (view == null){
view = inflater.inflate(R.layout.contacts_custom_row,null);
Button deleteBtn = (Button)view.findViewById(R.id.customRowDeleteButton);
TextView name = (TextView)view.findViewById(R.id.customRowContactName);
TextView phone = (TextView)view.findViewById(R.id.customRowContactNumber);
TextView email = (TextView)view.findViewById(R.id.customRowContactEmail);
name.setText(names.get(position));
phone.setText(phoneNumbers.get(position));
email.setText(emails.get(position));
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//SHOULD I PLACE CODE TO DELETE THE ROW IN HERE?
}
});
}
return view;
}
Basically what you need is one List<>to rule the size of you List (i believe yours is the names. For that, your getItem(int position) has to return names.size(). To delete a specific row, you just need to delete the index of names that you want, and call notifyDataSetChanged() in your adapter after that.
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());
}
});
I have a ListView with a custom Adapter that extends ArrayAdapter. It's a ArrayAdapter of Type Artist.
Artist is a very small class that has a name and an id. The Artist Class has toString() overridden to return just the name.
I have an EditText. The EditText has an TextChangeListener where i call .getFilter().filter(chars, callback) on my adapter.
In the Filter.Filterlistener().onComplete() callback i print the count and it looks really good. As i type the count decreases. So it seams everything works as advertised, but the List stays the same. I tried to call artistAdapter.notifyDataSetChanged() to force the list to redraw, but nothing happens. [see 2.)]
I am tinkering around for days now! I am desperate.. Hopefully someone can have a look on my code and tell me what i am doing wrong!
Thanks!
Here is what i have done:
1.) Defined a ListView and an EditText like this:
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_search_text"
android:layout_width="fill_parent"
android:layout_height="35dip"
android:layout_below="#id/header">
</EditText>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_search"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ListView>
2.) Setup my ListView in the Activities onCreate():
private ListView listView = null;
private ArtistAdapter artistAdapter = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_artists);
artistAdapter = new ArtistAdapter(this, R.layout.row, list); // 'list' is an ArrayList<Artist>
listView = (ListView) findViewById(R.id.list_search);
listView.setAdapter(artistAdapter);
listView.setFastScrollEnabled(true);
listView.setTextFilterEnabled(true);
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int position, long id) {
// do something
}
});
EditText txtSearch = (EditText) findViewById(R.id.list_search_text);
txtSearch.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable arg0) { }
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { }
public void onTextChanged(CharSequence chars, int start, int before, int count) {
artistAdapter.getFilter().filter(chars, new Filter.FilterListener() {
public void onFilterComplete(int count) {
Log.d(Config.LOG_TAG, "filter complete! count: " + count);
artistAdapter.notifyDataSetChanged();
}
});
}
});
}
3.) This is my ArtistAdapter in short. I added an remove() and add() method:
public class ArtistAdapter extends ArrayAdapter<Artist> implements SectionIndexer {
private List<Artist> items;
/* other stuff like overridden getView, getPositionForSection, getSectionForPosition and so on */
#Override
public void remove(Artist object) {
super.remove(object);
items.remove(object);
}
#Override
public void add(Artist object) {
super.add(object);
items.add(object);
}
}
4.) My artist has also the toString() overridden:
public class Artist implements Comparable<Artist> {
public String uid;
public String name;
public Artist(String id, String name) {
this.uid = id;
this.name = name;
}
public int compareTo(Artist another) {
return this.name.compareToIgnoreCase(another.name);
}
#Override
public String toString() {
return this.name;
}
}
I found the solution. I have rewritten the whole code from scratch and found the problem.
In my custom ArrayAdapter called ArtistAdapter (see 3. in question) if have a var to store the items:
private List items;
And in my overridden getView() when i want to get the current item i did:
items.getItem(position)
now i do a:
getItems(position) (so the item is retrieved from the storage of the base class and not my own) and this seems to do the trick!
This is my getView() as it is now (the version, that is working):
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout artistView;
Artist art = getItem(position);
if (convertView == null) {
artistView = new LinearLayout(getContext());
String inflater = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater vi;
vi = (LayoutInflater)getContext().getSystemService(inflater);
vi.inflate(resId, artistView, true);
} else {
artistView = (LinearLayout) convertView;
}
TextView nameView = (TextView)artistView.findViewById(R.id.txt_name);
TextView uidView = (TextView)artistView.findViewById(R.id.txt_uid);
nameView.setText(art.name);
uidView.setText(art.uid);
return artistView;
}
Pfu, this was a really annoying bug...
Try using listView.setFilterText() rather then adapter filter.
You have to override the toString() method, to return the text you want to filter.