In my app, I want the users to see a list of cities, select the city, then see people associate with that city.
So, I have this to get the data:
protected void onResume() {
super.onResume();
setProgressBarIndeterminateVisibility(true);
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.orderByAscending(ParseConstants.KEY_LOCATION);
query.setLimit(1000);
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> users, ParseException e) {
setProgressBarIndeterminateVisibility(false);
if (e == null) {
// Success
mMidwifeLocation = users;
String[] locations = new String[mMidwifeLocation.size()];
String check;
int i = 0;
for(ParseUser user : mMidwifeLocation) {
check=user.getString("city");
if(check!=null){
if(!Arrays.asList(locations).contains(check)){
locations[i] = user.getString("city");
}
}
i++;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
SearchingMidwife.this,
android.R.layout.simple_list_item_checked,
locations);
setListAdapter(adapter);
}
else {
Log.e(TAG, e.getMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(SearchingMidwife.this);
builder.setMessage(e.getMessage())
.setTitle(R.string.error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
And this to pass the selected item to the new activity:
#Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id);
SparseBooleanArray checked = l.getCheckedItemPositions();
ArrayList<String> selectedItems = new ArrayList<String>();
for (int i = 0; i < checked.size(); i++) {
// Item position in adapter
position = checked.keyAt(i);
// Add sport if it is checked i.e.) == TRUE!
if (checked.valueAt(i))
selectedItems.add(adapter.getItem(position));
}
String[] outputStrArr = new String[selectedItems.size()];
for (int i = 0; i < selectedItems.size(); i++) {
outputStrArr[i] = selectedItems.get(i);
}
Intent intent = new Intent(getApplicationContext(),
MidwifeResultList.class);
// Create a bundle object
Bundle b = new Bundle();
b.putStringArray("selectedItems", outputStrArr);
// Add the bundle to the intent.
intent.putExtras(b);
// start the ResultActivity
startActivity(intent);
}
When I try it though, the app stops with an error once I select the item...
FATAL EXCEPTION: main Process: android.bignerdranch.com.mobilemidwife,
PID: 31604 java.lang.NullPointerException at
android.bignerdranch.com.mobilemidwife.SearchingMidwife.onListItemClick(SearchingMidwife.java:169)
Which points to this:
if (checked.valueAt(i)) selectedItems.add(adapter.getItem(position)); }
I declare adapter before onCreate:
ArrayAdapter adapter;
I assume this is the same adapter that is used in OnResume...something is not quite right, not sure what that would be. It seems like the adapter from onResume is not being passed into onResume, as it is null.
I am a bit new to this, so trying to learn this as best I can; I apologize if the problem is something missed that is simple.
Thanks so much for your help/insights
Michael Cabus
Your problem is here:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
SearchingMidwife.this,
android.R.layout.simple_list_item_checked,
locations);
This is creating a local variable which is only scoped inside the method.
Change it to
adapter = new ArrayAdapter<String>(
SearchingMidwife.this,
android.R.layout.simple_list_item_checked,
locations);
by removing the leading ArrayAdapter<String> and that should fix this particular problem.
Update:
May I suggest using a different coding style such as putting leading underscore to your class member variables so that it's easier to detect these problems in the future? it's only a suggestion but I've found it immensely helpful to adapt this particular style.
What I mean is to for instance declare your variable like
ArrayAdapter _adapter;
in your class and then set it like this:
_adapter = new ArrayAdapter<String>(
SearchingMidwife.this,
android.R.layout.simple_list_item_checked,
locations);
Now every time you see "_", it's indicating that it's a member variable and not a local variable (since you would declare those without the leading underscore).
Just a personal suggestion. Up to you to adopt it or leave it.
Related
I'm trying to select an item in a ListView based on a value I get from an Intent. I've tried ListView.setSelection, but it's not working.
Intent i = this.getIntent();
String sp = i.getStringExtra("Sport");
for (int position = 0; position < sports.length; position++)
if (sports[position].equals(sp)) {
listView.setSelection(position);
}
Here is the rest of the code, for context:
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sport_item);
ListView listView = findViewById(R.id.listview);
String[] sports = new String[] {
"Soccer",
"Running",
"Swimming",
"Volleyball",
"Tennis"
};
ArrayAdapter arrayAdapter = new ArrayAdapter(this, R.layout.listview, R.id.textView, sports);
listView.setAdapter(arrayAdapter);
Button btnSelect = findViewById(R.id.btnSelect);
listView.setChoiceMode(listView.CHOICE_MODE_SINGLE);
btnSelect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (ListView.getCheckedItemPosition() != -1) {
Intent i = new Intent(SportActivity.this, InformationActivity.class);
i.putExtra("Sport", sports[listView.getCheckedItemPosition()]); |
i.putExtra("Position", listView.getCheckedItemPosition());
setResult(Activity.RESULT_OK, i);
finish();
} else
Toast.makeText(SportActivity.this, "Ban chua lya chon", Toast.LENGTH_SHORT).show();
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(SportActivity.this, "Sport selected :" + sports[i], Toast.LENGTH_SHORT).show();
}
});
Intent i = this.getIntent();
String sp = i.getStringExtra("Sport");
for (int position = 0; position < sports.length; position++)
if (sports[position].equals(sp)) {
listView.setSelection(position);
}
}
show more code, post it in here. you should call setSelected only after setting adapter, before there is no content on list so nothing gets selected
in your case your problem is caused probably by comparing Strings with == operator. in Java it compares objects and one obtained from intent and second one from array arent same objects, even if they have same content (they still are two objects in two separated placed in memory). use equals method for comparing only content
if(sports[position].equals(sp))
I need some help guys.
The problem is that I have a spinner that has commodities in it, such as chemicals,biscuits etc. but these commodities are stored in the database. I have written a web service that retrieves the commodities and the corresponding commodity code from database the web service works fine. I am getting the data in my android code. So I have stored the commodity in one array list say ar1, and the commodity code in one more array list say ar2. Now I want these commodity, what I have stored in ar1 to be displayed as spinner items and when user selects one of the spinner items, I must be able to retrieve the corresponding commodity code of that commodity.
Can some body help me??
I am using the below code but i am not able to get the desired result
String[] arr_Commodities = new String[ar2.size()];
spinnerMap = new HashMap<String, String>();
for (int i = 0; i < ar2.size(); i++)
{
spinnerMap.put(ar2.get(i),ar1.get(i));
arr_Commodities[i] = ar2.get(i);
System.out.println(arr_Commodities[i]);
}
ArrayAdapter<String> adapter =new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_spinner_item, arr_Commodities);
adapter =new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_spinner_item, arr_Commodities);
spin_commodity.setAdapter(adapter);
I find nothing is wrong with this code but i am still not able to pop[ulate the spinner some one please modify the above code..thank you
you can try this and improvise the loop on populating items:
final ArrayList<String[]> items = new ArrayList<String[]>();
for(int i= 0; i <10 ; i++){//sample loop populating items
String[] item = new String[2];
item[0] = "id";
item[1] = "commodities";
items.add(item);
}
Spinner s = new Spinner(context);//sample spinner
ArrayAdapter<String[]> adapter = new ArrayAdapter<String[]>(context , android.R.layout.simple_list_item_1, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
s.setOnItemSelectedListener(new OnItemSelectedListener(){
#Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {
// TODO Auto-generated method stub
String[] selected = items.get(position);
//commodity id
String comId = selected[0];
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
});
String[] ar1={"chemicals","biscuits"};
String[] ar2={"1","2"};
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, ar1); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
your_spinner.setAdapter(adapter);
//to get the selected item position
int x=your_spinner.getSelectedItemPosition();
Your required code is
String code=ar2[x];
I am attempting to pass selected items on a list to a new activity.
I declared an ArrayAdapter
ArrayAdapter madapter
Before OnCreate; in OnResume, I collect the data; and assign it to mAdapter
//variable mAdapter
//new ArrayAdapter string
madapter = new ArrayAdapter<String>(
SearchingMidwife.this,
android.R.layout.simple_list_item_checked,
locations);
//set List to display mAdapter
And then I have this, that should allow for, when a listItem is clicked, to get selected items into a variable, and pass it to a new activity
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//in checked, in listview get Item positions for checked items
SparseBooleanArray checked = l.getCheckedItemPositions();
//assign selected items to new String ArrayList
ArrayList<String> selectedItems = new ArrayList<String>();
//determine size of items checked (number)
for (int i = 0; i < checked.size(); i++) {
// Item position in adapter
position = checked.keyAt(i);
// Add location if it is checked i.e.) == TRUE!
if (checked.valueAt(i))
//add selected items to madapter
selectedItems.add(madapter.getItem(position));
}
//create string output array, store new string array with selected items
String[] outputStrArr = new String[selectedItems.size()];
for (int i = 0; i < selectedItems.size(); i++) {
outputStrArr[i] = selectedItems.get(i);
}
Intent intent = new Intent(getApplicationContext(),
MidwifeResultList.class);
// Create a bundle object
Bundle b = new Bundle();
b.putStringArray("selectedItems", outputStrArr);
// Add the bundle to the intent.
intent.putExtras(b);
// start the ResultActivity
startActivity(intent);
}
I have a result activity that is designed to collect the selected item and display it:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_midwife_result_list);
Bundle b = getIntent().getExtras();
String[] resultArr = b.getStringArray("SelectedItems");
ListView lv = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, resultArr);
lv.setAdapter(adapter);
}
When I run the program, I can see the listItem results, but when I select one the program stops, and there is this error:
Unable to start activity ComponentInfo{android.bignerdranch.com.mobilemidwife/android.bignerdranch.com.mobilemidwife.MidwifeResultList}: java.lang.NullPointerException: storage == null
pointing to this line of code:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, resultArr);
The code seems to be right...why would there be a null value on resultArr?
b.putStringArray("selectedItems", outputStrArr);
...
String[] resultArr = b.getStringArray("SelectedItems");
You have a typo, in one place you write "selectedItems" and in another you write "SelectedItems". Notice the first letter is capitalized in one but not the other. You should change them to be the same.
I am having a difficulty upon converting arraylist to hashSet. I dont have knowledge about HashSet that why I use ArrayList. I've read some about it but understand none. I am here trying to get some help about my problem.
All I wanted is to NOT DUPLICATE the words entered in my app's ListView. Here's my code. Please bear with it. I've seen some questions too here but it got me a lot more confused. Please be nice.
P.S. My first try :)
ArrayAdapter<String> adapter;
//onCreate
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>());
wordList.setAdapter(adapter);
//SEARCH
public void viewWord(View view) {
s1 = search.getText().toString();
s2 = dbHelper.getData(s1);
if (optionTxtView == 0) {
tv2.setText(s2);
optionTxtView = 1;
} else {
if (optionTxtView == 1) {
tv3.setText(s2);
optionTxtView = 1;
}
}
adapter.add(text.getText().toString());
adapter.notifyDataSetChanged();
ListView works by returning data based on position. Sets do not have a notion of position; you have to iterate over the Set to find the element you want.
On the other hand, Lists do have a notion of position, this is why they play nicely with ListView and the BaseAdapter class.
Adding ArrayList elements to a HashSet (Note: use LinkedHashSet if the order of elements matters):
ArrayList<String> list = new ArrayList<String>();
HashSet<String> set = new HashSet<String>();
list.add("Hello");
list.add("Hello");
list.add("World!");
System.out.println(list); // [Hello, Hello, World!]
set.addAll(list);
System.out.println(set); // [Hello, World!]
Using your code, maybe you could try something like:
ArrayAdapter<String> adapter;
//onCreate
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>());
HashSet<String> noDupesSet = new HashSet<String>();
noDupesSet.addAll(wordlist);
wordlist.clear();
wordlist.addAll(noDupesSet);
wordList.setAdapter(adapter);
//SEARCH
public void viewWord(View view) {
s1 = search.getText().toString();
s2 = dbHelper.getData(s1);
if (optionTxtView == 0) {
tv2.setText(s2);
optionTxtView = 1;
} else {
if (optionTxtView == 1) {
tv3.setText(s2);
optionTxtView = 1;
}
}
adapter.add(text.getText().toString());
adapter.notifyDataSetChanged();
ListViews have always been my weak point and right now I am practicing putting a Listview, within a Listview. Anyway, I first call my ListView at the start of my program and it loads it with an array saved in my strings.xml:
String[] departments = getResources().getStringArray(
R.array.departments_array);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item,
departments));
setContentView(R.layout.main);
ListView lv = getListView();
lv.setTextFilterEnabled(true);
What I want to do is update this ListView with a new array of values each time a list item is clicked. The reason why I am trying to do it this way is because I plan on having 27 different arrays with different values for each position, and I feel it would be lighter on my resources if instead of making a ListView for each array of items, I would update this one ListView. I know I am probably not doing this the most efficient way, but if there is another way of implementing my idea please tell me.
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
switch (position) {
case 0:
try {
//It is here that i dont know what to do, I was going to call
//the Listview the same way i did previously using my setlistadapter,
//but i kept getting errors about the code being undefined
String[] listitems1 = getResources().getStringArray(
R.array.items_array);
} catch (ClassCastException e) {
Toast.makeText(getApplicationContext(), "Error",
Toast.LENGTH_SHORT).show();
}
break;
case 1:
try {
//The listview will be changed again here
} catch (ClassCastException e) {
Toast.makeText(getApplicationContext(), "Error",
Toast.LENGTH_SHORT).show();
}
break;
}
};
});
Have you thought of using a BaseAdapter and setting it as the list adapter
http://developer.android.com/reference/android/widget/BaseAdapter.html
Your approach is wrong( if I understand what are you doing). Instead of replacing the adapter of the ListView every time the user clicks(and simply setting a new adapter should work) a element in the initial list you should start a new activity passing the clicked position and in your new activity set the adapter on a ListView with the correct array based on that position.
A small example:
Main class:
/**
* The main class with the initial 27 items array.
*/
public class Class1 extends ListActivity {
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// start the second activity that will show our array depending on the
// position clicked
Intent i = new Intent(this, Class2.class);
// put the position in the Intent so we can know in the other activity
// what array to load.
i.putExtra("pos", position);
startActivity(i);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I just used a simple array of 2 items, you'll load your 27 items
// array
String[] items = { "1", "2" };
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, items));
}
}
Secondary activity that will show the array based on the previously selected position:
public class Class2 extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get the Intent that started the activity
Intent i = getIntent();
// find out what position did that other activity send to us.
int position = i.getIntExtra("pos", -1);
// load the ListView with an adapter based on the array that you
// want(according to that position)
if (position == 0) {
// the first element in the main list
String[] items = getResources().getStringArray(R.array.a1);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, items));
} else if (position == 1) {
// the second element in the main list
String[] items = getResources().getStringArray(R.array.a2);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, items));
} else {
// etc
}
}
}
Luksprog's answer is indeed correct, and it is very useful for lists many levels deep (you do not put limits, just keep spawning new activity instances with the proper list loaded)
BUT
If your list isn't more than 2 levels deep you can use ExpandableListActivity instead of ListActivity which is basically an enhanced version of the single-level list you're using which natively handle group collapsing/expanding and therefore you do not need the spawn of a new activity for each sublevel.
again note that this approach works only for lists which do not go deeper than 2 levels
ExpandableListActivity documentation
ExpandableListView documentation
ExpandableListAdapter documentation - you should be fine with the BaseExpandableListAdapter implementation
And here you have some nice example from Google itself:
public class ExpandableList3 extends ExpandableListActivity {
private static final String NAME = "NAME";
private static final String IS_EVEN = "IS_EVEN";
private ExpandableListAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();
for (int i = 0; i < 20; i++) {
Map<String, String> curGroupMap = new HashMap<String, String>();
groupData.add(curGroupMap);
curGroupMap.put(NAME, "Group " + i);
curGroupMap.put(IS_EVEN, (i % 2 == 0) ? "This group is even" : "This group is odd");
//filling with dummy data...
List<Map<String, String>> children = new ArrayList<Map<String, String>>();
for (int j = 0; j < 15; j++) {
Map<String, String> curChildMap = new HashMap<String, String>();
children.add(curChildMap);
curChildMap.put(NAME, "Child " + j);
curChildMap.put(IS_EVEN, (j % 2 == 0) ? "This child is even" : "This child is odd");
}
childData.add(children);
}
// Set up our adapter
mAdapter = new SimpleExpandableListAdapter(
this,
groupData,
android.R.layout.simple_expandable_list_item_1,
new String[] { NAME, IS_EVEN },
new int[] { android.R.id.text1, android.R.id.text2 },
childData,
android.R.layout.simple_expandable_list_item_2,
new String[] { NAME, IS_EVEN },
new int[] { android.R.id.text1, android.R.id.text2 }
);
setListAdapter(mAdapter);
}
}