I have an empty string-array resource in my strings.xml file like below:
<string-array name="categories"/>
I'm getting array of data from an API back which I need to populate onto a listview. Its ArrayAdapter takes in an #ArrayResource int for its resource like below:
public void showListViewDialog(…, #ArrayRes int arrayResource) {
...
ListView listView = alertDialogView.findViewById(R.id.listViewCategories);
ArrayAdapter arrayAdapter = ArrayAdapter.createFromResource(context,
arrayResource, R.layout.custom_list_item);
listView.setAdapter(arrayAdapter);
}
In my Java class, this is how I am retrieving the string-array resource:
List<String> categoriesToAdd= Arrays.asList(getResources().getStringArray(R.array.categories));
How can I then add the data back to it? I've tried the following but it does not work:
List<String> listCategories = new ArrayList<>();
listCategories.add(categoriesToAdd);
It is not possible to alter the string-array resource at run-time. So you cannot update it to show data in a ListView.
You don't need a string-array resource to create an ArrayAdapter. Instead, you can simply pass an ArrayList to its constructor to create it.
For example:
List<String> data = new ArrayList<>();
// sample data
data.add("Data 1");
data.add("Data 2");
final ArrayAdapter<String> adapter = new ArrayAdapter<>(this /*context*/,
android.R.layout.simple_list_item_1, android.R.id.text1, data);
ListView listView = findViewById(R.id.listView);
listView.setAdapter(adapter);
Now if you want to add data to the list, use:
adapter.add("Data 3");
AFIK, Its not possible to change any resource files at runtime which bundled in APK. What you can do, just fetch your data from API and use it and if you want to save it for later use then save it in SharedPreferences file
Related
I have a Gridview with Images on it, and a search bar on the top of my page. I know how to use the search bar to filter text, but how can I filter images? Is there a way to somehow "tag" the images?
Thanks!
You must create a data model for your images and use an id to filter them.
public class MyDataModel {
int resourceId;
String imageName
public MyDataModel(String name, resourceId);
// constructors getters, setters, etc
}
And in your activity you can create a list with your data:
List<MyDataModel> data = new List();
data.add(new MyDataModel("name", R.drawable.name))
//import all your data
And then on your SearchView query listener add to filter to Adapter;
adapter.getFilter().filter(//name);
Create a list of names of images and for each item of the adapter you tag the names of the images. Now filter the adapter using the tags of the images. :)
I'm doing a small project as part of the Android course.
The app is supposed to retrieve the most popular movies using some site's API and then display them in a grid view (using posters as thumbnails).
When a specific movie is clicked a new activity will be started providing details.
I've gotten this far:
Obtained a list of most popular movies poster image URL's using the website's API.
Implemented an adapter extending ArrayAdapter which accepts ArrayList as the data source and loads the image from URL into ImageView item.
Populated the GridView using the adapter.
Setup listeners on Gridview using this code:
s:
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
//do stuff according to position/view
}
The info I need to pass onto the movie details activity when a movie is clicked can be obtained in step 1 (I just extracted the poster URLS from the json).
To be able to even provide information when a view is clicked I need to (at the very minimum) also extract the movie's ID and store it.
So as it seems my options are:
Store the IDs in the adapter. Then when a click occurs use getItem(position) to obtain the ID and send it with the intent. The next activity will then have to query the server for the movie details.
This means creating a class:
static class MovieItem {
int Id;
string posterUrl;
}
And converting the adapter to use ArrayList<MovieItem>.
Same as option 1 but instead use setTag to store the Id of the movie.
Same as option 1 but instead obtain all the required information (title, rating, plot, etc..) and store it to MovieItem. Query not required in the next activity.
Same as option 3 but instead use setTag (MovieItem). Query not required in the next activity.
I'm new to app development and I'm trying to get things done the right way, Would appreciate some help.
EDIT:
Also wanted to add, if I had stored additional movie information in the adapter would that not have been appropriate because the information isn't relevant to that class?
Thanks for your troubles! :)
When you first request the list of Movie info, you could store the details for each movie in something like a HashMap<String, HashMap<String, String>>, where the String is the movie id, and the Map is a set of Key/Value pairs for details information. Then, when a click comes through on your onClick, you would use the position to determine which movie poster was clicked. You would then retrieve the details HashMap for the selected movie, put it into a Bundle, pass it to the Intent of your new Activity, then retrieve it on the other side. So the code would look something like this:
When you first retrieve your list of movies, you would do something like this:
//You would put each set of movie data into a HashMap like this...
HashMap<String, HashMap<String, String>> movies = new HashMap<>();
HashMap<String, String> details = new HashMap<>();
details.put("dateReleased", "7.12.2015");
details.put("rating", "PG-13");
details.put("title", "Cool Awesome Movie");
movies.put("12345", details);
//Then when an onClick comes in, you would get the set of
//details for the movie that was selected (based on position)
HashMap<String, String> selectedDetails = movies.get("12345");
//Put the retrieved HashMap of details into a Bundle
Bundle bundle = new Bundle();
bundle.putSerializable("movieDetails", selectedDetails);
//Send the bundle over to the new Activity with the intent
Intent intent = new Intent(this, YourDetailsActivity.class);
intent.putExtras(bundle);
startActivity(intent);
Then when the new Activity starts, you would retrieve the details from the Bundle in your onCreate():
//Then in onCreate() of the new Activity...
Bundle bundle = getIntent().getExtras();
HashMap<String, String> movieDetails = (HashMap<String, String>) bundle.getSerializable("movieDetails");
String dateReleased = movieDetails.get("dateReleased");
String rating = movieDetails.get("rating");
String title = movieDetails.get("title");
I am trying to display a list in android using guidance from vogella's tutorial for sqlite in android :
this is part of my ProjectListDataSource class (This gets all data from the sqlite database):
public List<ProjectList> getAllProjects() {
List<ProjectList> projects = new ArrayList<ProjectList>();
Cursor cursor = database.query(ProjectListHelper.TABLE_PROJECT_LIST,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
projects.add(cursorToProjectList(cursor));
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
return projects;
}
private ProjectList cursorToProjectList(Cursor cursor) {
ProjectList projList = new ProjectList();
projList.setId(cursor.getLong(0));
projList.setProjName(cursor.getString(1));
projList.setProjComment(cursor.getString(2));
projList.setProjDateTime(cursor.getString(3));
return projList;
}
And this is my activity class :
public class ProjectListActivity extends ListActivity implements
OnClickListener {
private static final String TAG = "ProjectListActivity";
private ProjectListDataSource datasource;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_projectlist);
Log.d(TAG, "On Creat'd");
init();
}
private void init() {
// Getting data from database and adding to ListView
datasource = new ProjectListDataSource(this);
datasource.open();
List<ProjectList> values = datasource.getAllProjects();
ArrayAdapter<ProjectList> adapter = new ArrayAdapter<ProjectList>(this,
android.R.layout.simple_list_item_activated_1, values);
setListAdapter(adapter);
}
But on doing that I am getting unexpected result like this (see image) :
http://i.imgur.com/tQMooi8.png
But the database has records like this (see image):
http://i.imgur.com/HfY2azs.png
Can anyone please explain and give a solution as to why I cant get the list view to show the records as in the database...
Thanks,
Viney
Basic adapters, like ArrayAdapter or CursorAdapter, will map only one value to a single view. Here, a ProjectList object to a TextView with the id of android.R.id.simple_list_item_activated_1
You need a single layout(for a single view within the ListView) with multiple views to which you will map id, name, date, comment, etc. You need to extend one of the adapters. Preferably BaseAdapter or CursorAdapter.
There are several issues here, depending on what you want to display.
The reason you're seeing the object string reference in your list is because you're using a plain ArrayAdapter, which simply calls toString() on the objects in the array. If you override toString() in ProjectList, you can display what you want (though that's normally not the best way to solve this problem).
Another option which would allow you to keep using a plain ArrayAdapter would be to create an array of strings from the ProjectList objects of the data you want to display. A bit wasteful, but that's another option.
What you normally want to do is extend ArrayAdapter and override getView(). In getView() you assign the data you want to display in the view.
If you want to display all the data from your ProjectList objects in a single list item, you'll also need to create a custom layout to represent the row.
I have an android app with a screen that comprises of a ListView, which I am using to display a list of devices. These devices are held in an array.
I am trying to use the ArrayAdapter to display what is in the array on the screen in a list.
It works when I first load the SetupActivity class, however, there is the facility to add a new device in the addDevice() method, which means the array holding the devices is updated.
I am using notifyDataSetChanged() which is supposed to update the list but it doesn't seem to work.
public class SetupActivity extends Activity
{
private ArrayList<Device> deviceList;
private ArrayAdapter<Device> arrayAdapter;
private ListView listView;
private DevicesAdapter devicesAdapter;
private Context context;
public void onCreate(Bundle savedInstanceState) //Method run when the activity is created
{
super.onCreate(savedInstanceState);
setContentView(R.layout.setup); //Set the layout
context = getApplicationContext(); //Get the screen
listView = (ListView)findViewById(R.id.listView);
deviceList = new ArrayList<Device>();
deviceList = populateDeviceList(); //Get all the devices into the list
arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
listView.setAdapter(arrayAdapter);
}
protected void addDevice() //Add device Method (Simplified)
{
deviceList = createNewDeviceList(); //Add device to the list and returns an updated list
arrayAdapter.notifyDataSetChanged(); //Update the list
}
}
Can anyone see where I am going wrong?
For an ArrayAdapter, notifyDataSetChanged only works if you use the add, insert, remove, and clear functions on the Adapter.
Use clear to clear the adapter - arrayAdapter.clear()
Use Adapter.addAll and add the newly formed list - arrayAdapter.addAll(deviceList)
Call notifyDataSetChanged
Alternatives:
Repeat this step after new devicelist is formed - but this is
redundant
arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
Create your own class derived from BaseAdapter and ListAdapter that
gives you more flexibility. This is most recommended.
While the accepted answer solves the problem, the explanation of why is incorrect, and since this is an important concept I thought I'd attempt to clarify.
Slartibartfast's explanation that notifyDataSetChanged() only works when add, insert,remove, or clear is called on the adapter is incorrect.
That explanation is true of the setNotifyOnChange() method, which if set to true (as it is by default) will automatically call notifyDataSetChanged() when any of those four actions occur.
I think the poster confused the two methods. notifyDatasetChanged() itself does not have those restrictions. It just tells the adapter that the list it is looking at has changed, and it does not matter how the change to the list actually happened.
While I can't see the source code for your createNewDeviceList(), I would guess your problem came from the fact that you had the adapter referencing the original list you created, and then you created a new list in createNewDeviceList(), and since the adapter was still pointing to the old list it could not see the changes.
The solution slartibartfast mentioned works because it clears the adapter and specifically adds the updated list to that adapter. Thus you don't have the problem of your adapter pointing to the wrong place.
Hope this helps someone!
your method addDevice is causing an endless loop. Dont call a method from itself like you are doing here :
deviceList = addDevice();
Okay so i have a database, and i want it so you can favorite items.
Would i make it so you can save items then it will load it into a list view?
this is my load thing
//Calls the database, gets a list of names.
// if listofnames.size()==0 keep name, otherwise
// change name to first name.
ArrayList<String> nameList = new ArrayList<String>();
favList = db.getName();
if(favList.size()>0){
name.setText(favList.get(0));
But that just sets a text i want it to add items..
You may use ArrayAdapter or SimpleAdapter or BaseAdapter - through which you may bind dataSource (List<T>) to the ListView.
You can do this as follows
public class MyClass extends ListActivity{
public void onCreate(Bundle bundle){
//get the names from database
setListAdapter(new ArrayAdapter<E>(this,R.layout.xml_filename,your_list);
}
}
Remember in this case your xml file should be the TextView (I.e the items what list view should contain). You cannot pass an xml file with a ListView directly.
If you have still some problem, then post your code which can be solved.
You can follow the given link for more clarification.
http://developer.android.com/resources/tutorials/views/hello-listview.html