Good morning, i'm retrieving some values from my MySQL database because i want to display them into a ListView with custom adapter. I have this code.
for(int i=0; i<jsonArray.length();i++) {
ogge = new Ogge();
json = jsonArray.getJSONObject(i);
ogge.title = json.getString("Title");
ogge.array = new String[] {json.getString("field1"), json.getString("field2"), json.getString("field3"), json.getString("field4"), json.getString("field5"), json.getString("field6")};
ogge.adapter = Ogge.MY_CUSTOM;
list.add(ogge);
}
This for is correct because the values are put in the array in Ogge class. This is the adapter
case Ogge.MY_CUSTOM:
view = inflater.inflate(R.layout.custom, null);
textView = (TextView)view.findViewById(R.id.textView1);
textView2 = (TextView)view.findViewById(R.id.textView2);
textView3 = (TextView)view.findViewById(R.id.textView3);
textView.setText(Html.fromHtml(ogge.title));
textView2.setText(MyJsonClass.DATABASE_FIELD[position]);
textView3.setText(ogge.array[position]);
break;
The problem is the follow: when i open my app i see only the first and the second value of ogge.array but i want to show all. If i make a for into the adapter to get the value from the array the values are all stored into the array so the array is correct but, then, why i show only the first two values and not all?
Adapter full code
public MyCustomAdapter(Context context, int resource, ArrayList<Ogge> list) {
super(context, resource, list);
// TODO Auto-generated constructor stub
this.context = context;
this.list = list;
}
#SuppressLint("CutPasteId")
#Override
public View getView(int position, View view, ViewGroup parent) {
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final Ogge ogge = list.get(position);
switch(ogge.adapter) {
case Ogge.MY_CUSTOM:
view = inflater.inflate(R.layout.custom, null);
textView = (TextView)view.findViewById(R.id.textView1);
textView2 = (TextView)view.findViewById(R.id.textView2);
textView3 = (TextView)view.findViewById(R.id.textView3);
textView.setText(Html.fromHtml(ogge.title));
textView2.setText(MyJsonClass.DATABASE_FIELD[position]);
textView3.setText(ogge.array[position]);
break;
}
return view;
}
#Override
public boolean isEnabled(int position) {
return false;
}
}
Related
I have a simple list view where each item is a view that has a title, from an ArrayList of strings and button, so that each entry in the ArrayList creates a new list item.
I also have another ArrayList of corresponding primary keys, which I want to use to delete specific items from an SQLite database but which isn't used in the list view(I don't want to display the ID's, but the strings that poplulate the list might not necessarily be unique so I can't use them to delete).
I have a onClick listener and method in the getView method for the list view, so that when someone clicks the delete button, I know the position in the list that the button was pressed in, so hopefully, I can then call a delete method on the database using id[position], however, I think due to the list view itself being created after the activity it's inside of, it can't resolve the id array, so I can't call delete.
public class TodayListActivity extends AppCompatActivity {
private ArrayList<String> names = new ArrayList<>();
FoodDB Db = null;
int deleteId;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todaylist);
ListView lv = (ListView) findViewById(R.id.today_meal_list);
Bundle a = this.getIntent().getExtras();
String[] id = a.getStringArray("idArray"); //used to delete
String[] mealNames = a.getStringArray("mealNamesArray"); //displayed
Collections.addAll(names, mealNames);
//call the list adapter to create views based off the array list 'names'
lv.setAdapter(new MyListAdapter(this, R.layout.list_item, names));
}
protected class MyListAdapter extends ArrayAdapter<String> {
private int layout;
private MyListAdapter(Context context, int resource, List<String> objects) {
super(context, resource, objects);
layout = resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
viewHolder viewholder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layout, parent, false);
viewholder = new viewHolder();
viewholder.title = (TextView) convertView.findViewById(R.id.report_meal_name);
viewholder.delButton = (Button) convertView.findViewById(R.id.button_delete_meal);
viewholder.delButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer)v.getTag();
//int deleteId derived from id[position]
deleteId = Integer.parseInt(id[position]);
idToDelete(deleteId);
//update the list view to exclude the deleted item
names.remove(position);
notifyDataSetChanged();
}
});
convertView.setTag(viewholder);
} else {
viewholder = (viewHolder) convertView.getTag();
}
//set string value for title
viewholder.title.setText(getItem(position));
viewholder.delButton.setTag(position);
return convertView;
}
}
public class viewHolder {
TextView title;
TextView delButton;
}
//delete from database
public void idToDelete(int DeleteId){
Db.deleteFoods(deleteId);
}
}
Any suggestions as to how or where to get either the position index out of the list view (to the activity, where the id array is) or get access to the id array inside the listview would be appreciated!
You can pass the id array to the MyListAdapter adapter, by changing this class' constructor to accept it as a parameter. Also, you are already passing the names list as a parameter, you should keep a reference to it so you can access it when the button is pressed.
Here is an example:
protected class MyListAdapter extends ArrayAdapter<String> {
private int layout;
private List<String> names;
private String[] ids;
private MyListAdapter(Context context, int resource, List<String> names, String[] ids) {
super(context, resource, names);
layout = resource;
this.names = names;
this.ids = ids;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
...
viewholder.delButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int deleteId = Integer.parseInt(ids[position]);// the "position" variable needs to be set to "final" in order to access it in here.
idToDelete(deleteId);
names.remove(position);
notifyDataSetChanged();
}
});
....
}
}
and here is how you can create an instance of this adapter:
lv.setAdapter(new MyListAdapter(this, R.layout.list_item, names, id));
I'm trying to inflate a list using baseadapter within an activity. The list just doesn't inflate. From the logs implemented within the class, the getView() function doesn't even execute. Here's the code. -
public class CallLog extends Activity {
ListView logList;
List mList;
Context mCtx;
ArrayList<String> logName;
ArrayList<String> logNumber;
ArrayList<String> logTime;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.reject_call_log);
mCtx = getApplicationContext();
ListView logList = (ListView) findViewById(R.id.log_list);
mList = new List(mCtx, R.layout.log_row);
logList.setAdapter(mList);
SharedPreferences savedLogName = PreferenceManager.getDefaultSharedPreferences(mCtx);
SharedPreferences savedLogNumber = PreferenceManager.getDefaultSharedPreferences(mCtx);
SharedPreferences savedLogTime = PreferenceManager.getDefaultSharedPreferences(mCtx);
try{
logName = new ArrayList(Arrays.asList(TextUtils.split(savedLogName.getString("logName", null), ",")));
logNumber = new ArrayList(Arrays.asList(TextUtils.split(savedLogNumber.getString("logNumber", null), ",")));
logTime = new ArrayList(Arrays.asList(TextUtils.split(savedLogTime.getString("logTime", null), ",")));
Collections.reverse(logName);
Collections.reverse(logNumber);
Collections.reverse(logTime);
}catch(NullPointerException e){
e.printStackTrace();
//TextView noLog = (TextView)findViewById(R.id.no_log);
}
}
public class List extends BaseAdapter {
LayoutInflater mInflater;
TextView nameText;
TextView numberText;
TextView timeText;
int timePos = 1;
public List(Context context, int resource) {
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (convertView == null) {
v = mInflater.inflate(R.layout.row, null);
}
nameText = (TextView) v.findViewById(R.id.log_name);
numberText = (TextView) v.findViewById(R.id.log_number);
timeText = (TextView) v.findViewById(R.id.log_time);
nameText.setText(logName.get(position));
numberText.setText(logNumber.get(position));
timeText.setText(logTime.get(timePos) + logTime.get(timePos+1));
Log.d("RejectCall", "ListView");
timePos+=2;
return v;
}
}
}
Where is it all going wrong? Also, is there a better way to do what I'm trying to do?
Please replace the following code :
#Override
public int getCount() {
return 0;
}
with
#Override
public int getCount() {
return logName.size();
}
As list view only show the numbers of rows that is returned by this method and right now you are returning 0;
And after fetching the data in arraylist please use adapter.notifyDataSetChanged() to notify the list view.
You have to call notifyDataSetChanged() as you are filling data in array list after setting the adapter. so to notify the list view that data has been changed you have to call notify method(as above)
Your getItem() and getCount() haven't been implemented. If you want any kind of adapter to work for the list, these need to be implemented. Your list is also not holding any actual data, so getItem() has nothing to set.
Don't forget to call notifiyDataSetChanged() in your adapter after you set appropriate implementations for the above two functions.
I'm trying to hide a adapter when my object "TuMesaModel" be a administrator, this is the code
public class TuMesaAdapter extends ArrayAdapter<TuMesaModel>{
private String _id;
public TuMesaAdapter(Context context, List<TuMesaModel> objects, String id) {
super(context, 0, objects);
_id = id;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent){
ViewHolder holder = null;
TuMesaModel entry = getItem(position);
String numero = "+"+entry.getUsername();
//Toast.makeText(getContext(), Settings.PREFERENCES.getString(Settings.PHONE_PREF, null), Toast.LENGTH_LONG).show();
if(convertView == null){
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.tumesa_user, parent, false);
holder = new ViewHolder();
holder.numero_personal_tu_mesa = (TextView) convertView.findViewById(R.id.numero_personal_tu_mesa);
holder.aceptar_y_rechazar_tu_mesa = (LinearLayout) convertView.findViewById(R.id.aceptar_y_rechazar_tu_mesa);
holder.foto_perfil_tu_mesa = (ImageView) convertView.findViewById(R.id.foto_perfil_tu_mesa);
holder.mRelative = convertView.findViewById(R.id.layout_tu_mesa);
Utils.setFontAllView((ViewGroup) holder.mRelative);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.numero_personal_tu_mesa.setText(entry.getUsername());
if(!entry.isAdmin()){
holder.mRelative.setVisibility(View.GONE);
//Toast.makeText(getContext(), Settings.PREFERENCES.getString(Settings.PHONE_PREF, null), Toast.LENGTH_LONG).show();
//Toast.makeText(getContext(), "Luego:"+numero, Toast.LENGTH_LONG).show();
}
return convertView;
}
private static class ViewHolder {
public View mRelative;
public TextView numero_personal_tu_mesa;
public LinearLayout aceptar_y_rechazar_tu_mesa;
public ImageView foto_perfil_tu_mesa;
}
}
In the mainActivity
Type collectionMesa = new TypeToken<Collection<TuMesaModel>>() {}.getType();
_response = new Gson().fromJson(reader, collectionMesa);
Log.i("TamaƱo response TuMesaActivity", _response.size()+"");
return null;
}
#Override
protected void onPostExecute(Void Void) {
super.onPostExecute(Void);
setSupportProgressBarIndeterminateVisibility(false);
_mesa_adapter = new TuMesaAdapter(TuMesaActivity.this, _response, _bundle.getString("_id"));
_list_view.setAdapter(_mesa_adapter);
_mesa_adapter.notifyDataSetChanged();
}
But when I run the function setVisible (View.Gone) is a space in the list corresponding to the adapter. What can I do to remove that space??
You can't do it in a clean way.
You must remove the non admin entries from your list, or create a list without those entries, and call notifyDataSetChanged.
Just filter the list in the constructor, something like this:
public TuMesaAdapter(Context context, List<TuMesaModel> objects, String id) {
super(context, 0);
final List<TuMesaModel> filtered = new ArrayList<TuMesaModel>();
for(final TuMesaModel object : objects) {
if(!object.isAdmin()){
filtered.add(object);
}
}
addAll(filtered);
_id = id;
}
see ArrayAdapter#addAll (since API level 11)
If you want to remove all the data from the list then pass an empty list and make the following calls as you did earlier.
_mesa_adapter = new TuMesaAdapter(TuMesaActivity.this, _response, _bundle.getString("_id"));
_list_view.setAdapter(_mesa_adapter);
_mesa_adapter.notifyDataSetChanged();
or you can also try setting list adapter to null as,
_list_view.setAdapter(null);
Lemme me know if this helps. :)
I have an app that loads data from a sqllite database, then converts the data to appropriate formats so it could pass on the data to fragment tabs.
Everything works fine except for the images.
In the DB images are stored in full path, for example R.drawable.muntjakas and the images are available in the resource drawable folder.
The app pulls the data from the db and then converts it to int format so it could be passed on. Eclipse is not giving me any errors, but when the app loads images are not displayed. My xml files have the image id set up and displays the images if I assign the values manually for example
flag = new int[] { R.drawable.muntjakas,.... };
What's the problem?
fragmenttab1.java class that loads data from sql and converts it:
public class FragmentTab1 extends SherlockFragment {
ListView list;
ListViewAdapter adapter;
private static final String DB_NAME = "animalsDB.sqllite3";
private static final String TABLE_NAME = "animals";
private static final String ANIMAL_ID = "_id";
private static final String ANIMAL_NAME = "name";
private static final String ANIMAL_PIC = "pic";
public static final String[] ALL_KEYS = new String[] {ANIMAL_ID, ANIMAL_NAME,ANIMAL_PIC };
private SQLiteDatabase database;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmenttab1, container,
false);
ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(getActivity(), DB_NAME);
database = dbOpenHelper.openDataBase();
Cursor cursor = getAllRows();
ArrayList<String> nameArray = new ArrayList<String>();
ArrayList<Integer> picArray = new ArrayList<Integer>();
for(cursor.moveToFirst(); cursor.moveToNext(); cursor.isAfterLast()) {
nameArray.add(cursor.getString(cursor.getColumnIndex(ANIMAL_NAME)));
picArray.add(cursor.getInt(cursor.getColumnIndex(ANIMAL_PIC)));
}
final String[] name = (String[]) nameArray.toArray(new String[nameArray.size()]);
final Integer[] pic = (Integer[]) picArray.toArray(new Integer[picArray.size()]);
final int[] flag = new int[pic.length];
for (int i = 0; i < pic.length; i++ ) {
flag[i] = pic[i];
}
// Locate the ListView in fragmenttab1.xml
list = (ListView) rootView.findViewById(R.id.listview);
// Pass results to ListViewAdapter Class
adapter = new ListViewAdapter(getActivity(), name, flag);
// Binds the Adapter to the ListView
list.setAdapter(adapter);
// Capture clicks on ListView items
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Send single item click data to SingleItemView Class
Intent i = new Intent(getActivity(), SingleItemView.class);
// Pass all data country
i.putExtra("country", name);
// Pass all data flag
i.putExtra("flag", flag);
// Pass a single position
i.putExtra("position", position);
// Open SingleItemView.java Activity
startActivity(i);
}});
return rootView;
}
public Cursor getAllRows() {
String where = null;
Cursor c = database.query(true, TABLE_NAME, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
}
My listViewAdapter.java class that should load the data on the screen:
package kf.kaunozoo;
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
String[] country;
int[] flag;
LayoutInflater inflater;
public ListViewAdapter(Context context, String[] country, int[] flag) {
this.context = context;
this.country = country;
this.flag = flag;
}
public int getCount() {
return country.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
// Declare Variables
TextView txtcountry;
ImageView imgflag;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.listview_item, parent, false);
// Locate the TextViews in listview_item.xml
txtcountry = (TextView) itemView.findViewById(R.id.country);
// Locate the ImageView in listview_item.xml
imgflag = (ImageView) itemView.findViewById(R.id.flag);
// Capture position and set to the TextViews
txtcountry.setText(country[position]);
// Capture position and set to the ImageView
imgflag.setImageResource(flag[position]);
return itemView;
}
}
What am I doing wrong? All answers are appreciated
I have had this problem once in one of my apps, however, what I did was, I saved unique ids for each drawable in database as I had limited images. While displaying I wrote a small function where I used switch statement to check for each id from database and then loaded images accordingly in ImageView.
However, when you have lots of images, try to use below function, where you can provide image names dynamically from database.
// image from res/drawable
int resID = getResources().getIdentifier("your_image_name",
"drawable", getPackageName());
Also, you may try the solution given at this blog.
I have a bit troublesome with view caching in listview (a.k.a convertView)
so here is my code,
private class CurrencyAdapter extends ArrayAdapter<CurrencyModel> {
Context ctx;
int layoutResourceId;
List<CurrencyModel> adapter_models = null;
public CurrencyAdapter(Context ctx, int layoutResourceId,
List<CurrencyModel> model) {
super(ctx, layoutResourceId, model);
this.ctx = ctx;
this.layoutResourceId = layoutResourceId;
adapter_models = model;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d(Constants.APP_TAG, "position: " + position);
View row = convertView;
CurrencyAdapterContainer holder = null;
if (row == null) {
Log.d(Constants.APP_TAG, "APP NULL");
row = ((Activity) ctx).getLayoutInflater().inflate(
layoutResourceId, parent, false);
holder = new CurrencyAdapterContainer();
holder.textView = (TextView) row
.findViewById(R.id.currencies_txt);
holder.imgView = (ImageView) row
.findViewById(R.id.currencies_flag_icon);
row.setTag(holder);
} else {
Log.d(Constants.APP_TAG, "APP NOT NULL");
holder = (CurrencyAdapterContainer) row.getTag();
}
CurrencyModel curr = getItem(position);
if (curr.currency_value == null) {
if (counter < MAX_COUNTER) {
++counter;
CurrencyJsonDownloader cDownloader = new CurrencyJsonDownloader(
curr, holder.textView); //download currency value in background, and set textview text if currency_value has been loaded in onpostExcecute (i'm using AsyncTask)
String url = CURRENCY_URL.replace("<symbol>", curr.symbol);
Log.d(Constants.APP_TAG, "Url currency: " + url);
cDownloader.execute(url);
}
holder.textView.setText("");
} else {
holder.textView.setText(curr.currency_value);
}
holder.imgView.setImageResource(curr.drawableId);
return row;
}
#Override
public CurrencyModel getItem(int position) {
// TODO Auto-generated method stub
return adapter_models.get(position);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return adapter_models.size();
}
}
static class CurrencyAdapterContainer {
ImageView imgView;
TextView textView;
}
and here is the output in my logcat
position : 0
APP NULL
position : 1
APP NOT NULL
position : 2
APP NOT NULL
position : 3
APP NOT NULL
.
.
.
position : 10
APP NOT NULL
which make a disaster because it means that the textview being passed in the background job is the same textview and the the changed view is the same textview and the other textview will have blank view unless i scroll it of course which call again the getView() and everything is fine. But it's a problem when starting the app, because just one textview that always changing its value.
so why is this happen? and is there any hack that i can do??
thanks before...
ListView item Views are recycled, so never hold a reference to a particular item view and expect it to represent same data after ListView has been scrolled.
Pass the data item to your worker task instead and let it update the data to it.
Updating:
If your current item is off screen, It'll be requested from adapter (
when ListView scroll to it), and will show updated data.
If that item is currently being displayed , call notifyDataSetChanged() on adapter, this will make ListView refresh its displayed items.
I think problem is with your List adapter. Here i had posted a adapter class i think it will help you.
public class UploadListAdaptor extends BaseAdapter {
private Context context;
private List<UploadDetailsObj> uploadList;
public UploadListAdaptor(Context context, List<UploadDetailsObj> list) {
this.context = context;
uploadList = list;
}
public int getCount() {
return uploadList.size();
}
public Object getItem(int position) {
return uploadList.get(position);
}
public long getItemId(int position) {
return position;
}
/** LIST CATEGORY */
public View getView(int position, View convertView, ViewGroup viewGroup) {
final UploadDetailsObj chlListObj = uploadList.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater
.inflate(R.layout.inflator_progress_bar, null);
TextView photoName = (TextView) convertView
.findViewById(R.id.tv_photoname);
Button btnProgress=(Button)convertView.findViewById(R.id.btn_progress);
photoName.setText(chlListObj.getPhotoName());
}
return convertView;
}
}
You can call this adapter by using this code.
List<UploadDetailsObj> listofUploads= new ArrayList<UploadDetailsObj>();
UploadListAdaptor uploadListAdptr = new UploadListAdaptor(yourclass.this,
listofUploads);
uploadListView.setAdapter(uploadListAdptr);