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
}
});
}
}
Related
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
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.
So I'm having a weird order of events in my code. It'll probably be something minor that I haven't seen yet. A have ListView that and is pulling the string from an EditText after button click.
The EditText lives in a dialog that's being pulled back to the main Activity by an interface
What happens now, is when I type something in the EditText field say "a", nothing shows up. But when I go to add another, "b", "a" shows up. and so forth. So one has to be created in order for the previous to show up.
Here's my what I have.
public class NewActivity extends FragmentActivity implements AddSiteDialog.AddSiteDialogListener {
ListView mSiteListView;
ArrayList<String> siteList = new ArrayList<String>();
CustomAdapter arrayAdapter = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_site);
mSiteListView = (ListView) findViewById(R.id.siteAddList);
arrayAdapter = new CustomAdapter();
mSiteListView.setAdapter(arrayAdapter);
Button b = (Button) findViewById(R.id.addSiteButton);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showDialog();
}
});
}
public void showDialog() {
FragmentManager fm = getSupportFragmentManager();
AddSiteDialog addSiteDialog = new AddSiteDialog();
addSiteDialog.show(fm, "main");
}
public void onSignIn(String inputText) {
siteList.add(inputText);
}
class CustomAdapter extends ArrayAdapter<String> {
CustomAdapter() {
super(NewActivity.this, R.layout.add_site, siteList);
}
public View getView(int position, View convertView, ViewGroup parent){
View row = convertView;
if (row == null){
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.list_row, parent, false);
}
((TextView) row.findViewById(R.id.textViewId)).setText(siteList.get(position));
return (row);
}
}
}
Can anyone spot where this is happening?
Simple.
call arrayAdapter.notifyDataSetChanged() in
public void onSignIn(String inputText) {
siteList.add(inputText);
//add that here
}
If the data which is backed by your adapter changes, you need to call notifyDataSetChanged() on your adapter to instruct the ListView to update itself.
I don't see anything like that in your code.
Just to add:
Your adapter implementation is sub-optimal - although in this case it doesn't really matter.
You should create a ViewHolder and store it as your View's tag, so that you can retrieve it if convertView is given. The ViewHolder should keep references to all sub-views of your view (TextView, ImageView, whatever you need to update). This would avoid the repeated call to findViewById() - which is slow.
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);
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.