Android cursor adapter get checkbox and data of listview - java

I have this code that used cursor adapter:
public class TemplateActivity extends Activity {
Button btnSort, btnDel;
private ListViewAdapter listAdapter;
private RetailerDatabaseHelper dbHelper;
private ListView listView;
private static final String TAG = TemplateActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_template);
btnSort = (Button) findViewById(R.id.btnSort);
btnDel = (Button) findViewById(R.id.btnDelete);
dbHelper = new RetailerDatabaseHelper(this);
listView = (ListView) findViewById(R.id.listViewData);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "clicked on item: " + position);
}
});
new Handler().post(new Runnable() {
#Override
public void run() {
listAdapter = new ListViewAdapter(TemplateActivity.this, dbHelper.getAllData());
listView.setAdapter(listAdapter);
}
});
my problem is that how can i get the value of the data from the listview when a data is clicked.
Here is my adapter for this:
public class ListViewAdapter extends CursorAdapter {
public ListViewAdapter (Context context, Cursor c) {
super(context, c);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// when the view will be created for first time,
// we need to tell the adapters, how each item will look
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View retView = inflater.inflate(R.layout.custom_dialog_box, parent, false);
return retView;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// here we are setting our data
// that means, take the data from the cursor and put it in views
TextView textViewPersonName = (TextView) view.findViewById(R.id.checkBox1);
textViewPersonName.setText(cursor.getString(cursor.getColumnIndex(cursor.getColumnName(1))));
TextView textViewPersonPIN = (TextView) view.findViewById(R.id.number);
textViewPersonPIN.setText(cursor.getString(cursor.getColumnIndex(cursor.getColumnName(2))));
}
}
another thing. how will i implement here that when i checked a checkbox and press a button it will get the data of the checkbox? thank you all for the help.

I haven't worked on ListViewAdapter but i have the same scenario as yours.
I have used CustomAdapter class extending Baseadapter and using custom layout. By this way you can set OnClicklistners for every view individually(check box,button,total layout... ).

The easiest way to do it in OnItemClickListener is this:
Cursor c = ((ListViewAdapter)l.getAdapter()).getCursor();
c.moveToPosition(position);
You can then use the c.getLong(0); to get the id (assuming you fetched the id column as the first column which is generally the case).
Second question :(Get the checked items list) :
You can write a setOnCheckedChangeListener (CompoundButton.OnCheckedChangeListener listener) for the Checkbox in your bindView() method of your Adapter, then if item is checked then add the item to the list, if it is unchecked then remove the item from the list.

Related

How to add items dynamically to a custom adapter for ListView

I made adapter for ListView. If I fill the elements array before creating the adapter and linking it to the listView, the elements are displayed.
But if I use the updateItems () method to add items when the button is clicked, nothing happens.
Code of adapter:
public class ListAdapter extends ArrayAdapter<Lf> {
private LayoutInflater inflater;
private int layout;
private List<Lf> lfs;
public ListAdapter(Context context, int resource, List<Lf> lfs) {
super(context, resource, lfs);
this.lfs = lfs;
this.layout = resource;
this.inflater = LayoutInflater.from(context);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView==null){
convertView = inflater.inflate(this.layout, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
Lf lf = lfs.get(position);
viewHolder.name.setText(lf.getLf());
viewHolder.freq.setText((int)lf.getFreq() + "");
return convertView;
}
public void updateItems(List<Lf> lfs) {
this.lfs.clear();
this.lfs.addAll(lfs);
this.notifyDataSetChanged();
}
private class ViewHolder {
final TextView name, freq;
ViewHolder(View view){
name = (TextView) view.findViewById(R.id.text_item_1);
freq = (TextView) view.findViewById(R.id.text_item_2);
}
}
}
Code of MainActivity:
public class MainActivity extends AppCompatActivity {
EditText editText1;
ListView listView;
ListAdapter adapter;
List<Lf> elements = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (EditText) findViewById(R.id.edit_text);
listView = (ListView) findViewById(R.id.fragment_list);
// Working... Elements print on screen
for(int i = 0; i < 10; i++) {
Lf temp = new Lf();
temp.setLf("mean");
temp.setFreq(100);
elements.add(temp);
}
adapter = new ListAdapter(this, R.layout.list_item, elements);
listView.setAdapter(adapter);
}
public void activity_button(View view) {
adapter.updateItems(elements);
}
}
If I click on the button, the existing items on the screen are cleared instead of a new one added. But in debug I see that elements normally passed to ListAdapter.
The problem is that your adapter's lfs's field and your activity's elements field both refer to the same List instance. This happens because you pass elements to the ListAdapter constructor, and then simply assign this.lfs = lfs.
So let's look at what happens when you pass elements to updateItems()...
public void updateItems(List<Lf> lfs) {
this.lfs.clear(); // this.lfs and the input lfs are the same list, so this clears both
this.lfs.addAll(lfs); // input lfs is now empty, so addAll() does nothing
this.notifyDataSetChanged();
}
Probably the best thing to do is to create a copy of the list in your adapter's constructor.
this.lfs = new ArrayList<>(lfs);
Now your adapter and activity will reference different lists, so this.lfs.clear() won't accidentally clear out the very list you're passing to it.

Unable to show checked List View Item in the next Activity

I Have an Activity with a ListView. ListView row consist of 3 TextView and a Checkbox. I want to show the checked list item to another activity. I am using Custom Adapter that extends Cursor Adapter. here's my code for Custom Adapter
class MyCursorAdapter extends CursorAdapter /*implements Serializable*/{
private LayoutInflater inflater;
ArrayList<String> selectedStrings = new ArrayList<>();
private String str;
TextView tv1,tv2,tv3;
public MyCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
View view = inflater.inflate(R.layout.simplecursorrowlayout, viewGroup, false);
return view;
}
#Override
public void bindView(View view, Context context,final Cursor cursor) {
tv1 = view.findViewById(R.id.textView1);
tv2 = view.findViewById(R.id.textView2);
tv3 = view.findViewById(R.id.textView3);
tv1.setText(String.valueOf(cursor.getInt(0)));
tv2.setText(cursor.getString(1));
tv3.setText(cursor.getString(2));
final CheckBox checkBox = view.findViewById(R.id.cBox);
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(((CheckBox)view).isChecked()){
tv1.setText(String.valueOf(cursor.getInt(0)));
tv2.setText(cursor.getString(1));
}
}
});
/*checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b){
//str=tv1.getText().toString()+" "+tv2.getText().toString();
//selectedStrings.add(str);
tv1.setText(String.valueOf(cursor.getInt(0)));
tv2.setText(cursor.getString(1));
}
}
});*/
/* Intent intent = new Intent(view.getContext(),DisplayRecord.class);
intent.putStringArrayListExtra("Selected_Students",selectedStrings);
context.startActivity(intent);*/
}
#Override
public boolean isEnabled(int position) {
return true;
}
}
codes in comments are someother way that I've tried
When using Intent to pass all those data, my app hangs with a Black screen.
I think you could expose the selectedStrings from the adapter.
class MyCursorAdapter extends CursorAdapter Serializable*/{
public ArrayList<String> getSelectedStrings() {
return selectedStrings;
}
// other existing codes
}
And then in the current activity, retrieve it when it's time to move to the next activity.
class MyActivity extends AppCompatActivity {
public void displaySelectedItems() {
Intent intent = new Intent(this, DisplayRecord.class);
intent.putStringArrayListExtra("Selected_Students", adapter.getSelectedStrings());
context.startActivity(intent);
}
// other MyActivity's code
}

Adding onClickListeners to a list view andrioid

I have two java classes below that make a customListView. I got the code from somebody I'm working on an app with but I don't really understand her code. I want to add buttons that will bring you to an new activity when they are clicked, and change the text of "Description of "+itemname[positionof] to be different for each section(she has them all grouped so I can't change each individually).
I know that you can do something like
public void onLeaderboardClick(View view)
{
Intent intent = new Intent(MainActivity.this , Leaderboard.class);
startActivity(intent);
}
to start the new activites but as I've said above I'm just not sure how to split them up indivually so each can have a diffeernt onClickValue
public class ListMainActivity extends Activity {
ListView list;
String[] itemname ={
"Capture The Flag",
"Leaderboard",
"Log out"};
Integer[] imgId={
R.drawable.capturetheflag,
R.drawable.leaderboard,
R.drawable.logout,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_main);
CustomListAdapter adapter=new CustomListAdapter(this, itemname, imgId);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
String Selecteditem= itemname[+position];
Toast.makeText(getApplicationContext(), Selecteditem, Toast.LENGTH_SHORT).show();
}
});
}
}
and
public class CustomListAdapter extends ArrayAdapter<String>{
private final Activity context;
private final String[] itemname;
private final Integer[] imgid;
public CustomListAdapter(Activity context, String[] itemname, Integer[] imgid) {
super(context, R.layout.mylist, itemname);
this.context=context;
this.itemname=itemname;
this.imgid=imgid;
}
public View getView(int position,View view,ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View rowView=inflater.inflate(R.layout.mylist, null,true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.item);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
TextView extratxt = (TextView) rowView.findViewById(R.id.textView1);
txtTitle.setText(itemname[position]);
imageView.setImageResource(imgid[position]);
extratxt.setText("Description of "+itemname[position]);
return rowView;
};
}
You can add individual on click listener to every element in the list item by specifying them in the custom adapter
How do i call onclick listener of a button which resides in listview item
View this question it might be helpful to you
I think you should add a button into row layut layout.
Then in getView() method of Adapter class :
Button btnClick= (Button) rowView.findViewById(R.id.btnClick);
btnClick.setOnClickListener(#Override
public void onClick(View v) {
//todo something with each button
});
For anyone looking back at this question, I ended up making a switch statement
# In your Adapter Class while inflating xml add a buttons as required
# and get the references for that buttons then write onClick on #that button in your getView method of Adapter
public View getView(int position,View view,ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View rowView=inflater.inflate(R.layout.mylist, null,true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.item);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
TextView extratxt = (TextView) rowView.findViewById(R.id.textView1);
Button button =(Button) rowView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do your Work
Launch the Required Intent
}
});
txtTitle.setText(itemname[position]);
imageView.setImageResource(imgid[position]);
extratxt.setText("Description of "+itemname[position]);
return rowView;
};
You will have to use rowView.setOnClickListener() in the getViewMethod of the class custom adapter and inside that you can then specify which activity you wanna go based on the position of the view.

Having problems while trying to populate a todo listview using a custom adaptor?

I want a user to input data through an editable text and I want to receive that data through a custom made listview, for that I am trying to use a custom adapter to add a textfield into my listview, through the tostring() method I have converted the data from the editable textview to a string and I am adding that string within my custom adapter to an Arraylist variable values and I’m trying to display that data through get(0) but either the Arraylist is not populating correctly or the data is not displaying properly because whenever I type something within my editable text and press the add button nothing happens, before this I added the string to an Array Adapter and the listview was populating normally, what am I doing wrong?
public class todoFragment extends ListFragment {
private EditText mToDoField;
private Button mAdd;
UsersAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.todo_title);
}
public class UsersAdapter extends ArrayAdapter<String> {
public Context context;
public ArrayList<String> values;
public UsersAdapter(Context context, ArrayList<String> values) {
super(context, 0, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = LayoutInflater.from(getContext()).inflate(R.layout.todo_list, parent, false);
TextView todoTextView = (TextView) convertView.findViewById(R.id.todo_TextView);
todoTextView.setText(values.get(0));
return convertView;
}
}
#TargetApi(9) // remember this for isEmpty()
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_todo, container, false);
ArrayList<String> todoList = new ArrayList<String>();
mAdapter = new UsersAdapter(getActivity(), todoList);
ListView listViewToDo = (ListView) v.findViewById (android.R.id.list);
listViewToDo.setAdapter(mAdapter);
mToDoField = (EditText) v.findViewById(R.id.todo_editText);
mAdd = (Button)v.findViewById(R.id.add_button);
mAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String toDo = mToDoField.getText().toString().trim();
if (toDo.isEmpty()){
return;
}
mAdapter.values.add(toDo);
mToDoField.setText("");
}
});
return v;
}
}
Firstly, you should not be doing
todoTextView.setText(values.get(0));
Because this will always return the first element of the values list. You should do
todoTextView.setText(values.get(position));
Secondly,
mAdapter.values.add(toDo);
is not really right. It will work, but its not the best practise. Try using something like
mAdapter.add(toDo);
or
values.add(toDo);
Now once you've added the data to the list, you need to notify the adapter that the data set has been changed. This is done by
mAdapter.notifyDataSetChanged();
When you manually update the data don't forget to call:
mAdapter.notifyDataSetChanged();
Instead of mAdapter.values.add(toDo); UsemAdapter.add(toDo);
Look at the Add Method Of ArrayAdpter Class, it Itself use notifyDataSetChanged() so need to write any extra line of code:
public void add(T object) {
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.add(object);
} else {
mObjects.add(object);
}
}
if (mNotifyOnChange) notifyDataSetChanged();
}

Updating ListView On Custom ArrayAdapter

I apologize if this is similar to other threads, but I have yet to find a good solution on how to update the ListView in my custom ArrayAdapter.
I'm extending FragmentActivity in order to create a custom Dialog popup for adding / updating new List entries (which works fine), but I can't seem to get the ListView in ServerActivityArrayAdapter to update after a change is made.
Obviously, adapter.notifyDataSetChanged(); in the ServersActivity class isn't enough, but I'm stumped as to how to get my ListView to update after the Save button is clicked in the ServerDialog popup. Any help would be greatly appreciated!
public class ServersActivity extends FragmentActivity {
private List<Server> server;
private ListView lv;
private ServerActivityArrayAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server_list);
server = getServers();
lv = (ListView) findViewById(android.R.id.list);
adapter = new ServerActivityArrayAdapter(this, R.layout.server_list_item, server);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
showServerDialog(position);
}
});
}
...
private void showServerDialog(int position) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
ServerDialog serverDialog = new ServerDialog(position);
ServerDialog.newInstance();
serverDialog.show(fragmentManager, "server_dialog");
}
ServerDialog class for adding new List entries
public class ServerDialog extends DialogFragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.settings_fragment, container);
context = getActivity().getApplicationContext();
dbh = new DbHandler(context);
etName = (EditText) view.findViewById(R.id.etName);
etAddress = (EditText) view.findViewById(R.id.etAddress);
etPort = (EditText) view.findViewById(R.id.etPort);
swtchNumDoors = (Switch) view.findViewById(R.id.swtchNumDoors);
Button btnSave = (Button) view.findViewById(R.id.btnSave);
loadData();
String title = (!newServer) ? "Edit Server" : "Add A New Server " + ID;
getDialog().setTitle(title);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
server[ID] = String.valueOf(ID);
server[SERVER_NAME] = etName.getText().toString();
server[ADDRESS] = etAddress.getText().toString();
server[PORT] = etPort.getText().toString();
if (server[ADDRESS].isEmpty() || server[PORT].isEmpty()) {
Toast.makeText(context, "Invalid Entry", Toast.LENGTH_LONG).show();
} else {
saveData();
// TODO - notify ServersActivity of change
}
}
});
return view;
}
public class ServerActivityArrayAdapter extends ArrayAdapter<Server> {
private int layout;
private String[][] values;
private int defServer;
private static LayoutInflater inflater;
ServerActivityArrayAdapter class for displaying ListView
public ServerActivityArrayAdapter(Context context, int layout, List<Server> servers) {
super(context, layout, servers);
this.layout = layout;
int i = 0;
values = new String[servers.size()][5];
for (Server server : servers) {
values[i][0] = Integer.toString(server.id);
values[i][1] = server.name;
values[i][2] = server.address;
values[i][3] = Integer.toString(server.port);
values[i][4] = Integer.toString(server.num_doors);
defServer = (server.default_server) ? i : 0;
i++;
}
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private static class ViewHolder {
private TextView tvServerName;
private CheckBox cbDefault;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
try {
if(v == null) {
v = inflater.inflate(layout, parent, false);
holder = new ViewHolder();
holder.tvServerName = (TextView) v.findViewById(R.id.tvServerName);
holder.cbDefault = (CheckBox) v.findViewById(R.id.cbDefault);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.tvServerName.setText(values[position][1]);
holder.cbDefault.setChecked(defServer==position);
} catch (Exception e){
System.out.println(e);
}
return v;
}
You could use an interface and have a method in it maybe named updateListView().
Implement this interface in your FragmentActivity. In the implemented method, add code to update the listView.
And in the button code of your dialog, call ((Interfacename) getActivity).updateListView()
Your problem is in the implementation of the adapter. You are instantiating the ArrayAdapter with a List<Server> object (The super call) but then creating your own two dimensional array values to contain the data. You use the values array for the getView() method yet make no mention or show through code how you actually modify that data to update the adapter.
You should be calling back into the adapter to update it. EG, calling add(), remove(), etc. You only mention updating the DB which has nothing to do with updating your adapter. It's not linked in anyway to the DB. Even if you were to call into the previously mentioned mutate methods on the adapter, they wouldn't work unless you specifically override them. The default ArrayAdapter implementation will modify the List<Server> data and not the values two-dim array you created.
But if you find yourself override those mutate methods to support your values two-dim array...there's no point in subclassing the ArrayAdapter. Part of the point of the ArrayAdapter is handling all the data management for you. In such a situation you should be instead subclassing BaseAdapter.

Categories