I have a ListView with a CustomAdapter that has up to 50 rows( only 11 on the screen at once). Each row contains a spinner and two EditTexts. I pass 3 sets of data to the adapter for each of the three columns. When a spinner item is selected or text changed I want to amend the relevant data set inside the adapter so that it can be retrieved by the calling activity.
I can get a OnItemSelectedListener() registered against each spinner, however, I can't find a way to know which row the spinner was on. Because of that I can't update the data set.
This is the adapter.
SQLiteDatabase db;
Activity mActivity;
int [] mCategories;
String [] mComments;
String [] allCategories;
int [] mAmounts;
String [] spinnerValues;
TransCatListAdapter(Activity activity, int[] categories, String[] comments, int[] amounts){
super (activity, R.layout.transcat_row, comments);
mActivity = activity;
mCategories = categories;
mComments = comments;
mAmounts = amounts;
db = DatabaseHelper.getInstance(activity);
}
public View getView(int pos, View convertView, ViewGroup parent) {
View row = convertView;
if (row==null) {
LayoutInflater inflater=mActivity.getLayoutInflater();
row = inflater.inflate(R.layout.transcat_row, null);
}
Spinner SPNCategory = (Spinner) row.findViewById(R.id.trncatrow_category);
EditText ETComment = (EditText) row.findViewById(R.id.trncatrow_comment);
EditText ETAmount = (EditText) row.findViewById(R.id.trncatrow_amount);
SPNCategory.setAdapter(new CategorySpinnerAdapter(mActivity, R.layout.categoryspinnerstyle, DatabaseMethods.getCategories(db)));
ETComment.setText(mComments[pos]);
ETAmount.setText(Utils.formatAsMoneyString(mAmounts[pos]));
return (row);
}
So if I understand correctly, you want to be able to register an OnItemSelectedListener to your spinners but you want to be able to identify WHICH spinner it was right? Try this
getView(int pos, View convertView, ViewGroup parent) {
...
spinner SPNCategory = (Spinner) row.findViewById(R.id.trncatrow_category);
spinner.setOnItemSelectedListener(new YourSpinnerListener(pos);
...
private class YourSpinnerListener implements OnItemSelectedListener {
private int mSpinnerPosition;
public YourSpinnerListener(int spinnerPosition) {
mSpinnerPosition = spinnerPosition;
}
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
This class that implements the OnItemSelectedListener now has a reference to the position of the spinner.
Have fun!
Related
I don't know how to set the selected country isd code in
spinner.Below I have posted the code what I have been tried so far:
MainActivity.java:
public class MainActivity extends Activity implements OnItemSelectedListener {
ArrayList<String> arrCode;
ArrayList<String> arrCountry;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
arrCode = new ArrayList<>();
arrCountry = new ArrayList<>();
arrCountry.add("US");
arrCountry.add("KZ");
arrCountry.add("EG");
arrCountry.add("ZA");
arrCountry.add("GR");
arrCode.add("1");
arrCode.add("7");
arrCode.add("20");
arrCode.add("27");
arrCode.add("30");
ArrayAdapter<String> adapter_state = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, arrCountry);
adapter_state.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sp_mobile_code.setAdapter(adapter_state);
sp_mobile_code.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
int spinnerValue1 = sp_mobile_code.getSelectedItemPosition();
String data = arrCode.get(spinnerValue1);
Log.e("data", "" + data);
sp_mobile_code.setPrompt(data);
/* sp_mobile_code.setSelection(position);*/
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
My issue is : I can't set the isd code in same spinner.If I have to
set isd code in textview means it will be easy.But I have to set it
in the spinner
Edit: spinner list showing correctly the country list.on clicking the country list, I have to show the isd code
Use Custom ArrayAdapter.
private static class CustomSpinnerAdapter extends ArrayAdapter<String>
{
List<String> arrCodes;
public CustomSpinnerAdapter(Context context, int resource, List<String> items, List<String> arrCodes)
{
super(context, resource, items);
this.arrCodes = new ArrayList<>();
this.arrCodes = arrCodes;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
TextView view = (TextView) super.getView(position, convertView, parent);
view.setText(arrCodes.get(position));
return view;
}
}
Check the position in the getView() and set text of your desire. Use this adapter for the Spinner
I've been trying to make listView redirect user onClick to URL's when clicking on different elements.
Example:
clicking on "apple" would open "stackoverflow.com",
but clicking on tomato would open "google.com" etc.
Could anyone give me some advice how can I accomplish this, because after 2 days of trying and searching all I've got is a headache..
displayMainMenu.java
public class DisplayMainMenu extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_main_menu);
final String[] food = new String[] {"Apple", "Tomato", "Potato"};
ListAdapter adapter = new MyAdapter(this, food);
ListView listView = (ListView) findViewById(R.id.mainMenu);
listView.setAdapter(adapter);
}
class MyAdapter extends ArrayAdapter<String>
{
public MyAdapter(Context context, String[] values)
{
super(context, R.layout.entry, values);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.entry, parent, false);
String text = getItem(position);
TextView textView = (TextView) view.findViewById(R.id.listTextView1);
textView.setText(text);
return view;
}
}
}
You should make a new class that holds the shown string value (Apple, Tomato, Potato, etc) and also holds the URL that you want to link to.
Then make the ArrayAdapter use that class. The getView function you have already should suffice (when its updated to use the new class).
Then in your activity, use 'setOnItemClickListener' to set a new listener.
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MyItem clickedItem = () parent.getItemAtPosition(position);
<< Insert code to open the link with the URL you can get from 'clickedItem' >>
}
});
That should do it.
I delete database entry using onclicklistener but it is not refreshing the listview. how can i refresh this listview?
This is main class for listview:
public class AFragment extends Fragment implements OnItemClickListener {
protected static final String file_name ="user";
ListView list;
Database entry;
View v;
String values[];
MySimpleArrayAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
SharedPreferences settings = getActivity().getSharedPreferences(file_name, 0);
String name = settings.getString("name", null);
entry = new Database(getActivity());
entry.open();
values=entry.planlist(name);
entry.close();
if(values.length>0){
v = inflater.inflate(R.layout.activity_afragment, container,false);
adapter = new MySimpleArrayAdapter(getActivity(), values);
list=(ListView)v.findViewById(R.id.list);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
list.setOnItemClickListener(this);
}else{
v = inflater.inflate(R.layout.activity_my_tabs_listener, container,false);
}
// Toast.makeText(getActivity(),String.valueOf(values.length), Toast.LENGTH_LONG).show();
return v;
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Intent i = new Intent(getActivity(),Details.class);
i.putExtra("sub", values[arg2]);
startActivity(i);
Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
}
}
Here i use onclicklistener to delete data from database but it is not refreshing:
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public Business aFragment = new Business();
int mypos =0;
ViewHolder holder;
View row;
public MySimpleArrayAdapter(Context context, String[] values) {
super(context,R.layout.activity_my_simple_array_adapter, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
mypos = position;
row = convertView;
holder = new ViewHolder();
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(R.layout.activity_my_simple_array_adapter, parent, false);
TextView textView = (TextView) row.findViewById(R.id.text);
Button btn = (Button) row.findViewById(R.id.button1);
holder.tv = textView;
holder.btn = btn;
row.setTag(holder);
}else{
holder = (ViewHolder)row.getTag();
}
holder.tv.setText(values[position]);
final int id = position;
holder.btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Database entry = new Database(context);
entry.open();
entry.delete(values[id]);
entry.close();
// Toast.makeText(getContext(), String.valueOf(id), Toast.LENGTH_LONG).show();
}
});
return row;
}
static class ViewHolder{
TextView tv;
Button btn;
}
}
as anil said, you should put notifyDataSetChanged(); inside the onClickListener
this basically tells the adapter to render the list again and will call getView() again for every visible item in the list, if your code crashes, you should check two things:
first - debug the program and check that the new data fits what you want, in your case, check that the entry was deleted properly.
second - debug the getView method, step through each call and see what gives you the crash.
in your case the problem is that you are only updating the database, but in fact your listview data is taken from the values[] array which is not updated after you delete the database entry, you should create a function for updating it.
Put adapter.notifyDataSetChanged(); on click of ListView
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Database entry = new Database(context);
entry.open();
entry.delete(values[id]);
entry.close();
adapter.notifyDataSetChanged();
// Toast.makeText(getContext(), String.valueOf(id), Toast.LENGTH_LONG).show();
}
If you do lots of adding and deleting to the list I think you should do the things below.
You should use ArrayList<String> instead of simple String[] so that you can easily delete. Database deletion do not effect the list directly unless you use Loaders
After you delete and item from the list, you should call notifyDataSetChanged() to the adapter. If you do not call this method, the list wont be updated.
adapter.notifyDataSetChanged();
you are removing it from the database but you are not removing it from the dataset that fills up your ListView. The simplest thing you can do is to change values from array to ArrayList, and since you are using an ArrayAdapter, you can call remove(int position). You need a List<T> of objects otherwise remove will throws an exception.
You can do one thing.
Firstly create a method called myAdapter().
In this put your creation of adapter code,so you can create new adapter for loading new data by simply calling myAdapter() method.
Whenever there should be modification in your ListView just called the following code,
listview.invalidate();
Then simply call the myAdapter().
That's it.Hope this is useful to you..:)
SOLVED HERE IS THE SOLUTION ANSWER http://www.congdegnu.es/2011/06/02/spinners-en-android-tres-formas-de-poblarlos/
I'm populating a spinner from my sqlite database like this:
Cursor CS = newDB.rawQuery("Select ID AS _id, Name from Schools",null);
CS.moveToFirst();
do{
Schools.add(CS.getString(CS.getColumnIndex("_id")));
} while(CS.moveToNext());
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item,Schools);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(dataAdapter);
My problem is that I only add an id but how can I add a value to that id so when the value get select I get the id ?
I think that "schools" is an array containing you own class "school".
You could add a propertie which contains the information.
Or you could use a 2 dimensional array.
Than you have to set up your arrayadapter to get the information (getter Method).
Hope it helps
Try Cursor Adapter
or
Take a global variable
Hashmap schoolmap=new Hashmap();
While inserting data to the list also add to Hashmap like this
CS.moveToFirst();
do{
Schools.add(CS.getString(CS.getColumnIndex("_id")));
schoolmap.put(CS.getString(CS.getColumnIndex("_id")),CS.getColumnIndex("_id"))
} while(CS.moveToNext());
onSpinner item click get the value like this
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
String value=((TextView)view).getText();
int id=Integer.parseInt(schoolmap.get(value));
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
Take a look at using a SimpleCursorAdapter for your spinner instead. Although this has been deprecated since API-11, so you may also want to think about using a LoaderManager with a CursorLoader.
An explanation on how to transition to a LoaderManager and CursorLoader can be found here:
How to transition from managedQuery to LoaderManager/CursorLoader?
I would recommend you start by using the SimpleCursorAdapter, then if confortable enough, move on to the other method.
1) Create an ArrayList<School>
2) Add all your Schools to the Arraylist
3) Create a custom adapter like this:
public class SchoolAdapter extends ArrayAdapter<School>{
public SchoolAdapter(Context ctx, List<School> schools){
super(ctx, 0, schools);
}
#Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
TextView tv;
if (convertView == null){
tv = new TextView(getContext());
} else {
tv = (TextView) convertView;
}
tv.setTextSize(16);
final School school = getItem(position);
tv.setText(school.toString());
return tv;
}
}
4) Use this in your activity:
final SchoolAdapter adapter = new SchoolAdapter(this, schools);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
School school = adapter.getItem(pos);
// Do whatever you want with your school
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
My activity contains a button and a ListView. The ListView contains a Spinner and an EditText view. I use the button each time I want to insert a new row entry in my Activity's ListView.
I have followed the instructions of previous stackoverflow threads like this one here: Android Listview with spinner and a checkbox on how to populate ListViews with focusable objects like Spinners.
My problem is that each time I dynamically add a new ListView entry in the ListView, the Spinner value of the previous ListView entry is lost (actuall the Spinner returns to its default setting). Say for simplicity that my Spinners are populated with the following data:
String spinner_data[] = {"apple", "banana", "pear", "watermelon", "strawberry"};
For example, if I select my first ListView's Spinner value to be "pear" and then I add a new ListView entry with my Button, the "pear" entry disappears from the 1st ListView Spinner and the default value "apple" appears).
Any help is appreciated!
This is my activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView) findViewById(R.id.lv);
da = new DataAdapter(this, new ArrayList<RawData>());
lv.setAdapter(da);
btn_new = (Button)findViewById(R.id.btn_new);
btn_new.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
da.add(new RawData(this));
da.notifyDataSetChanged();
}
});
}
The RawData class is this one:
public class RawData {
private int selected_position;
private ArrayAdapter<CharSequence> adapter;
public RawData(Context context)
{
adapter = ArrayAdapter.createFromResource(context, R.array.data, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}
public ArrayAdapter<CharSequence> getAdapter()
{
return adapter;
}
/**
* get adapter's item text from selected position
* #return
*/
public String getText()
{
return (String) adapter.getItem(selected_position);
}
public int getSelected()
{
return selected_position;
}
public void setSelected(int selected)
{
this.selected_position = selected;
}
}
The DataArrayAdapter is the following:
public class DataArrayAdapter extends ArrayAdapter<RawData> {
private Activity myContext;
//private final List<RawData> list;
public DataArrayAdapter(Activity context, List<RawData> list)
{
super(context, R.layout.row_view, list);
myContext = context;
}
static class ViewHolder
{
protected RawData data;
protected Spinner spn;
protected EditText edt;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View view = null;
if ( convertView == null )
{
LayoutInflater inflator = myContext.getLayoutInflater();
view = inflator.inflate(R.layout.row_view, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.edt = (EditText)view.findViewById(R.id.edt);
viewHolder.data = new RawData(myContext);
viewHolder.spn = (Spinner)view.findViewById(R.id.spn);
viewHolder.spn.setAdapter(viewHolder.data.getAdapter());
viewHolder.spn.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2_position, long arg3) {
// TODO Auto-generated method stub
viewHolder.data.setSelected(arg2_position);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
// Update the TextView to reflect what's in the Spinner
view.setTag(viewHolder);
}
else
{
view = convertView;
}
// This is what gets called every time the ListView refreshes
ViewHolder holder = (ViewHolder) view.getTag();
holder.spn.setSelection(getItem(position).getSelected());
return view;
}
}
You're not handling the situation when getView gets a non-null convertView. In your example, after you add an item, ListView refreshes itself, and position that should display 'pear' gets an existing convertView (the one that was used previously to display 'apple') and you just pass it along to ListView without setting the data for current position. You cannot rely on ListView items to store any data, you should always set correct contents for position in getView method of your adapter.
Just to be clear, I see that your code sets the selected position in the end of getView but the issue is that whatever is tagged to your convertView when it is passed to getView by recycler mechanism in ListView is random and can be associated with any position it used to display before.
To make your application work you'll have to create array of selectedItem values for all your spinners, and attach it as a member to your adapter. You'll have to update the corresponding value on each OnItemSelected event and you'll add a new value for each "add" button click. And when you prepare your view in getView you'll just set the selected spinners index to corresponding value in your array.