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
Related
This is the first question I am posting. Here is my question and below given is the debugged code from android studio.
Here, I have tried to extract the data by taking the data from the adapter into the mainActvity, but I failed as the app is crashing on Clicking the save button. Here the data is nothing but and object.
MainActivity :
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ArrayList<ListItem_Elements> testsList;
int n=5;//No. of tests
Button btn_save;
CustomAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView)findViewById(R.id.listView);
btn_save= (Button)findViewById(R.id.btn_save);
//CustomAdapter adapter;
Resources res=getResources();//Takes the resource permission required to show ListView
testsList= new ArrayList<ListItem_Elements>();
testsList = SetList();
adapter= new CustomAdapter(this, testsList, res);
listView.setAdapter(adapter);
btn_save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(testsList!=null)
saveValues();
}
});
}
public ArrayList<ListItem_Elements> SetList() {
/*Enter the Test names*/
ArrayList<ListItem_Elements>tests_Array= new ArrayList<ListItem_Elements>();
for(int i=0;i<5;i++) {
ListItem_Elements e = new ListItem_Elements();
e.setTest("XYZ");
e.setResult(null);
tests_Array.add(e);
}
return tests_Array;
}
ArrayList<ListItem_Elements>ar= new ArrayList<>();
public void saveValues() {
if(adapter.extractedArray!=null) {
ar = adapter.extractedArray;
Toast.makeText(MainActivity.this, ar.size(), Toast.LENGTH_SHORT).show();
}
}
}
--------------------------------------------------------------------------------
CustomAdapter :
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomAdapter extends BaseAdapter {
private Activity activity;
public static ArrayList<ListItem_Elements> extractedArray= new ArrayList<ListItem_Elements>();
private ArrayList<ListItem_Elements> array;
//Declaration of ArrayList which will be used to recieve the ArrayList that has to be putup into the ListView
private LayoutInflater inflater; //To Instantiates a layout XML file into its corresponding View
Resources res;
//protected String bridgeValue;
CustomAdapter(Activity a, ArrayList<ListItem_Elements> b, Resources resLocal) {
activity = a;
array= b;
res = resLocal;
//Initialization of inflater to link the layout of list items
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public CustomAdapter() {
}
#Override
public int getCount() {
return array.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
// keeping references for views we use view holder
public static class ViewHolder {
/*Declaration of elements of layout of list items in the class for future use of putting up
data onto the List View*/
TextView textView;
EditText editText;
}
#Override
//Here views were bound to a position
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
// if a view is null(which is for the first item) then create view
if (convertView == null) {
vi = inflater.inflate(R.layout.layout_items, null);
// Taking XML files that define the layout of items, and converting them into View objects.
holder = new ViewHolder();//Stores the elements of the layout of list items
/*Initializing the elements of the layout of list item*/
holder.textView = (TextView) vi.findViewById(R.id.textView);
holder.editText = (EditText) vi.findViewById(R.id.editText);
vi.setTag(holder);
//Stores the view(layout of list item) into vi
}
//else if it already exists, reuse it(for all the next items). Inflate is costly process.
else {
holder = (ViewHolder) vi.getTag();
//Restores the already exisiting view in the 'vi'
}
/*Setting the arrayList data onto the different elements of the layout of list item*/
try {
holder.textView.setText(array.get(position).getTest());
if(holder.editText.getText()!=null) {
ListItem_Elements obj = new ListItem_Elements();
obj.setTest(array.get(position).getTest());
obj.setResult(holder.editText.getText().toString());
extractedArray.add(position, obj);
}
}
catch (Exception e) {
e.getMessage();
}
return vi;//Returns the view stored in vi i.e contents of layout of list items
}
}
--------------------------------------------------------------------------------
public class ListItem_Elements {
String test;
String result;
ListItem_Elements() {
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
You are missing some necessary code. EditText has a method called addTextChangedListener() which accepts a TextWatcher implementation. This implementation would be responsible for updating the data in the adapter.
final ListItem_Elements item = array.get(position);
holder.textView.setText(item.getTest());
holder.editText.setText(item.getResult());
holder.editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
item.setResult(s.toString());
}
// omitted empty impls for beforeTextChanged() and afterTextChanged(), you need to add them
});
Now, everytime the user updates the EditText, your adapter value will be updated. Then you just get the array values:
public void saveValues() {
// testLists in the activity and array in the adapter are references
// to the same list. So testLists already has the updated results
}
And take out this whole block of code:
holder.textView.setText(array.get(position).getTest());
if(holder.editText.getText()!=null) {
ListItem_Elements obj = new ListItem_Elements();
obj.setTest(array.get(position).getTest());
obj.setResult(holder.editText.getText().toString());
extractedArray.add(position, obj);
}
It doesn't do the right thing.
you are filling the listView with value from an ArrayList. Why you don't just get values from the your ArrayList ??
public void saveValues() {
if(tests_Array!=null) {
//and here you get values from your list
//by a simple for instruction
Toast.makeText(MainActivity.this, tests_Array.size(), Toast.LENGTH_SHORT).show();
}
}
I am writing a code in Android to refresh a Gridview in every 2 mins. I searched a lot in the web but i don't find any specific technique to do it.
Java Code
MainActivity.java
package com.example.mycustomgridrefresh;
import java.util.ArrayList;
import android.os.Bundle;
import android.widget.GridView;
import android.app.Activity;
public class MainActivity extends Activity
{
GridView gd;
MyGrid mg;
ArrayList<String> abc;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gd = (GridView)findViewById(R.id.gd);
abc = new ArrayList<String>();
for(int i=0;i<100;i++)
{
abc.add(String.valueOf(i));
}
mg = new MyGrid(this,this,abc);
gd.setAdapter(mg);
}}
MyGrid.java
package com.example.mycustomgridrefresh;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class MyGrid extends BaseAdapter
{
ArrayList<String> abc;
Activity activity;
public MyGrid(Activity activity , Context cont,ArrayList<String> abc)
{
super();
this.abc = abc;
this.activity = activity;
}
#Override
public int getCount()
{
return abc.size();
}
#Override
public Object getItem(int arg0)
{
return abc.get(arg0);
}
#Override
public long getItemId(int arg0)
{
return 0;
}
public class ViewHolder
{
public TextView txt;
}
#Override
public View getView(int arg0, View arg1, ViewGroup arg2)
{
ViewHolder view;
LayoutInflater inflator = activity.getLayoutInflater();
if(arg1==null)
{
view = new ViewHolder();
arg1 = inflator.inflate(R.layout.mygrid, null);
view.txt = (TextView) arg1.findViewById(R.id.txt);
arg1.setTag(view);
}
else
{
view = (ViewHolder) arg1.getTag();
}
view.txt.setText(abc.get(arg0));
return arg1;
}
}
This above Grid is printing 100 numbers is 10 rows & columns. I want to change the value of the grid cells for each 2mins. The value should to change to +1.
Please suggest me some good solution.
Thanks in Advance !!!
To refresh the values you need to call in MyGrid:
notifyDataSetChanged()
To do any task each 2 mins you need to create other thread, something like this:
public void startRunnable(){
Runnable r = new Runnable() {
#Override
public void run() {
while(needToRefresh){
//add one...
this.notifyDataSetChanged();
Thread.sleep(2000);
}
}
};
this.activity.runOnUiThread(r);
}
Don't forget to stop the needToRefresh condition onPause, onStop.
EDIT: Because notifyDataSetChanged() need to be call in UI thread, you need to call runnable using this.activity.runOnUiThread
See there: How to use notifyDataSetChanged() in thread
I have a ListFragment that contains a list of items. I would like to load say 9 items at a time and when i scroll and reach the bottom of the listview i want to load another 9 items in background.
I make 2 request to my web server:
1) to get all the item id's of the items, by a searh() method
2) to get all the item details of a specific item though its id, by getId(id) method
The version i have implemented gets all the ids and then loads all the items at once in the doInBackground method of AsyncTask and it works. and it takes very long (i dont want a button because its really ugly).
I'd like to introduce this thing about the onScrollListener so that when i first open my app, in background i get all the ids, and then i get the first 9 items and show them. then when i scroll to the end i want to load the next 9 items. How do i do this?
I have read a few posts but it not clear to me, especially due to the fact that i have 2 functions that need to be run in background, 1 function needs to be run once while the other many times and i need to keep track of which id's i getting.
I would also if possible like to add the function that if i pull the ListView a little then it should update my view.
Here is my code:
import java.util.ArrayList;
import java.util.HashMap;
import android.app.ListFragment;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.Toast;
import com.prjma.lovertech.R;
import com.prjma.lovertech.adapter.ListViewAdapter;
import com.prjma.lovertech.util.MVPFunctions;
public class CompraFragment extends ListFragment {
public ListView listView;
public ListViewAdapter adapter;
/**
* Keep track of the login task to ensure we can cancel it if requested.
*/
private DownloadTask mDownloadTask = null;
public ArrayList<HashMap<String, Object>> items;
public Bitmap icon;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//View rootView = inflater.inflate(R.layout.fragment_compra, false);
View rootView = inflater.inflate(R.layout.fragment_compra, container, false);
// now you must initialize your list view
listView = (ListView) rootView.findViewById(android.R.id.list);
mDownloadTask = new DownloadTask();
mDownloadTask.execute((Void) null);
return rootView;
}
/**
* Represents an asynchronous login/registration task used to authenticate
* the user.
*/
public class DownloadTask extends AsyncTask<Void, Void, Boolean> {
private ProgressDialog progressDialog;
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
//Here i get all the id's
ArrayList<Long> ids = MVPFunctions.getMioSingolo().search();
//for each id get all its details and put it in a map
items = new ArrayList<HashMap<String, Object>>();
for(int i=0; i < ids.size(); i++){
items.add(MVPFunctions.getMioSingolo().getItem(ids.get(i)));
}
return true;
}
#Override
protected void onPreExecute(){
/*
* This is executed on UI thread before doInBackground(). It is
* the perfect place to show the progress dialog.
*/
progressDialog = ProgressDialog.show(getActivity(), "", "Downloading Content...");
}
#Override
protected void onPostExecute(final Boolean success) {
mDownloadTask = null;
// dismiss the dialog after getting all products
progressDialog.dismiss();
//showProgress(false);
if (items.get(0).get("status error")!= null){
Toast.makeText(getActivity(), "status error = " + items.get(0).get("status error"), Toast.LENGTH_LONG).show();
Log.i("status error put toast", (String) items.get(0).get("status error"));
//fai qualcosa, tipo torna indietro, ecc
}
// updating UI from Background Thread
ListViewAdapter adapter = new ListViewAdapter(getActivity(),R.layout.listview_item_row, items, icon);
// updating listview
listView.setAdapter(adapter);
}
#Override
protected void onCancelled() {
mDownloadTask = null;
//showProgress(false);
}
}
}
Adapter class:
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.prjma.lovertech.R;
import com.prjma.lovertech.activity.DettagliActivity;
import com.prjma.lovertech.model.Item;
public class ListViewAdapter extends ArrayAdapter<String> {
private static LayoutInflater inflater = null;
public Context context;
public int layoutResourceId;
public ArrayList<HashMap<String, Object>> items;
public Bitmap icon;
//public ImageLoader imageLoader;
public ListViewAdapter(Context context, int listviewItemRow, ArrayList<HashMap<String, Object>> items, Bitmap icon) {
// TODO Auto-generated constructor stub
super(context, listviewItemRow);
this.items = items;
this.context = context;
this.icon = icon;
}
public int getCount() {
return items.size();
}
public Item getItem(Item position) {
return position;
}
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder viewHolder = new ViewHolder();
if (row == null) {
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.listview_item_row, null);
viewHolder.ic_thumbnail = (ImageView)row.findViewById(R.id.ic_thumbnail);
viewHolder.scadenza = (TextView)row.findViewById(R.id.tvScadenza);
viewHolder.prezzo = (TextView)row.findViewById(R.id.tvPrezzo);
viewHolder.followers = (TextView)row.findViewById(R.id.tvFollowers);
viewHolder.hProgressBar = (ProgressBar)row.findViewById(R.id.hProgressBar);
row.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)row.getTag();
}
HashMap<String, Object> item = items.get(position);
viewHolder.ic_thumbnail.setImageBitmap((Bitmap) item.get("pic1m"));
viewHolder.scadenza.setText((CharSequence) item.get("scadenza"));
viewHolder.prezzo.setText((CharSequence) item.get("prezzo"));
viewHolder.followers.setText((CharSequence) item.get("followers"));
viewHolder.hProgressBar.setProgress((Integer) item.get("coefficient"));
//row.onListItemClick(new OnItemClickListener1());
row.setOnClickListener(new OnItemClickListener(position));
return row;
}
private class OnItemClickListener implements OnClickListener {
private int mPosition;
private OnItemClickListener(int position){
mPosition = position;
}
#Override
public void onClick(View arg0) {
Log.i("onListItemClickList", "Item clicked: " + mPosition);
Toast.makeText(context, "Message " + Integer.toString(mPosition), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context, DettagliActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("id", mPosition);
intent.putExtras(bundle);
context.startActivity(intent);
}
}
static class ViewHolder {
public TextView prezzo;
public TextView scadenza;
public TextView followers;
public ImageView ic_thumbnail;
public ProgressBar hProgressBar;
}
}
In your adapter, check how close the user is from the bottom of the data set. When they get to the end, call a method that fetches more items from the network. I normally use a "REFRESH_THRESHOLD" integer to prefetch items before they're needed.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Item current = getItem(position);
//Pre-fetch
if(getCount() - position <= REFRESH_THRESHOLD){
//If there are more items to fetch, and a network request isn't already underway
if(is_loading == false && has_remaining_items == true){
getItemsFromNetwork();
}
}
Now i try to use adapter . But i dont understand how to set value from data .Becuase in friends = db.selectall ,value in friend have 3 value(fname,lname,nickname).So my question is How to set value(fname/lname/nickname OR one or the other) My code NOW look like this ::::
package com.example.sqlite;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.sqlite.db.FriendsDB;
import com.example.sqlite.entry.FriendEntry;
public class FriendsListActivity extends Activity {
private Context context;
private FriendsDB db;
private ArrayList<FriendEntry> friends;
private ArrayList<String> data;
private TextView hellotext;
private ListView hellolistview;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.friendlist_layout);
}
public void showAllList(){
//view matching
hellotext = (TextView) findViewById(R.id.hellotext);
hellolistview = (ListView) findViewById(R.id.hellolistview);
//select data
friends = db.selectAll();
if(friends.size()==0){
Toast.makeText(context,"You dont have any friend.",Toast.LENGTH_SHORT).show();
}else{
data = new ArrayList<String>();
for (int i = 1;i<=friends.size();i++){
// set value for data
**data.add("Your Name is "+friends["fname"]);<< I want to add data like this .How to correct**
}
}
}
private class adapter extends BaseAdapter{
private Holder holder;
#Override
//ดาต้ามีกี่แถว
public int getCount() {
// TODO Auto-generated method stub
return friends.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
//create
if( view == null){
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_layout,null);
holder = new Holder();
holder.title = (TextView) view.findViewById(R.id.item_title);
view.setTag(holder);
}else{
holder = (Holder) view.getTag();
}
//assign data / wait for data
return null;
}
private class Holder{
//view แต่ละตัวเก็บค่าอะไรบ้าง
public TextView title;
}
}
}
When you have data in Cursor and you want to display it in a ListView, you need to use a CursorAdapter.
You can either use the pre-defined SimpleCursorAdapter or if you want custom views, you can extend the CursorAdapter class.
Tutorial here: http://thinkandroid.wordpress.com/2010/01/11/custom-cursoradapters/
You are doing it allmost all right , but I suggest you to use an ArrayList of HashMap type instead of using Friends class.
This will lower your application burden.
ArrayList<HashMap<Object,String>> list=new ArrayList<HashMap<Object,String>>();
HashMap<Object,String> hm;
in your select all method
do{
hm=new HashMap<Object,String>();
hm.add(Key_Name,"retrieve the value from cursor here");
list.add(hm);
}while(c.movetonect());
return list;
in your activity
ArrayList<HashMap<Object,String>> list=new ArrayList<HashMap<Object,String>>();
list=db.selectAll();
HashMap<Object,String> hm;
for (int i=0;i<list.length;i++){
hm=list.getIndex(i); //retrieve all the vaalues here
}
use list adapters which accept list to populate the listview
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