Can I have two different sources pass data to an array adapter? - android

I am trying to add data from two different sources to an array adapter. One source is from a spinner containing hard coded strings, the other is to allow the user to create their own string to pass to the array (via the adapter). Here is my code below. It appears to me that the array adapter can only except one data source according to the arguments that can be passed to it.......ie
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource
(this, R.array.alarmList, android.R.layout.simple_spinner_item );
Here I can only guess that the actual string input is gathered from......... android.R.layout.simple_spinner_item
Do I need to use another array adapter or is there a way to add my string variable to the adaoter as well as the item the user has chosen from the spinner? I've done some research here but drawing a blank!!Many thanks. Here's my code which tries to enter strings to adapter..........
public class NewAlarm extends Activity {
Spinner alarms;
//private Button b = (Button) findViewById(R.id.btnAddCustom);
final EditText et = (EditText) findViewById(R.id.edittext);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newalarm);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.alarmList, android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
//et.setText("name");
alarms = (Spinner) findViewById(R.id.cmbAlarms);
alarms.setAdapter(adapter);
}
public void addAlarm(View view) {
MainMenu.alarmList.add(new Alarm(alarms.getSelectedItem().toString()));
Toast.makeText(getApplicationContext(), "Added " + alarms.getSelectedItem().toString() + " alarm.", Toast.LENGTH_SHORT).show();
NewAlarm.this.finish();
}
public void addCustomAlarm (View view){
MainMenu.alarmList.add(new Alarm(et.getText().toString()));
}
}
And here's my array adapter code............
public View getView(final int position, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.alarm_item, null);
}
Thanks guys!!
// Get a handle on the UI controls
TextView name = (TextView) convertView.findViewById(R.id.txtAlarmName);
final TextView timeStamp = (TextView) convertView.findViewById(R.id.txtTimeStamp);
// if the value of the timestamp from the alarm at the position selected is not a null value then set the text label to the alarm timestamp value
if (MainMenu.alarmList.get(position).getTimeStamp() != null)
{
timeStamp.setText(MainMenu.alarmList.get(position).getTimeStamp().toString());
}
// Set the alarm name
name.setText(listItems.get(position).getName());
// Get a handle on the button
Button btnCheckNow = (Button) convertView.findViewById(R.id.btnCheckNow);
btnCheckNow.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
// Set the timestamp of the alarm object at the selected position
MainMenu.alarmList.get(position).setTimeStamp();
// Set the timestamp label
timeStamp.setText(MainMenu.alarmList.get(position).getTimeStamp().toString());
}
});
return convertView;
}

Instead of calling ArrayAdapter.createFromResource(), import the array and add the string before creating the adapter :
CharSequence[] array = Arrays.asList(
getResources().getTextArray(R.array.alarmList));
List<CharSequence> list = new ArrayList<CharSequence>(array);
list.add("custom string");
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(this,
android.R.layout.simple_spinner_item, list);

Related

ToggleButtons on ListView

What is the syntax to get a specific togglebutton from a listview containing the said togglebuttons within a listview_row layout?
I would like to initiate the state of each togglebutton (based on some values originating from a Database), within the onCreate method. I have the following code within a loop, but I am not sure how to change it to reference a specific togglebutton from the listview.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mydb = new DBHelper(this);
ArrayList array_list = mydb.getAllAlarms();
for(int i = 0; i < array_list.size(); i++) {
arrayListItem = array_list.get(i).toString();
activationInt = Integer.parseInt(arrayListItem);
LayoutInflater vi = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listview_row, null);
alarm_activated = (ToggleButton) view.findViewById(R.id.alarm_activated);
if (activationInt == 1) {
alarm_activated.setChecked(true);
alarm_activated.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.MULTIPLY);
} else {
alarm_activated.setChecked(false);
}
}
ArrayAdapter arrayAdapter =
new ArrayAdapter(this, listview_row,R.id.alarm_name,array_list);
obj = (ListView)findViewById(R.id.listViewAlarms);
obj.setAdapter(arrayAdapter);
obj.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
String itemVal =(String) arg0.getItemAtPosition(arg2);
Bundle dataBundle = new Bundle();
dataBundle.putString("name", itemVal);
Intent intent = new
Intent(getApplicationContext(),DisplayAlarm.class);
intent.putExtras(dataBundle);
startActivity(intent);
}
});
Updating views of a ListView/RecyclerView should not really be done in this way.
First because child views referenced in a ListView do not represent the totality of your rows, but only the visible rows at one moment.
ListView binds their item views on DataSet values, so you'd better use data objects that contains your "checked" boolean status, then when you need to sync, update your DataSet and notifyDataSetChange your adapter.
So you'll have to create your custom adapter by following this kind of example : Custom Adapter for List View

ListView creates one more item than needed

I have a ListView which is populated in my MainActivity, but when i want to find the selected item, all of the items appear to have the same position.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_teams);
ListView mainListView;
// Find the ListView in the UI.
mainListView = (ListView) findViewById( R.id.listView );
String values = "Team A vs Team B=Team C vs Team D";
//Matches are send in one long string, and are separated by the = sign.
//This splits the string up and puts it into an array.
String[] array = values.split("=", -1);
ArrayList<String> arraylist = new ArrayList<String>();
arraylist.addAll( Arrays.asList(array) );
ArrayAdapter listAdapter;
// Create ArrayAdapter using the planet list.
listAdapter = new ArrayAdapter<String>(this, R.layout.list_view_style, arraylist);
// Set the ArrayAdapter as the ListView's adapter.
mainListView.setAdapter(listAdapter);
}
This makes a list like this:
Team A vs Team B [checkbox]
Team C vs Team D [checkbox]
I have a button and when it is clicked it runs this method:
public void matchStart(View view){
String selectedMatch = String.valueOf(((ListView) findViewById( R.id.listView )).getSelectedItemPosition());
Toast.makeText(SelectTeams.this, selectedMatch, Toast.LENGTH_SHORT).show();
}
However whenever i click the button, the toast displays the same value no matter which item in the listview is selected. Why is this?
You should use the adapters getView method, something like this:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.some_layout, parent,
false);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//here get what you need by the position
}
});
}
}

ListVIew not updating onRestoreSaveInstanceState

Here is my method:
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
DataBaseHandler handler = new DataBaseHandler(getApplicationContext());
//set the spinner for measurement type
Spinner measurementTypeSpinner = (Spinner) findViewById(R.id.MeasurementTypes);
ArrayAdapter adapter = (ArrayAdapter) measurementTypeSpinner.getAdapter();
int typePos = adapter.getPosition(savedInstanceState.getString("measurementtype"));
measurementTypeSpinner.setSelection(typePos);
//set the spinner for the measurement unit
Spinner measurementUnitSpinner = (Spinner) findViewById(R.id.MeasurementSubValues);
ArrayAdapter arrayAdapter = (ArrayAdapter) measurementUnitSpinner.getAdapter();
int unitPos = arrayAdapter.getPosition(savedInstanceState.getString("measurementunit"));
measurementUnitSpinner.setSelection(unitPos);
//set the value
EditText value = (EditText) findViewById(R.id.unit_value);
value.setText(savedInstanceState.getString("value"));
/**
* The list view stuff
*/
ListView unitsList = (ListView) findViewById(R.id.units_list);
unitsList.setItemsCanFocus(true);
MeasurementType mType = handler.getMeasurementType(savedInstanceState.getString("measurementtype"));
//create the converter
Converter converter = new Converter(MeasurementType.getMeasurementType(savedInstanceState.getString("measurementtype")), savedInstanceState.getString("measurementunit"), savedInstanceState.getString("value"));
//convert the values
ArrayList<Unit> convertedValues = converter.convert();
//set the adapter for the list view
unitAdapter = new UnitListAdapter(this, convertedValues, mType);
unitsList.setAdapter(unitAdapter);
}
Basically, there is another activity with a list of items and when the user checks one, it updates the database setting an int property to 1, so that when the ArrayAdapter goes through an arraylist it picks up the property as 1 and displays it, instead of 0 in which case it doesn't display it.
Now on pressing the back button, both the spinners are populated with the values I stored, the value for the EditText is restored, but the ListView is not updated, yet when I leave the app and come back in, the value that was checked is there in the list...
This says to me that I might need to do something with onStop() and onRestart() could someone please advice me. The comment saying 'the list view stuff' is where I am trying to update the list view, it just isn't working and when I debug it won't go into the restore method at all, which is confusing.
EDIT
public class UnitListAdapter extends ArrayAdapter<Unit> {
private Context context;
private ArrayList<Unit> units;
private MeasurementType type;
public UnitListAdapter(Context context, ArrayList<Unit> units, MeasurementType type) {
super(context, R.layout.unit, R.id.unit_name, units);
this.context = context;
this.units = units;
this.type = type;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.unit, parent, false);
final TextView unitName = (TextView) rowView.findViewById(R.id.unit_name);
final EditText unitValue = (EditText) rowView.findViewById(R.id.unit_value);
if(units.get(position) != null) {
if(units.get(position).getView() == 1) {
unitName.setText(units.get(position).getUnitName());
unitValue.setText(units.get(position).getValue().toString());
} else {
unitName.setVisibility(View.GONE);
unitValue.setVisibility(View.GONE);
}
}
return rowView;
}
#Override
public void add(Unit u) {
units.add(u);
notifyDataSetChanged();
}
#Override
public void clear() {
units.clear();
notifyDataSetChanged();
}
#Override
public int getCount() {
return units.size();
}
}
As asked for. Sorry about confusion whilst editing.
onRestoreInstanceState() is not called when the user presses the back button. Most likely you need to move your logic to onResume(). I suggest that you read about the Activity lifecycle to get a better understanding about when each of the onXxx() methods are called.
After updating the list you need to call notifyDataSetChanged() to repopulate the listview.
http://developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged()

How to control values and text in spinner

I want to build android app with spinner , I would like to appear in spinner some text , and when selected, it appears in TextView other text than the value of which is a selected.
for example , i want to appear in spinner website name (like= stackoverflow) and when select appear in TextView the website URL (like=https://stackoverflow.com/)
can anyone help me?
thanks in advance
First, you create yourself an Object:
public class LanguageObject {
private String title;
private String url;
public LanguageObject(String title, String url) {
this.title = title;
this.url = url;
}
public String getTitle() {
return title;
}
public Integer getUrl() {
return url;
}
}
Then, in your Activity/Fragment, you create an ArrayList with the objects you need:
ArrayList<SpinnerObject> spinnerObjectList = new ArrayList<SpinnerObject>();
spinnerObjectList.add(new SpinnerObject("Google", "www.google.com"));
spinnerObjectList.add(new SpinnerObject("StackOverflow", "www.stackoverflow.com"));
In addition to that, create a custom adapter that will handle your data:
public class SpinnerAdapter extends ArrayAdapter<SpinnerObject> {
public SpinnerAdapter (Context context, int textViewResourceId, ArrayList<SpinnerObject> spinnerObjects) {
super(context, textViewResourceId, spinnerObjects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
SpinnerObject spinnerObject = getItem(position);
if(view == null) {
LayoutInflater layoutInflater;
layoutInflater = LayoutInflater.from(getContext());
view = layoutInflater.inflate(android.R.layout.select_dialog_item, null);
if (view != null) {
TextView textView = (TextView) view.findViewById(android.R.id.text1);
textView.setText(spinnerObject.getTitle());
}
}
return view;
}
Now you can use this adapter on your Spinner, and get the url when one of the items was clicked.
You can add text to spinner like this:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
List<String> texts = new ArrayList<String>();
texts.add("Google");
texts.add("Facebook");
List<String> urls = new ArrayList<String>();
urls.add("www.google.com");
urls.add("www.facebook.com");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, texts);
spinner.setAdapter(adapter);
then you need to listen for item selected on spinner
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
String url = urls.get(i);
// do with url whatever you need
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
// do nothing
}
});
For adding text in spinner you can use following code in onCreate()
Spinner locale;
ArrayList<String> lList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locale =(Spinner)findViewById(R.id.Cmblocale);
// bind data to Spinner(ComboBox)
lList =new ArrayList<String>();
lList.add("English");
lList.add("Canada");
lList.add("Chinese");
lList.add("French");
lList.add("Germany");
lList.add("Japan");
ArrayAdapter<String> cAdapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_item,lList);
locale.setAdapter(cAdapter);
}
For Retrieving value use following code inside your setOnItemSelectedListener on spinner
if(locale.getSelectedItem().equals("English"))
{
txtText.setText(English);
}else if(locale.getSelectedItem().equals("Chinese"))
{
txtText.setText(Chinese);
}else if(locale.getSelectedItem().equals("Canada"))
{
txtText.setText(Canada);
}else if(locale.getSelectedItem().equals("French"))
{
txtText.setText(French);
}else if(locale.getSelectedItem().equals("Germany"))
{
txtText.setText(Germany);
}else if(locale.getSelectedItem().equals("Japan"))
{
txtText.setText(Japan);
}
Spinner spinner = (Spinner) findViewById(R.id.spinner); //create a spinner view in XML
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.your_array, android.R.layout.simple_spinner_item); // create adapter which has second parameter as the array which contains the values you want to show as entries of spinner
spinner.setAdapter(adapter); // set the adapter to your spinner and your spinner will show the values from array that you set in second parameter of adapter
To listen to the click on the options of the spinner
public class SpinnerActivity extends Activity implements OnItemSelectedListener {
...
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
}
Now to show the appropriate link of the website for selected option from spinner you can have a map which has keys as same as the spinner values and values as websites as you want....
HashMap<String, String> nameWebsiteMap = new HashMap<String, String>();
nameWebsite.put("stack overflow","http://stackoverflow.com/"); // for example
So in onItemSelected you can simply do this
selectedSiteName = nameWebsite.get(parent.getItemAtPosition(pos).toString());
textView.setText(selectedSiteName);

Android: Spinners within a ListView loose their values when I add dynamically new ListView entries

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.

Categories

Resources