This question already has answers here:
JSON Android And Listview
(3 answers)
Closed 9 years ago.
I'm a new programmer and I'm making an app which can get data from MYSQL to php and then display on android. I've been trying to find a solution but none of the tutorials I've seen so far seems to work for me, I've only managed to get one object from json into a single textview. But what I really need is to get data to be displayed on individual rows on listview.
here's my JSON output,
[{"id":"1","name":"darrel","password":"pass1234"},{"id":"2","name":"garrett","password":"important"},{"id":"3","name":"neoys","password":"yseniopass"},{"id":"4","name":"john","password":"mikel123"},{"id":"5","name":"owen","password":"mike4l"}]
and my java code which gets only one of the users displayed onto a textview.
package com.darre.jsonreader;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ListActivity;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class Users extends ListActivity {
/** Called when the activity is first created. */
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#SuppressLint("NewApi")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//listView.setOnItemClickListener(new OnItemClickListener() {
// public void onItemClick(AdapterView<?> parent, View view,
// int position, long id) {
// When clicked, show a toast with the TextView text
// Toast.makeText(getApplicationContext(),
// ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://172.30.54.153/databases/");
TextView textView = (TextView)findViewById(R.id.textView1);
ListView listview = (ListView)findViewById(R.id.listView1);
try {
HttpResponse response = httpclient.execute(httppost);
String jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
JSONArray mArray = new JSONArray(jsonResult);
for (int i = 0; i < mArray.length(); i++) {
JSONObject object = mArray.getJSONObject(i);
String name = object.getString("name");
String password = object.getString("password");
textView.setText(name + " - " + password);
}
}
catch (JSONException e) {
e.printStackTrace();
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
Thanks in advance!!!
You can read this tutorial, it explains to ways of implement it, the first, a "direct" List adapter, the second, the way to customize your List.
http://www.mkyong.com/android/android-listview-example/
Also, you shouldn't work with JSON data, first, you have to create an Object for each Item, and then group it with some kind of List (ArrayList, for example).
You have to create ListView adapter:
Put this in your Code :
private String[] listArr;
public ArrayList<String> ary_name = new ArrayList<String>();
try {
HttpResponse response = httpclient.execute(httppost);
String jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
JSONArray mArray = new JSONArray(jsonResult);
for (int i = 0; i < mArray.length(); i++) {
JSONObject object = mArray.getJSONObject(i);
String name = object.getString("name");
String password = object.getString("password");
textView.setText(name + " - " + password);
ary_name.add(name);
}
listArr = new String[ary_name.size()];
listArr = ary_name.toArray(listArr);
MyArrayAdapter adapter = new MyArrayAdapter(this, listArr);
listView.setAdapter(adapter);
public class MyArrayAdapter extends ArrayAdapter<String> {
Activity context;
String[] listArr;
private TextView btnchkout;
// private final integer[] image;
public MyArrayAdapter(Activity context, String[] objects) {
super(context, R.layout.custmlayout, objects);
// TODO Auto-generated constructor stub
this.context = context;
listArr = objects;
}
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.custmlayout, null, true);
TextView textView = (TextView) view.findViewById(R.id.txtTicketNo);
textView.setText(listArr[position]);
return view;
}
}
If you want to use a ListView... then you should parse you JSON file into some kind of data structure like a List or an ArrayList and the n use an adapter to populate the ListView data.
Here is an example for ListView adapter:
private class MySecondAdapter extends ArrayAdapter<MiniTask>
{
private ArrayList<MiniTask> list;
public MySecondAdapter(Context context, int textViewResourceId, ArrayList<MiniTask> miniTaskList)
{
super(context, textViewResourceId, miniTaskList);
this.list = new ArrayList<MiniTask>();
this.list.addAll(miniTaskList);
}
public View getView(final int position, View convertView, ViewGroup parent)
{
miniTask = miniTaskList.get(position);
ViewHolder holder = new ViewHolder();
{
LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflator.inflate(R.layout.check_list_item_new, null);
holder.title = (TextView) convertView.findViewById(R.id.tvItemTitle);
holder.commentsPicturesButton = (ImageView) convertView.findViewById(R.id.iAddCommetOrPicture);
holder.commentsPicturesButton.setTag(position);
holder.commentsPicturesButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Intent intent = new Intent(getApplicationContext(), PicturesAndCommentsActivity.class);
intent.putExtra(TasksListActivity.KEY_ID, task.getId());
intent.putExtra("mini_task_text", miniTask.getTitle());
startActivity(intent);
}
});
holder.selected = (CheckBox) convertView.findViewById(R.id.cbCheckListItem);
holder.selected.setTag(position);
holder.selected.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
{
Log.d(TAG, "pressed the checkbox: " + v.getId() + " in position: " + position + " tag: " +v.getTag() +" and item from array: " + miniTaskList.get(position) );
CheckBox checkbox = (CheckBox) v;
miniTaskList.get(position).setSelected(checkbox.isChecked());
numOfCheckedMiniTasks = 0;
for(int i=0;i<miniTaskList.size();i++)
{
miniTask = miniTaskList.get(i);
if(miniTask.isSelected())
{
numOfCheckedMiniTasks ++;
}
}
int percent = (int)(numOfCheckedMiniTasks * 100.0f) / miniTaskList.size();
Log.d(TAG, "the percentage is: " +percent);
tasksRepository.get(tasksRepository.indexOf(task)).setMiniTasksPercentageComplete(percent);
}
}
});
}
holder.title.setText(miniTask.getTitle());
holder.selected.setChecked(miniTask.isSelected());
return convertView;
}
}
Check this tutorials for getting more information:
http://cyrilmottier.com/2012/02/16/listview-tips-tricks-5-enlarged-touchable-areas/
Related
I have been searching about this issue but still I am not very clear on how to use a click listener with an array adapter.
I need a click listener for each item of the list.
Codes:
The Area item:
package fogames.tamagomonsters;
public class Area {
public String name;
public String number;
public Area(String name, String number) {
this.name = name;
this.number = number;
}
}
The array adapter:
package fogames.tamagomonsters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class AreasAdapter extends ArrayAdapter<Area> {
public AreasAdapter(Context context, ArrayList<Area> Areas) {
super(context, 0, Areas);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Area Area = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_area, parent, false);
}
// Lookup view for data population
TextView tvname = (TextView) convertView.findViewById(R.id.tvName_area);
TextView tvnumber = (TextView) convertView.findViewById(R.id.tvNumber_of_beasts);
// Populate the data into the template view using the data object
tvname.setText(Area.name);
tvnumber.setText(Area.number);
// Return the completed view to render on screen
return convertView;
}
}
The activity:
package fogames.tamagomonsters;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ListView;
import java.util.ArrayList;
public class PlayMenuActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
FrameLayout fl = new FrameLayout(this);
fl.setBackgroundColor(Color.argb(255, 0, 0, 0));
// Construct the data source
ArrayList<Area> arrayOfAreas = new ArrayList<Area>();
// Create the adapter to convert the array to views
AreasAdapter adapter = new AreasAdapter(this, arrayOfAreas);
// Attach the adapter to a ListView
ListView lv = new ListView(this);
lv.setAdapter(adapter);
// Restore preferences
SharedPreferences prefs = getSharedPreferences(PreferenceConstants.PREFERENCE_NAME, MODE_PRIVATE);
int mlen = prefs.getInt(PreferenceConstants.MLEN, 0);
long money = prefs.getLong(PreferenceConstants.MONEY, 0);
int mall = 6; //hay que ver que hacer con esto...
int eqall = 3; //igual
boolean[] mgot = new boolean[mall];
int[] exp = new int[eqall];
int[] lvl = new int[eqall];
int[] at = new int[eqall];
int[] en = new int[eqall];
for (int i = 0; i < mall; i++) {
mgot[i] = prefs.getBoolean(PreferenceConstants.MGOT[i], false);
}
for (int i = 0; i < eqall; i++) {
exp[i] = prefs.getInt(PreferenceConstants.EXP[i], 0);
lvl[i] = prefs.getInt(PreferenceConstants.LVL[i], 0);
at[i] = prefs.getInt(PreferenceConstants.AT[i], 0);
en[i] = prefs.getInt(PreferenceConstants.EN[i], 0);
}
String name[] = {getString(R.string.a001)};
int prado_got = 0;
if (mgot[0]) {
prado_got += 1;
}
if (mgot[3]) {
prado_got += 1;
}
String prado = String.valueOf(prado_got) + " / 2";
String number[] = {prado};
// Add item to adapter
Area a001 = new Area(name[0], number[0]);
adapter.add(a001);
this.setContentView(fl);
}
}
Thank you in advance.
You can do something like that:
•First insert in your adapter this method
#Override
public Area getItem(int position) {
return [yourArrayAreas].get(position);
}
•Then, in your Activity...
final AreasAdapter adapter = new AreasAdapter(this, arrayOfAreas);
ListView lv = new ListView(this);
lv.setAdapter(adapter);
mListStopsMuni.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id{
Area yourClickArea = adapter.getItem(position);
//Rest of code...
}
});
Good luck ;)
Something like this:
ArrayList<Area> arrayListAreas;
public AreasAdapter(Context context, ArrayList<Area> Areas) {
super(context, 0, Areas);
this.arrayListAreas = Areas;
}
//And then....
#Override
public Area getItem(int position) {
return arrayListAreas.get(position);
}
After I create or receive a message send the message then save it to realm. Afterwards I need to update my threads ListView on the threads page and bring the newest messages to the top. I already have it so the thread list shows the updated preview and updated date, but it stays in it's inital ListView position. I tried to requery realm to get all info and reorder by the lastUpdated time, but it doesn't seem to work. Do I need to wipe the old thread list then repopulate it to get it to update?
I have the update triggered on the onResume()
#Override
protected void onResume() {
super.onResume();
updateListview = true;
updateList();
}
Here's my update
#UiThread
public void updateList() {
try {
if (updateListview) {
thread_realm = Realm.getInstance(this);
results = thread_realm.where(ZipListModel.class).findAllSorted("zipupdated", RealmResults.SORT_ORDER_DESCENDING);
adapter = new ZipListAdapter(this, results);
threadsListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
if (results.size()==0){
createZipHint.setVisibility(View.VISIBLE);
} else {
createZipHint.setVisibility(View.INVISIBLE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Adapter
package com.admin.zipline.adapters;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.admin.zipline.R;
import com.admin.zipline.activities.ZipListPage;
import com.admin.zipline.model.ZipListModel;
import org.androidannotations.annotations.ViewById;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ZipListAdapter extends ArrayAdapter<ZipListModel>
{
List<ZipListModel> items;
Context context;
Typeface semiBold;
Typeface light;
Typeface regular;
String[] months={};
public ZipListModel ziplist;
ArrayList<String> ziplistNames,ziplistParticipantsaids;
public ZipListAdapter(Context context, List<ZipListModel> threadslist) {
super(context,R.layout.zip_adapter_view,threadslist);
this.context = context;
this.items=threadslist;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
ViewHolder holder ;
if (view == null) {
holder =new ViewHolder();
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.zip_adapter_view, parent, false);
light = Typeface.createFromAsset(context.getAssets(), "ProximaNova-Light.otf");
regular = Typeface.createFromAsset(context.getAssets(), "ProximaNova-Regular.otf");
semiBold = Typeface.createFromAsset(context.getAssets(),"ProximaNova-Semibold.otf");
//TODO
/*for showing the author image
* */
//holder.thread_image = (ImageView)view.findViewById(R.id.author_avatar);
holder.thread_text = (TextView) view.findViewById(R.id.threadtext);
holder.thread_name = (TextView) view.findViewById(R.id.threadname);
holder.last_updated = (TextView) view.findViewById(R.id.lastupdated);
holder.zip_members=(TextView)view.findViewById(R.id.ziplist_members);
holder.thread_text.setTypeface(light);
holder.thread_name.setTypeface(semiBold);
holder.zip_members.setTypeface(regular);
view.setTag(holder);
}else{
holder =(ViewHolder)view.getTag();
}
try{
ziplist = items.get(position);
ziplistNames = new ArrayList<String>();
ziplistParticipantsaids=new ArrayList<>();
if (ziplist != null) {
if (ziplist.getMessagesListsmodel().first().getText()!=null){
holder.thread_text.setText(ziplist.getMessagesListsmodel().first().getText());
}
if (ziplist.getMessagesListsmodel().first().getCreatedAt()!=null){
holder.last_updated.setText(getDate(ziplist.getMessagesListsmodel().first().getCreatedAt()));
}
for (int i = 0; i < ziplist.getParticipantsmodel().size(); i++) {
ziplistNames.add(ziplist.getParticipantsmodel().get(i).getName());
ziplistParticipantsaids.add(ziplist.getParticipantsmodel().get(i).getParticipantId());
}
String members="";
for (int i=0;i<ziplistNames.size();i++){
members+=ziplist.getParticipantsmodel().get(i).getFirstName()+", ";
}
if (members.length() > 3){
members=members.substring(0,members.length()-2);
}
holder.zip_members.setText(members);
if(ziplist.getZipname().isEmpty()){
holder.thread_name.setText(members);
} else {
holder.thread_name.setText(ziplist.getZipname());
}
}
}
catch (Exception e){
e.printStackTrace();
}
view.setBackgroundColor(Color.parseColor(ziplist.getZipColor()));
return view;
}
String getDate(Date date) {
try {
Date d = date;
months=context.getResources().getStringArray(R.array.months);
return months[d.getMonth()] + " " + (d.getDate());
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public class ViewHolder{
ImageView thread_image;
TextView thread_text,thread_name,last_updated,zip_members;
// CardView cardView;
}
}
The question is not quite clear to me but i can suggest some common ways to do this.
Assume your ZipListModel defined like this:
public class ZipListModel extends RealmObject {
private String title;
private Date date;
private String Author;
... getters and setters...
}
The easiest way to show your models in the ListView is using RealmBaseAdapter. You can find document here. And example.
eg.:
public class ZipListAdapter extends RealmBaseAdapter<ZipListModel> implements ListAdapter {
public ZipListAdapter(Context context, int resId,
RealmResults<ZipListModel> realmResults,
boolean automaticUpdate) {
super(context, realmResults, automaticUpdate);
}
...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Update your views with the realmResults
...
ZipListModel zlm = realmResults.get(position);
authorTextView.setText(zlm.getAuthor);
...
}
...
}
The benifit of using RealmBaseAdapter is the realmResults can be updated automatically when the Realm transaction commited which means in your case, whenever you update your Realm by
thread_realm = Realm.getInstance(this);
thread_realm.beginTransaction()
// Change something in your Realm
...
thread_realm.commitTransaction()
The ZipListAdapter's notifyDataSetChanged will be called automatically and the listView will be updated.
BTW, you can still stay with your own adpater and simply update it by using RealmChangeListener. See example .
Try use RealmBaseAdapter.UpdateData(RealmResult<T> result). My project has similar requirement and it works for me
https://realm.io/docs/java/latest/api/io/realm/RealmBaseAdapter.html
I have the following code:
package com.example.myfirstapp;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
public class FetchData extends Activity {
private TextView textView;
private JSONObject jObject;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fetch_data);
textView = (TextView) findViewById(R.id.TextView1);
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
readWebpage(message);
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
mParseResponse(response);
}
#Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
public void readWebpage(String message) {
//Intent intent = getIntent();
//String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] {message});
}
ArrayList<String> year, title, details, director, rating, cover;
// For Parse Login Response From Server
public void mParseResponse(String response) throws UnknownHostException {
year=new ArrayList<String>();
title=new ArrayList<String>();
details=new ArrayList<String>();
director=new ArrayList<String>();
rating=new ArrayList<String>();
cover=new ArrayList<String>();
try {
JSONObject jObject = new JSONObject(response);
JSONObject jsonobjresults = jObject.getJSONObject("results");
JSONArray jsonarrayresult = jsonobjresults.getJSONArray("result");
for(int i=0;i<jsonarrayresult.length(); i++){
JSONObject mJsonObj = jsonarrayresult.getJSONObject(i);
year.add(mJsonObj.getString("year"));
title.add(mJsonObj.getString("title"));
details.add(mJsonObj.getString("details"));
director.add(mJsonObj.getString("director"));
rating.add(mJsonObj.getString("rating"));
cover.add(mJsonObj.getString("cover"));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am getting confused as to how to create a custom adapter. Yes, i have gone thoeugh tutorials but confusion still exits. Plus, I am having an error when i make a call to mParseResponse. Any ideas where I am going wrong and how should i implement list view?
Perhaps this simple sample custom adapter listview will get on your feet with this stuff.
The main activity
public class MainActivity extends Activity {
String [] children = {
"Award 1",
"Award 2",
"Award 3",
"Award 4",
"Award 5",
"Award 6",
"Award 7",
"Award 8",
"Award 9",
"Award 10",
"Award 11",
"Award 12",
"Award 13",
"Award 14",
"Award 15"};
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView list = (ListView) findViewById(R.id.listview);
CustomAdapter adapter = new CustomAdapter(this, children);
list.setAdapter(adapter);
}
The custom adapter
public class CustomAdapter extends BaseAdapter {
// you could have instead extend ArrayAdapter if you wished, i find it less fickle but less flexible
// extends CursorAdapter is available too for listviews backed by cursors
private LayoutInflater inflator;
private String[] children;
public CustomAdapter(Context context, String[] children) {
super();
// pass what you need into the constructor. in this case the string array and context.
// do as much as you can here and not in getView because getView acts for each row
// --> it will greatly help performance
this.children = children;
inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// v---- your listview won't show anything if this is left default (at 0).
return children.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// getView is where all the action takes place
// first inflate the xml that holds the row and somehow connect it to convertView, the parameter
// checking if null allows these views to be recycled when they go off-screen not just made one per row
// ---> it will greatly help performance
if (convertView == null) {
convertView = inflator.inflate(R.layout.row, parent, false);
}
// then find the individual views with this xml (everything just like onCreate)
ImageView img = (ImageView) convertView.findViewById(R.id.imageView1);
TextView tv = (TextView) convertView.findViewById(R.id.textView1);
// then perform your actions to the your views
// each textView is set to an element in the array based on position. this is my listview limiter here.
// each imageview is set to the same picture but you should now have an idea how to set different images (based on position)
// using listview position in correspondence with array/arraylist positions is a very useful technique.
img.setImageResource(R.drawable.ic_launcher);
tv.setText(children[position]);
// v---- return your view, it's important.
return convertView;
}
}
row.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="TextView" />
</RelativeLayout>
The result
To get super acquainted with listview check out this video:
http://www.youtube.com/watch?v=wDBM6wVEO70
As for your other issue, you're gonna have to post a logcat for better responses.
I have defined onCheckedChanged for the checkbox in my listview.
When i click on the check box to check / uncheck it this function is getting invoked.
But when i setthe state of the check box from code like
check.setChecked(true);
the onCheckedChanged is not getting invoked.
Please help.
Adapter file :
package com.idg.project.adapters;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.TextView;
import com.idg.project.R;
import com.idg.project.activities.ScanListActivity;
import com.idg.project.activities.SearchResultActivity;
import com.idg.project.adapters.WishListAdapter.ViewHolder;
import com.idg.project.entity.ScannedProduct;
public class ScanListAdapter extends BaseAdapter {
private Context context;
private List<ScannedProduct> productList;
protected LayoutInflater mInflater;
Button showOrHideButton;
static public int count = 0;
String barcodeForSelectedRow;
String formatForSelectedRow;
OnItemClickListener rowListener;
Activity parentActivity;
boolean isWishList;
public ScanListAdapter(Context context, List<ScannedProduct> objects,
Button button, Activity parentActivity) {
super();
this.productList = objects;
this.context = context;
this.mInflater = LayoutInflater.from(context);
showOrHideButton = button;
this.parentActivity = parentActivity;
this.isWishList = isWishList;
}
public int getCount() {
return productList.size();
}
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
#Override
public void notifyDataSetChanged() {
// TODO Auto-generated method stub
super.notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final int pos = position;
Log.i("checkboxflag at : ", pos+"is"+(productList.get(pos).getCheckboxflag()));
Log.i("getview : fresh", "getview"+pos);
convertView = mInflater.inflate(R.layout.product_list_row, null);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.productid);
holder.text1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(parentActivity,
SearchResultActivity.class);
intent.putExtra("barcode", productList.get(pos)
.getBarcode());
intent.putExtra("format", productList.get(pos).getFormat());
intent.putExtra("IsScan", false);
Log.i("", "" + productList.get(pos).getBarcode());
parentActivity.startActivity(intent);
Log.i("", "" + pos);
}
});
holder.text2 = (TextView) convertView.findViewById(R.id.price);
// holder.text2.setOnClickListener(listener);
holder.image = (ImageView) convertView
.findViewById(R.id.productimageid);
convertView.setTag(holder);
// holder.image.setOnClickListener(listener);
holder.text1.setText(productList.get(position).getTitle());
holder.text2.setText(productList.get(position).getPrice().toString());
if (productList.get(position).getSmallImage() != null) {
byte[] bb = (productList.get(position).getSmallImage());
holder.image.setImageBitmap(BitmapFactory.decodeByteArray(bb, 0,
bb.length));
} else {
holder.image.setImageBitmap(null);
holder.image.setBackgroundResource(R.drawable.highlight_disabled);
}
// holder.image.setImageBitmap(Utils.loadBitmap(productList.get(position).getSmallImage()));
final CheckBox check = (CheckBox) convertView
.findViewById(R.id.checkbox);
check.setClickable(true); // to remove anything carried over from prev convert view
if(productList.get(pos).getCheckboxflag()==1)
{
Log.i("CheckBox set checked",""+pos);
check.setChecked(true);
}
else{
Log.i("CheckBox set unchecked",""+pos);
check.setChecked(false);
}
setWishListItemsInScanList(pos, convertView);
check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Log.i("OnclickListener","Current Position"+pos);
if (check.isChecked()
&& productList.get(pos).getWishListFlag() == 0) {
if(check.isClickable()){
Log.i("CheckBox check",""+pos);
ScanListActivity.updateCheckBoxSelection(1, pos);
ScanListAdapter.count++;
}
} else if (!check.isChecked()
&& productList.get(pos).getWishListFlag() == 0){
if(check.isClickable()){
ScanListActivity.updateCheckBoxSelection(0, pos);
ScanListAdapter.count--;
Log.i("CheckBox UNcheck",""+pos);
}
}
if (ScanListAdapter.count == 0) {
// showOrHideButton.setClickable(false);
// showOrHideButton.setVisibility(View.GONE);
showOrHideButton.setEnabled(false);
} else {
// showOrHideButton.setVisibility(View.VISIBLE);
showOrHideButton.setEnabled(true);
}
}
});
return convertView;
}
private void setWishListItemsInScanList(int pos, View convertView) {
if (productList.get(pos).getWishListFlag() == 1) {
Log.i("CheckBox set checked from wish list",""+pos);
CheckBox check = (CheckBox) convertView.findViewById(R.id.checkbox);
check.setClickable(false);
check.setChecked(true);
}
}
static class ViewHolder {
TextView text1;
ImageView image;
TextView text2;
}
}
List activity file :
package com.idg.project.activities;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.idg.project.R;
import com.idg.project.adapters.WishListAdapter;
import com.idg.project.adapters.ScanListAdapter;
import com.idg.project.entity.ScannedProduct;
import com.idg.project.services.ScannedProductDataAccessManager;
public class ScanListActivity extends BaseActivity {
static Button scanlist;
ScanListAdapter listAdapter;
static List<ScannedProduct> productList;
/* Notes for the Developer :
* For tracking the checked items Checkboxflag
* is maintained.
* Point1 : Select all will just set this flag in the local list and then call notifyDatachange of the adapter
* within adapter the check box is set or reset based on this flag for each row
*
* Point 2: When individual rows are selected , there is an onclick of the check box is invoked
* Here the Checkboxflag of the local list is set /unset . Also we need a way to knpw the select all button is
* to enabled or diabled. for that Count variable is updated here.
* Now Important point is these two actions shoulnt be taking place if the checkbox state change due to select all
* So there is a special check of isclickable in the onclicklistener
*
* Point 3: In scan list the items in the wish list are to be marked. This again needs special logic.
* This is done in the adapter code by checking all the rows whose wishListFlag is 1 and making it non clickable
*
* Important : Listview has the concept of ViewGroup and each view group is usually the rows fitting in the display screen
* so when we scroll, the viewGropu changes.
* Convertview is get reused for view groups. So need to careful undesired values that will be carried to next viewgroup*/
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.scan_list);
productList = new ArrayList<ScannedProduct>();
productList = getProductList();
for(int i=0;i<productList.size();i++){
Log.i("checkboxflag at : ", i+"is"+(productList.get(i).getCheckboxflag()));
}
final ListView lv = (ListView) findViewById(R.id.list);
scanlist = (Button) findViewById(R.id.addtowishlist);
scanlist.setEnabled(false);
listAdapter = new ScanListAdapter(this, productList, scanlist, this);
lv.setAdapter(listAdapter);
}
private List<ScannedProduct> getProductList() {
List<ScannedProduct> productList = new ArrayList<ScannedProduct>();
ScannedProductDataAccessManager productDataBaseManager = new ScannedProductDataAccessManager(
getApplicationContext());
String[] colList = { "title", "smallImage", "price" };
productList = productDataBaseManager.fetchAllProducts();
return productList;
}
static boolean selectFlag = false;
public void selectAll(View view) {
ListView listView = (ListView) findViewById(R.id.list);
view = findViewById(R.id.select_all);
if (selectFlag == false) {
for (int i = 0; i < listView.getAdapter().getCount(); i++) {
productList.get(i).setCheckboxflag(1);
}
view.setBackgroundResource(R.drawable.login_remme_dwn_btn);
selectFlag = true;
TextView text=(TextView) findViewById(R.id.select);
text.setText("Unselect All");
scanlist.setEnabled(true);
} else {
for (int i = 0; i < listView.getAdapter().getCount(); i++) {
productList.get(i).setCheckboxflag(0);
}
view.setBackgroundResource(R.drawable.login_remme_up_btn);
selectFlag = false;
TextView text=(TextView) findViewById(R.id.select);
text.setText("Select All");
scanlist.setEnabled(false);
}
((BaseAdapter)listView.getAdapter()).notifyDataSetChanged(); // we are only setting the flags in the list
// so need to notify adapter to reflect same on checkbox state
//listView.refreshDrawableState();
}
public void addToWishList(View view) {
ListView listView = (ListView) findViewById(R.id.list);
for (int i = 0; i < listView.getAdapter().getCount(); i++) {
ScannedProduct product = productList.get(i);
if (product.getWishListFlag() == 0 && product.getCheckboxflag()==1) {
product.setWishListFlag(1);
new ScannedProductDataAccessManager(getApplicationContext())
.updateProduct(product, "title",
new String[] { product.getTitle() });
product.setCheckboxflag(0);
//ScanListAdapter.count--;
}
Log.i("ScanList selected", product.getTitle());
}
Toast.makeText(getApplicationContext(),
"Added selected items to Wish List", Toast.LENGTH_SHORT).show();
scanlist.setEnabled(false);
((BaseAdapter)listView.getAdapter()).notifyDataSetChanged();
}
static public void updateCheckBoxSelection(int flag,int pos){ // when individual row check box is checked/ unchecked
// this fn is called from adapter to update the list
productList.get(pos).setCheckboxflag(flag);
}
}
Since your checkbox is inside listview, so you need to call notifyDataSetChanged method on your list's adapter to refresh it's contents.
update
instead of ((BaseAdapter)listView.getAdapter()).notifyDataSetChanged();, try calling listAdapter.notifyDataSetChanged();
I got the answer / bug in my code
i am not reusing convertview so its every time a new holder.
I am changing the flag of the checkbox and then assigning a statechange listener for the checkbox
thus its not getting invoked
when i changed the order to assign checkchangelistener before actually changing the state , its working as expected. The listener is getting called.
thanks all of you
Hi below is some code ive been playing with but when i debug it never gets to the onitemclicklisten routine can anyone help?
package sanderson.swords.mobilesales;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.app.ListActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.AdapterView.OnItemClickListener;
public class OrderProductSearch extends Activity {
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
HashMap<String,String> item = new HashMap<String,String>();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
setContentView(R.layout.orderproducts);
}
catch (Exception e) {
//
String shaw="";
shaw = e.getMessage();
}
//Create view of the list where content will be stored
final ListView listContent = (ListView)findViewById(R.id.orderproductlistview);
//Set for fast scrolling
listContent.setFastScrollEnabled(true);
//Create instance of the database
final DbAdapter db = new DbAdapter(this);
//Open the Database and read from it
db.openToRead();
//Routine to call all product sub groups from the database
final Cursor cursor = db.getAllSubGroupProduct();
//Manages the cursor
startManagingCursor(cursor);
int i=0;
cursor.moveToFirst();
while (cursor.getPosition() < cursor.getCount()) {
item.put("ProdName",cursor.getString(2));
item.put("ProdSize", cursor.getString(3));
item.put("ProdPack",cursor.getString(4));
item.put("OrdQty","0");
//list.add(item);
list.add(i, item);
item = new HashMap<String,String>();
cursor.moveToNext();
i = i + 1;
}
String[] from = new String[] {"ProdName", "ProdSize", "ProdPack", "OrdQty"};
int[] to = new int[] { R.id.productlinerow, R.id.productlinerow2, R.id.productlinerow3, R.id.productlinerow4};
SimpleAdapter notes = new SimpleAdapter(OrderProductSearch.this,list,R.layout.productlinerow,from,to);
listContent.setAdapter(notes);
//Close the database
db.close();
listContent.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String neil = "test";
neil = neil + "test";
}
});
}
}
An easier way to verify the click listener is to add some logcat prints in it, e.g.
listContent.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.d(TAG, "Click!");
}
});
If you set a breakpoint at
listContent.setOnItemClickListener(new OnItemClickListener() {
it may not break when you click.
Try setting a breakpoint at
String neil = "test";
and debugging.