I have a ArticlesAdapter which I am using to read remote JSON data. The adapter is working but I am struggling to get my ListView setonitemclicklister working.
What I am trying to accomplish is the ability to click on a ListItem and to get the Article data for the option clicked on.
I have functions like getName() in my Article class which I need to call in response to a ListItem click but I can't seem to find a way to accomplish it.
I am trying to do this in my AsyncTask class.
Using the following code:
protected void onPostExecute(JSONArray result) {
// TODO Auto-generated method stub
Log.i("CHECK", "RESULTS: " + result);
List<Article> articles = new ArrayList<Article>();
String title = null;
String nid = null;
try{
for(int i=0; i < data.length(); i++){
JSONObject dataObj = (JSONObject)data.get(i);
JSONObject record = dataObj.getJSONObject("node");
title = (record.getString("title"));
nid = (record.getString("nid"));
Log.i("FOUND", "title: " + title);
Log.i("FOUND", "nid: " + nid);
articles.add( new Article(title, "", Integer.parseInt(nid)) );
}
}catch(JSONException j){
Log.e("CHECK", "Attempting to read data returned from JSONReader: " + j.toString());
}
ListView articlesList = (ListView)findViewById(R.id.articlesList);
ArticleAdapter adapter = new ArticleAdapter(ArticlesActivity.this, R.layout.article_item, articles);
articlesList.setAdapter(adapter);
articlesList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "testing : ", Toast.LENGTH_LONG);
Log.i("CHECK", "AdapterView: " + parent);
Log.i("CHECK", "VIEW : " + view);
Log.i("CHECK", "POSITION : " + position);
Log.i("CHECK", "ID : " + id);
}
});
if(dialog.isShowing())
dialog.dismiss();
}
My problem is I am not sure how to get the setOnItemClickListener working.
I am able to print the arguments via the Log function:
Log.i("CHECK", "AdapterView: " + parent);
Log.i("CHECK", "VIEW : " + view);
Log.i("CHECK", "POSITION : " + position);
Log.i("CHECK", "ID : " + id);
...but I get errors when I try casting any of the arguments into an Article object so I can call it's getName() function etc.
Your AsyncTask appears to be nested in your Activity, if it isn't simply pass articles to your Activity, then use:
articlesList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Article article = articles.get(position);
// Do something with article
}
});
An architectural change you would want to do is pull your ListView, Adapter, and OnItemClickListener initialization out of the AsyncTask and only update articles as well as notify the Adapter in the onPostExecute callback.
Related
So I managed to save data from an array in a json file. This array is created manually as you can see by the 8 item.add(...) and each item has 4 values. isSelected, userName, userAttack, userStatus and isFavorite. Only isSelected and isFavorite will change through onItemClickListeners and are of type boolean. I want to store the change of those values as soon as I click on the item and it worked. The Logs would show me that json is an array with all the information inside.
My Problem is the retrieval of this information when the app is created and I have no idea where to place it. Not only that but I dont know how to use the json file in onCreate because the json is only made when I click or longclick on the items. Can somebody give me hints on how to successfully let the app remember that values the item has? Would be very thankful.
//package and imports
public class MainActivity extends Activity {
ListView listView;
private String msg = "Android : ";
private boolean isChecked;
ArrayList<UserModel> item = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ArrayList<UserModel> item = new ArrayList<>();
listView = (ListView) findViewById(R.id.list_view);
item.add(new UserModel(false, R.string.name0, R.string.atk0, R.string.stat0,false));
item.add(new UserModel(false, R.string.name1, R.string.atk1, R.string.stat1,false));
item.add(new UserModel(false, R.string.name2, R.string.atk2, R.string.stat2,false));
item.add(new UserModel(false, R.string.name3, R.string.atk3, R.string.stat3,false));
item.add(new UserModel(false, R.string.name4, R.string.atk4, R.string.stat4,false));
item.add(new UserModel(false, R.string.name5, R.string.atk5, R.string.stat5,false));
item.add(new UserModel(false, R.string.name6, R.string.atk6, R.string.stat6,false));
item.add(new UserModel(false, R.string.name7, R.string.atk7, R.string.stat7,false));
Log.d(msg, "Made UserModel List with size: " + item.size());
final CustomAdapter adapter = new CustomAdapter(this, item);
listView.setAdapter(adapter);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.d(msg,"Item " + i + " was long clicked!");
UserModel model = item.get(i);
if(model.isFavorite()) {
model.setFavorite(false);
Log.d(msg, "Item " + i + " was removed as Favorite!");
Toast.makeText(view.getContext(), model.getUserName() + i + " was removed from Favorites!", Toast.LENGTH_SHORT).show();
} else {
model.setFavorite(true);
Log.d(msg, "Item " + i + " was added as Favorite!");
Toast.makeText(view.getContext(),model.getUserName() + i + " was added to Favorites!",Toast.LENGTH_SHORT).show();
}
item.set(i, model);
adapter.updateRecords(item);
Gson gson = new Gson();
String json = gson.toJson(item);
Log.d(msg, "Here is the json file: " + json);
return model.isFavorite();
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.d(msg, "Item " + (i) + " was clicked!");
UserModel model = item.get(i);
if (model.isSelected())
model.setSelected(false);
else
model.setSelected(true);
Log.d(msg, "Item " + (i) + " " + model.isSelected());
item.set(i, model);
//now update adapter
adapter.updateRecords(item);
Gson gson = new Gson();
String json = gson.toJson(item);
Log.d(msg, "Here is the json file: " + json);
}
});
}
}
Assuming I understood your question, here is how you can load the json data onCreate.
ArrayList<UserModel> items = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Load json to string from the file you saved it in
...
String rawJson = "...";
//Parse data to your list
...
items = gson.fromJson(br, new TypeToken<List<UserModel>>(){}.getType());
}
However, I would recommend looking into storing your data in a local database, as it is easier to update and manage. Storing json in a file is very ugly.
You could check out libraries as Room.
If I populate my listview with the primary key of my table I can get this primary key using getItemAtPosition and then it works fine.
The problem is that I don't want to use the primarykey to populate de listview, instead I want to use other fields of my table. Doing that, when I use the getItemAtPosition comand, because itsn't unic I can't use this to select my register.
I thought about using getItemIdAtPosition but I didn't reached any solution.
public void populateListView() {
//get the data and append to the list
Cursor data = db.getAllDataFillup(selectedID);
ArrayList<String> listData2 = new ArrayList<>();
while (data.moveToNext()) {
//listData2.add("FILLUP_ID: " + data.getString(0) + " FILLUP_VEHICLE_ID: " + data.getString(1));
//listData2.add(data.getString(7) + " " + data.getString(8) + " " + data.getString(2));
listData2.add(data.getString(3));
//listData2.add(data.getString(2));
}
//create the list adapter and set the adapter
ListAdapter adapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listData2);
list_fillup.setAdapter(adapter2);
//set onItemClickListener to the listView
list_fillup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int fillupID = Integer.parseInt(adapterView.getItemAtPosition(i).toString());
long position = adapterView.getSelectedItemId();
//long a = list_fillup.get(codigoDoObjeto).getCodigoIdOuPKQualquer();
toastMessage("position: " + position);
//toastMessage("fillupPosition: " + fillupPosition);
//long fillupPosition = adapterView.getItemIdAtPosition(i);
Log.d(TAG, "onItemClick: You Clicked on " + fillupID);
Cursor data = db.getDataTableFillup(fillupID);//get the data associated with that fillupID
fillupID = -1;
while (data.moveToNext()) {
fillupID = data.getInt(0);
vehicleID = data.getInt(1);
fillupDate = data.getString(2);
odometer = data.getLong(3);
kmDriven = data.getLong(4);
liters = data.getLong(5);
consumption = data.getLong(6);
label = data.getString(7);
sequence = data.getInt(8);
}
if (fillupID > -1) {
Log.d(TAG, "onItemClick: The ID is: " + fillupID);
Intent screenVehicle = new Intent(Vehicle_painel.this, Fillup_edit.class);
screenVehicle.putExtra("fillupID", fillupID);
screenVehicle.putExtra("vehicleID", vehicleID);
screenVehicle.putExtra("vehicleName", selectedName);
screenVehicle.putExtra("date", fillupDate);
screenVehicle.putExtra("odometer", odometer);
screenVehicle.putExtra("kmDriven", kmDriven);
screenVehicle.putExtra("liters", liters);
screenVehicle.putExtra("consumption", consumption);
screenVehicle.putExtra("label", label);
screenVehicle.putExtra("sequence", sequence);
//toastMessage("fillupPosition: " + fillupPosition);
startActivity(screenVehicle);
} else {
toastMessage("fillupID = " + fillupID);
//db.deleteAllFillup(selectedID);
//toastMessage("No ID associated with that name hahaha");
}
The best thing to do would be to create a custom class to hold your data. That way you no longer just get a simple String value back from your adapter. Your ArrayList would be something like:
ArrayList<YourCustomClass> listData2 ...
Create a custom class "YourCustomClass" (Call it what ever you like). It could look like:
public class YourCustomClass {
private long itemId = 0;
private String itemName;
private String itemDescription;
public YourCustomClass(){
}
public void setItemId(long id){ this.itemId = id; }
public void setItemName(String itemName){ this.itemName = itemName; }
public void setItemDescription(String itemDescription){ this.itemDescription = itemDescription; }
public long getItemId() { return this.itemId; }
public String getItemName(){ return this.itemName; }
public String getItemDescription(){ return this.itemDescription; }
}
Now in your onItemClick method get the Id and the other data like this:
YourCustomClass data = (YourCustomClass) adapterView.getItemAtPosition(i);
long orderId = data.getItemId();
String name = data.getItemName();
You will need a custom adapter to populate your ListView with data.
You can also take a look at this answer. It shows how to change the background color of a ListView item, but also shows more detail of how to implement a custom adapter for your ListView.
How to set background color for each item listview depanding on variable value
I'm obviously missing something in making this custom adapter. Basically, I've got code that grabs JSON from the site, then breaks it down into a ArrayList. I can do a .toString() and spit it all out onto a listview just fine, but everything I find on the net for creating a custom adapter creates the list inside of it. Is there a way to just supply your pre-created list? I've yet to make any headway on getting the custom one to work...but, as I said I can get the string to work just fine, so I'll include that code.
Here's my classes:
public class JSONEvents {
String eid;
String bid;
private String bname;
private String valid;
#Override
public String toString() {
return "Events [eid=" + eid + ", bid=" + bid + ", bname=" + bname
+ ", start=" + start + ", end=" + end + ", points=" + points
+ ", title=" + title + ", description=" + description
+ ", cat=" + cat + ", type=" + type + ", subtype=" + subtype
+ ", valid=" + valid + "]";
}
public String getEventInfo(String field){
if("eid".equals(field)){return eid;}
else if("bid".equals(field)){return bid;}
else if("bname".equals(field)){return bname;}
else if("valid".equals(field)){return valid;}
return "none";
}
}
public class JSONAdventures {
private String aid;
private String bid;
private String start;
private String valid;
#Override
public String toString() {
return "Adventures [aid=" + aid + ", bid=" + bid + ", start=" + start
+ ", end=" + end + ", points=" + points + ", title=" + title
+ ", description=" + description + ", cat=" + cat + ", type="
+ type + ", subtype=" + subtype + ", steps_comp=" + steps_comp
+ ", total_steps=" + total_steps + ", valid=" + valid + "]";
}
public String getEventInfo(String field){
if("aid".equals(field)){return aid;}
else if("bid".equals(field)){return bid;}
else if("start".equals(field)){return start;}
else if("valid".equals(field)){return valid;}
return "none";
}
}
public class JSONEandA {
private ArrayList<JSONEvents> events;
private ArrayList<JSONAdventures> adventures;
#Override
public String toString() {
return "ResponseHolder [events=" + events + ", adventures="
+ adventures + "]";
}
public ArrayList<JSONEvents> getJSONEvents() {
return events;
}
public ArrayList<JSONAdventures> getJSONAdventures() {
return adventures;
}
}
For the code in m activity:
List<JSONEvents> eventlist = new ArrayList<JSONEvents>();
try {
Gson googleJson = new Gson();
JSONEandA rh = googleJson.fromJson(example,
JSONEandA.class);
for (JSONEvents e : rh.getJSONEvents()) {
eventlist.add(e);
//eventlist.addAll(e);
// System.out.println(e.toString());
System.out.println(e.getEventInfo("eid"));
System.out.println(e.toString());
}
final ListView listview = (ListView) findViewById(R.id.eventlistview);
String[] values = new String[eventlist.size()];
eventlist.toArray(values);
// String[] values = new String[] {e.toString()};
final ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < values.length; ++i) {
list.add(values[i]);
}
final StableArrayAdapter adapter = new StableArrayAdapter(
Events.this,
android.R.layout.simple_list_item_1, list);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
final View view, int position, long id) {
final String item = (String) parent
.getItemAtPosition(position);
list.remove(item);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(),
"Item Removed", Toast.LENGTH_LONG).show();
});
I've also pieced together an attempt at an adapter from various tutorials and such, but can't figure out how to tie it all together:
class EventAdapter extends ArrayAdapter<JSONEvents> {
private ArrayList<JSONEvents> items;
public EventAdapter(Context context, int textViewResourceId,
ArrayList<JSONEvents> items) {
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.list_events, null);
}
JSONEvents q = items.get(position);
if (q != null) {
TextView nameText = (TextView) v.findViewById(R.id.firstline);
TextView priceText = (TextView) v.findViewById(R.id.secondLine);
if (nameText != null) {
nameText.setText(q.getEventInfo("eid"));
}
if (priceText != null) {
priceText.setText(q.getEventInfo("bid"));
}
}
return v;
}
}
I would appreciate any help, thanks!
Did you put tha data into your adapter?
adapter.addAll(String[] data);
Or you could do it while creating adapter:
EventAdapter adapter = new EventAdapter(this, R.id.some_id, eventlist);
I am trying to update my listview with notifyDataSetChanged() this method, but listview is not getting updated, if i press back button and go to previous activity and then again if i come in this activity then it is getting updated, i don't know why. I tried all possible solution but not getting proper solution. Please help Below is my code.
Here is a link which i tried
ListView not getting updated on calling notifyDataSetChanged()
notifyDataSetChanged() not working
notifyDataSetChanged Android ListView
notifyDataSetChanged not updating ListView
The event of notifyDataSetChanged()
public class Assignment extends Activity {
ListView mListView;
ImageView imageViewCrtAsnm;
String[] stg1;
List<String[]> names2 = null;
DataManipulator dataManipulator;
ArrayAdapter<String> adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.assignment);
imageViewCrtAsnm = (ImageView) findViewById(R.id.createassignment);
mListView = (ListView) findViewById(R.id.displaydata);
imageViewCrtAsnm.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Assignment.this,
Assignment_Create.class);
startActivity(intent);
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View item,
final int position, long id) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
Assignment.this);
alertDialogBuilder.setTitle("Delete Data");
alertDialogBuilder
.setMessage("Click yes to Delete Record!")
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
String[] delete = names2.get(position);
String idString = delete[0];
long idLong = Long.valueOf(idString);
Log.d("Deleting...", idLong + "");
dataManipulator.delete(idLong);
names2.remove(position);
stg1 = new String[names2.size()];
int x = 0;
String stg;
for (String[] name : names2) {
stg = "Title : " + name[1] + "\n"
+ "Descr : " + name[2]
+ "\n" + "Day's Left : "
+ name[3];
stg1[x] = stg;
x++;
}
adapter.notifyDataSetChanged();
}
})
.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
});
dataManipulator = new DataManipulator(this);
names2 = dataManipulator.selectAll();
stg1 = new String[names2.size()];
int x = 0;
String stg;
for (String[] name : names2) {
stg = "Title : " + name[1] + "\n" + "Descr : " + name[2] + "\n"
+ "Day's Left : " + name[3];
stg1[x] = stg;
x++;
}
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, stg1);
mListView.setAdapter(new ArrayAdapter<String>(this, R.layout.check,
stg1));
mListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
ArrayAdapter makes a copy of your items that you pass to it in the constructor and uses that internally.
ArrayAdapter Source
So simply manipulating your original array means nothing to the adapter. You are notifying it that the data has changed when it has not changed at all, it still holds the original list you populated it with.
You need to either recreate the entire adpater again or use the clear, addAll, remove or insert methods to manipulate the data.
http://developer.android.com/reference/android/widget/ArrayAdapter.html
You are recreating your array when you remove data. Have you tried also recreating your adapter to use the new array?
I found solution for this.
Just use onResume method to call adapter class...
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
names2 = dataManipulator.selectAll();
stg1 = new String[names2.size()];
int x = 0;
String stg;
for (String[] name : names2) {
stg = "Title : " + name[1] + "\n" + "Descr : " + name[2] + "\n"
+ "Day's Left : " + name[3];
stg1[x] = stg;
x++;
}
adapter = new ArrayAdapter<String>(this, R.layout.assignment_custom,
stg1);
mListView.setAdapter(adapter);
mListView.setCacheColorHint(Color.TRANSPARENT);
mListView.setBackgroundResource(R.drawable.assignment_icon);
adapter.notifyDataSetChanged();
adapter.setNotifyOnChange(false);
mListView.invalidateViews();
}
Just call this part of code in onResume method and you are done. But anyway thanks to all who have helped me. i am posting this answer here so may be other's can take benefit and not waste time like i did.
my first time doing an app on android. i have 4 strings and a lisview.i want to display the strings whenever user press the items on the listview on a toast.
can any one help me on this ?
For eg: there are Event 1 ,event 2 and event 3 on my list view.
and when user press event 1. it will display the date, time , venue for that event.
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
Context context = getApplicationContext();
Toast.makeText(context,
"Date: "+date +" " +"Tme: "+ time, Toast.LENGTH_LONG).show();
Toast.makeText(context,"hi",Toast.LENGTH_LONG).show();
}
});
This is the codes for extracting it out from googleCalendar
date = contentResult[0].substring(10, 21);
time = contentResult[0].substring(21, 36);
location = contentResult[2].substring(6);
description = contentResult[4].substring(18);
eventTitle[i] = name;
eventDate[i] = date;
eventTime[i] = time;
eventVenue[i] = location;
eventContent[i] = description;
event[i] = name + " " + "Date: " +date + " " + "Time: " +time + " " +" Location:"+ location+ "Event Description:"+ description ;
You would need to set your lists onItemClickListener like so:
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id)
{
// Display a messagebox.
Toast.makeText(this,"You clicked something!",Toast.LENGTH_SHORT).show();
}
};
myList.setOnItemClickListener(mMessageClickedHandler);
Of course you would have to input your own data (I'm guessing from a database or web service) to the Toast message indicating the date, time, and location of the event.
EDIT: In response to your comment, it sounds like you are new to Android development. You might want to check out this great tutorial to learn how to use SQLite, and the Android SDK in general.