I'm trying this example for creating a simpleAdapter for a ListView. So, I got all created but when I change this line
List<Movie> movies = getData2();
ListAdapter adapter = new MovieListAdapter(this, movies, android.R.layout.simple_list_item_2, new String[]{Movie.KEY_NAME, Movie.KEY_YEAR}, new int[]{android.R.id.text1, android.R.id.text2});
I got this error:
The constructor is undefined
MovieListAdapter(ImdbApiActivity, List<Movie>, int, String[], int[])
It's the same example, I've just changed Cars for Movies. I know that this example is from 2009, my target is 2.1 on my project. Is there a incompatibility between versions or is there an error?
My simpleadapter class looks like this:
public class MovieListAdapter extends SimpleAdapter {
private List < Movie > movies;
private int[] colors = new int[] {
0x30ffffff, 0x30808080
};
#SuppressWarnings("unchecked")
public MovieListAdapter(Context context, List <? extends Map < String, String >> movies,
int resource,
String[] from,
int[] to) {
super(context, movies, resource, from, to);
this.movies = (List < Movie > ) movies;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
int colorPos = position % colors.length;
view.setBackgroundColor(colors[colorPos]);
return view;
}
}
Is there an error i'm missing? which is the "modern" way to achieve this?
Edit: Neither changing the context parameter or the List worked for this example. My Movie class extends from Hashmap. Any other idea? thanks!
import java.util.HashMap;
public class Movie extends HashMap {
public String year;
public String name;
public static String KEY_YEAR = "year";
public static String KEY_NAME = "name";
public Movie(String name, String year) {
this.year = year;
this.name = name;
}
#Override
public String get(Object k) {
String key = (String) k;
if (KEY_YEAR.equals(key))
return year;
else if (KEY_NAME.equals(key))
return name;
return null;
}
}
It seems to be problem in the parameter of your custom adapter class constructor.
You have defined it as List<? extends Map<String, String>> movies where you are passing List<Movies> object from the activity.That is why it is telling you,such constructor is not defined.
Try changing parameter of constuctor to List<Movies> movies,that would resolve your problem,i think!
Try changing
`ListAdapter adapter = new MovieListAdapter(this, movies, android.R.layout.simple_list_item_2, new String[]{Movie.KEY_NAME, Movie.KEY_YEAR}, new int[]{android.R.id.text1, android.R.id.text2});`
to
`ListAdapter adapter = new MovieListAdapter(YourClass.this, movies, android.R.layout.simple_list_item_2, new String[]{Movie.KEY_NAME, Movie.KEY_YEAR}, new int[]{android.R.id.text1, android.R.id.text2});`
because this may be referencing to the different instance.
YourClass.this is a reference to an instance of the YourClass.class. You can also send context returned by getApplicationContext()
Related
in my android project,
i am getting a list of data in arraylist
ArrayList<Items> item = db.getAllMenu();
but now i want to add this data into listview,
i tried as,
ListView lv=(ListView)findViewById(R.id.list_view_inside_nav);
String[] lv_arr = {};
lv_arr = (String[]) item.toArray();
lv.setAdapter(new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, lv_arr));
but its giving error.because i am trying to convert arratlist to string..
anyone plz help me, how to convert the arraylist to string[]
here are my some files...
items.java (getter and setter methods)
public class Items {
//private variables
String _name;
// Empty constructor
public Items(){
}
// constructor
public Items(String name){
this._name = name;
}
// getting name
public String getName(){
return this._name;
}
// setting name
public void setName(String name){
this._name = name;
}
}
and i am using this code to get data from database
public ArrayList<Items> getAllMenu() {
ArrayList<Items> passList = new ArrayList<Items>();
// Select All Query
String selectQuery = "SELECT * FROM " + CATEGOTY_TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Items menu = new Items();
menu.setName(cursor.getString(0));
// Adding category to list
passList.add(menu);
} while (cursor.moveToNext());
}
// return category list
return passList;
}
Your problem here is that you are trying to convert a List into an Array, this can't be done with a cast but methods exist.
The easiest would be to convert the list into an Array using the methods List.toArray(E[]).
ArrayList<Items> items = db.getAllMenu();
Items[] itemsArray = new Items[items.size()]; //Create the array to the correct size,
itemsArray = items.toArray(itemsArray); //Fill the array with the list data
//you could cast into Item[] directly but this is cleaner
Help to use here : Convert ArrayList<String> to String[] array
The array need to be an array of Items
Then, if you have override the toString methods of your Item class to return the String like you want.
public class Items {
...
#Override
public String toString(){
this.getName() //Just an example ;)
}
...
}
This will work like a charm. The adapter use this method to get the String to print.
EDIT :
After some research, you don't even need to create an array. ArrayAdapter accept an List so you only need to override Items.toString()
https://developer.android.com/reference/android/widget/ArrayAdapter.html
You can see here the need to override the toString
However the TextView is referenced, it will be filled with the toString() of each object in the array. You can add lists or arrays of custom objects. Override the toString() method of your objects to determine what text will be displayed for the item in the list.
And here is the constructor to use
ArrayAdapter (Context context,
int resource,
List objects)
So just create your adapter like this :
new ArrayAdapter<Items>(MainActivity.this,
android.R.layout.simple_list_item_1, item);
You have to make arraylist of object to do such thing here is a piece of my code that i use
My ArrayList
private ArrayList<Mediafileinfo> songList = new ArrayList<Mediafileinfo>();
Adding data in the arraylist object.
Mediafileinfo info = new Mediafileinfo();
info.setFile_uri(Uri.parse(audioCursor.getString(audiodata)));
info.setName(audioCursor.getString(audioTitle));
info.setDuration(audioCursor.getLong(audioduration));
info.setAlbum(audioCursor.getString(audioalbum));
info.setAlbum_Art_uri(ContentUris.withAppendedId(albumArtUri, audioCursor.getLong(audioalbumid)));
songList.add(info);
Make a class with getter and setter
public class Mediafileinfo {
private String name,album,artist;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
}
And call in your arraylist adapter like this
Mediafileinfo mediafileinfo = (Mediafileinfo) getItem(position);
TextView textView = (TextView) view.findViewById(R.id.textView);
textView.setText(mediafileinfo.getAlbum());
and rest will be the same
you can set the arraylist in your adapter like this
new CustomAdapter(this,songlist)
Hope this will help you.For more info
Wrong.
Items class cannot convert to a String class.
You need to convert each Items to String object.
Example :
Say your class Item
class Items{
public String itemName;
}
In your code change
String[] lv_arr = new String[items.size()];
for(int i=0;i<items.size();i++){
lv_arr[i]=item.get(i);
}
lv.setAdapter(new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, lv_arr));
let listobj be a list of object you want toset for your listView and Lv be your listview
use following code:
LV.setAdapter(new ArrayAdapter<>(getContext(),android.R.layout.simple_list_item_1 ,sensors));
update
if you want each item of your LisView represent a specific object you could also populate it with a custom adaptor like this :
first in your java files define new javaclass that extends BaseAdaptor
public class SensorAdaptor extends BaseAdapter{
private final Context context;
private final List<Sensor> sensors;
public SensorAdaptor(Context context , List<Sensor> sensors){
this.context = context;
this.sensors = sensors;
}
#Override
public int getCount() {
return sensors.size();
}
#Override
public Object getItem(int position) {
return sensors.get(position);
}
#Override
public long getItemId(int position) {
return sensors.get(position).getType();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_sensors, null);
} else {
view = convertView;
}
TextView listName = view.findViewById(R.id.txtSensorList);
listName.setText(sensors.get(position).getName());
return view;
}
}
attention in my case i want each item of listView represent a Sensor object
then in layout file in res/layout define a layout for this adaptor to use
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/**txtSensorList**"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
and then in yor activity
List<Sensor> sensors = mgr.getSensorList(Sensor.TYPE_ALL);
LV.setAdapter(new SensorAdaptor(getContext(),sensors));
attention
in my case i want to show a list of sensor Object
I am working on a project that gets queries from a database on a remote server. The SQL side of it gets information from two separate tables, combines them and sends a JSON encoded string back me. I then parse the string and create an ArrayList with a HashMap of String, String to hold the data. All of this works just fine. There are 108 entries and all the related variables show this.
My problem arises when I try and put the final ArrayList HashMap into a listView. I have created a custom layout that I know works as I use to populate it from a set of arrays through the use of a dataprovider class and a custom adapter.
I followed a tutorial to create a custom adapter for the ArrayList HashMap (http://techlovejump.com/android-multicolum-listview/) . It appears to work except it will only pull 10-12 of the Items from the ArrayList HashMap, and then repeat. It does have exactly 108 items in the list. I notice that the first item in the list that is just off of the screen changes to different items as I scroll though the list.
I have debugged the code in the custom adapter class and everything is working fine the position starts at 0 and goes up. I have mostly seen it go to 10, once or twice 12. At this point on the next time through the getView method the position is returned to 0 and it starts over.
I am just learning all this and probably doing something wrong just don't know what. Here is the code I have to call the the custom adapter class and the class itself.
Custom Adapter this called from the method that parses my JSON string and builds the original ArrayList HashMap
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Created by jokerfwb on 11/12/15.
*/
public class UsersmyListAdapter extends BaseAdapter {
private static final String TAG_NAME = "Name";
private static final String AGE ="UserAge";
private static final String CLASS = "Class";
private static final String LEVEL = "Level";
private static final String SKILL = "Skill";
private static final String ACTIVITY = "Activity";
private static final String TIME_STAMP = "TimeStamp";
private static final String TAG_IN_GROUP = "InGroup";
public ArrayList<HashMap<String, String>> myList;
Activity activity;
TextView name;
TextView classType;
TextView skill;
TextView activityType;
public UsersmyListAdapter(Activity activity, ArrayList<HashMap<String, String>> myList){
super();
this.activity = activity;
this.myList = myList;
}
#Override
public int getCount(){
return myList.size();
}
#Override
public Object getItem(int position){
return myList.get(position);
}
#Override
public long getItemId(int position){
return 0;
}
public View getView(int position ,View convertView, ViewGroup parent){
LayoutInflater inflater = activity.getLayoutInflater();
if(convertView == null){
convertView = inflater.inflate(R.layout.users_lfg_list_item,null);
name = (TextView) convertView.findViewById(R.id.name);
classType = (TextView) convertView.findViewById(R.id.classType);
skill = (TextView) convertView.findViewById(R.id.skill);
activityType = (TextView) convertView.findViewById(R.id.activityType);
}
HashMap<String, String> map = myList.get(position);
name.setText(map.get(TAG_NAME));
classType.setText(map.get(CLASS));
skill.setText(map.get(SKILL));
activityType.setText(map.get(ACTIVITY));
return convertView;
}
}
The call from my activity to the Custom Adapter this gets called at the end of the method that parses the JSON string pulled by my AsyncTask
UsersLFGListAdapter adapter = new UsersLFGListAdapter(this, UsersLFG);
listView.setAdapter(adapter);
Found a solution as well
The answer from Varzaru worked wonderfully. I also found another solution after much more googling. Just wanted to post it for anyone else that sees this. It is as follows
impleAdapter UserArrayList = new SimpleAdapter(UsersLFGListActivity.this, UsersLFG, R.layout.users_lfg_list_item, new String[] {TAG_DESTINY_USER_NAME, TAG_ACTIVE_CLASS, TAG_ACTIVE_CLASS_LIGHT, TAG_ACTIVITY_TYPE}, new int[]{R.id.name, R.id.Class, R.id.Light, R.id.activityType});
listView.setAdapter(UserArrayList);
Well without seeing your other class I can take a shot at this. First your Listview adapter is not good, try this one:
public class UsersmyListAdapter extends ArrayAdapter<HashMap<String, String>> {
private static final String TAG_NAME = "Name";
private static final String AGE ="UserAge";
private static final String CLASS = "Class";
private static final String LEVEL = "Level";
private static final String SKILL = "Skill";
private static final String ACTIVITY = "Activity";
private static final String TIME_STAMP = "TimeStamp";
private static final String TAG_IN_GROUP = "InGroup";
public ArrayList<HashMap<String, String>> myList;
Activity activity;
public UsersmyListAdapter(Activity activity, ArrayList<HashMap<String, String>> myList){
super(activity, R.layout.users_lfg_list_item, myList);
this.activity = activity;
this.myList = myList;
}
#Override
public int getCount(){
return myList.size();
}
#Override
public Object getItem(int position){
return myList.get(position);
}
#Override
public long getItemId(int position){
return 0;
}
public View getView(int position ,View convertView, ViewGroup parent){
HashMap<String, String> map = myList.get(position);
ItemViewHolder viewHolder;
if(convertView == null){
viewHolder = new ItemViewHolder();
convertView = activity..getLayoutInflater().inflate(R.layout.users_lfg_list_item, null, true);
viewHolder.name = (TextView) convertView.findViewById(R.id.name);
viewHolder.classType = (TextView) convertView.findViewById(R.id.classType);
viewHolder.skill = (TextView) convertView.findViewById(R.id.skill);
viewHolder.activityType = (TextView) convertView.findViewById(R.id.activityType);
convertView.setTag(viewHolder);
} else {
viewHolder = (ItemViewHolder) convertView.getTag();
}
viewHolder.name.setText(map.get(TAG_NAME));
viewHolder.classType.setText(map.get(CLASS));
viewHolder.skill.setText(map.get(SKILL));
viewHolder.activityType.setText(map.get(ACTIVITY));
return convertView;
}
public class ItemViewHolder {
TextView name;
TextView classType;
TextView skill;
TextView activityType;
}
}
Second you should never set the Listview adapter on your complete method of AsyncTask. You should set the adapter on create after you declare the listview and when the AsyncTask finishes then add the new items to the list and call:
adapter.notifyDataSetChanged();
Hope it helps with your issue!
May i know how to get HashMap item from a custom adapter
Code:
ArrayList<HashMap<String, String>> feeds_List;
...
...
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put("username", usr_name);
map.put("datetime", feed_date);
map.put("pts", point_txt);
map.put("pic", pic);
// adding HashList to ArrayList
feeds_List.add(map);
ListAdapter adapter = new ExtendedSimpleAdapter(
getActivity(), feeds_List,
R.layout.feed_item, new String[]{"username", "datetime", "pts"},
new int[]{R.id.usr_name, R.id.feed_time, R.id.no_stamp});
setListAdapter(adapter);
My Custom Adapter:
public class ExtendedSimpleAdapter extends SimpleAdapter{
Context context2;
public ExtendedSimpleAdapter(Context context, List<? extends Map<String, String>> data, int resource, String[] from, int[] to){
super(context, data, resource, from, to);
context2=context;
}
public View getView(int position, View convertView, ViewGroup parent){
// here you let SimpleAdapter built the view normally.
View v = super.getView(position, convertView, parent);
// Then we get reference for Picasso
ImageView img = (ImageView) v.getTag();
if(img == null){
img = (ImageView) v.findViewById(R.id.usr_pic);
v.setTag(img); // <<< THIS LINE !!!!
}
// get the url from the data you passed to the `Map`
String TAG_IMAGE="pic";
String url = ((Map)getItem(position)).get("pic");
// do Picasso
// maybe you could do that by using many ways to start
Picasso.with(context2)
.load(url)
//.resize(100, 100)
.into(img);
// return the view
return v;
}
}
Here is the problem:
I cannot get the url string in the custom adapter.
always getting errors of
"Incompatible types"(needed String, but found is object)
for this line
String url = ((Map)getItem(position)).get("pic");
The object you are casting against, should have the exact type. Casting to the generic Map doesn't enforce the compile time check, that the generics are meant for.
String url = ((Map<String, String>)getItem(position)).get("pic");
Use
private ArrayList<Map<String, String>> data;
Map<String, String> category = new Map<String, String>();
category = data.get(position);
String url=category.get("pic");
Simply change this
String url = ((Map)getItem(position)).get("pic");
to
String url = list.get(position).get("pic");
Also here
Context context2;
List<HashMap<String, String>> list;
public ExtendedSimpleAdapter(Context context, List<HashMap<String, String>> data, int resource, String[] from, int[] to){
super(context, data, resource, from, to);
context2=context;
this.list = data;
}
CustomListAdapter Class:
its like example for problem;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final List<FixtureData> list;
public CustomList(Activity context,List<FixtureData>list) {
super(context, R.layout.list_single);
this.context = context;
this.list = list;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.list_single, null, true);
TextView txt_date = (TextView) rowView.findViewById(R.id.txt_date);
TextView txt_team1 = (TextView) rowView.findViewById(R.id.txt_team2);
TextView txt_team2 = (TextView) rowView.findViewById(R.id.txt_team1);
txt_date.setText(list.get(position).date.toString());
txt_team1.setText(list.get(position).team1.toString());
txt_team2.setText(list.get(position).team2.toString());
return rowView;
}
}
MainActivity Class:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
public List<FixtureData> fixtureArray = new ArrayList<FixtureData>();
class FixtureData extends Object{
public String date=null;
public String team1=null;
public String team2=null;
}
FixtureData fixture = new FixtureData();
fixture.date="1990";
fixture.team1="Manchester";
fixture.team2="Barcelona";
fixtureArray.add(fixture);
final CustomList adapter2 = new CustomList(MainActivity.this, fixtureArray);
liste=(ListView)findViewById(R.id.list1));
liste.setAdapter(adapter2);
liste.setItemsCanFocus(true);
liste.setFocusable(false);
liste.setFocusableInTouchMode(false);
liste.setClickable(false);
}}
its just example for problem, dont check intention.
When i use single ArrayList my Codes Working like;
final List<String> date = new ArrayList<String>();
final List<Integer> team1= new ArrayList<String>();
final List<Integer> team2= new ArrayList<String>();
but when i tried custom ArrayList like this, its not working
public List<FixtureData> fixtureArray = new ArrayList<FixtureData>();
class FixtureData extends Object{
public String date=null;
public String team1=null;
public String team2=null;
}
FixtureData fixture = new FixtureData();
fixture.date="1990";
fixture.team1="Manchester";
fixture.team2="Barcelona";
fixtureArray.add(fixture);
with this codes giving me null ListView,
How can i solve my problem?
Override the getCount method in your CustomList
#Override
public int getCount()
{
return list.size();
}
OR
change
super(context, R.layout.list_single);
to
super(context, R.layout.list_single,list);
Your first line of Program shows
public class CustomList extends ArrayAdapter< String >{
It should be :
public class CustomList extends ArrayAdapter< FixtureData >{
Your ListAdapter class should know about what type of Object its going to handle
It looks like there's a lot going on in your code, but in addition to what Brijesh mentioned about changing ArrayAdapter to ArrayAdapter, one other thing that seems to be happening is that you never set your list to your adapter. You send in your list, and call super(context, R.layout.list_single), but you didn't include your list in that call and don't separately set it later. In addition, although this is not the only way to deal with this issue, since you are using a custom list item view with multiple text views, it might be easier to just send a 0 as a placeholder for the layout resource - that's okay bc you define it later in getView(). The super constructor for ArrayAdapter expects a layout with one text view. You probably want to check out the android developer reference page for ArrayAdapter http://developer.android.com/reference/android/widget/ArrayAdapter.html so you can see what your options are and what is expected, but one option would be to just call super(context,0,list). BTW - if you want to use this.list, make sure to define it before you use it in the call to super, instead of after as you currently have it.
I'd like to map an Array of "complex" data to a ListView. In a very simplified form my data model would look like something like this:
class ListPlacesValues {
String idObject;
String name;
String city;
String country;
ArrayList<String> classification;
double distance_quantity;
DistanceUnit distance_unit;
[...more stuff ...]
}
I know that I can convert my complex data into a HashList and then just use a SimpleAdapter:
SimpleAdapter mAdapter = new SimpleAdapter(
this,
hashList,
R.layout.places_listitem,
new String[] { "name", "city", "country"},
new int[] { R.id.name, R.id.city, R.id.country}
);
However, I would rather use my data model directly, but I've no idea where and how to start, so that in the end I can do something like this:
ArrayList<ListPlacesValues> values = getData();
MyAdapter mAdapter = new MyAdapter(
this,
values,
R.layout.places_listitem,
ListPlacesValues { values.name, values.city, values.country},
new int[] { R.id.name, R.id.city, R.id.country}
);
Solution: I found this Android API sample (List14), which was really helpful.
You can extend ArrayAdapter. Here's code example for you. In this example - SearchItem is some custom POJO. Basically you need to override getView() method to build your row by inflating row layout and then populating values based on List of items and current position
class SearchItemsAdapter extends ArrayAdapter<SearchItem> {
Activity context;
List<SearchItem> items;
SearchHeader header;
#SuppressWarnings("unchecked")
public SearchItemsAdapter(final Activity context,
final Map<SearchHeader, List<SearchItem>> result) {
super(context, R.layout.item, (List) ((Object[]) result.values()
.toArray())[0]);
this.context = context;
this.header = result.keySet().iterator().next();
this.items = result.get(this.header);
}
#Override
public View getView(final int position, final View convertView,
final ViewGroup parent) {
final View view = this.context.getLayoutInflater().inflate(
R.layout.item, null);
final SearchItem item = this.items.get(position);
((TextView) view.findViewById(R.id.jt)).setText(item.jt);
((TextView) view.findViewById(R.id.dp)).setText(item.dp);
((TextView) view.findViewById(R.id.cn)).setText(item.cn);
((TextView) view.findViewById(R.id.loc)).setText(item.loc.name);
final TextView body = ((TextView) view.findViewById(R.id.e));
body.setText(item.e);
body.setTag(item.src[0]);
((TextView) view.findViewById(R.id.src)).setText(item.src[1]);
return view;
}
}
There is one pitfall with the convertView in the sample you linked
if(convertView != null){ //reuse
convertView.setAnimation(null);
convertView.setAnyCustomFieldsIdontWantFilledWithData(null);
}
you want to set all animations or unused fields to null otherwise your items might have data in them or animations pending you dont want.