I have a listview in an android app with checkboxes and I'm trying to get a list of the items that are checked. I have tried both setting the checked state in the getView() method with setChecked(true) and by checking it manually by tapping on the item. I've tried two different methods for getting the checked items and both return null. What am I doing wrong?
Greg
//Called from a menu
//First attempt - checked is always null
//I also set setChoiceMode = CHOICE_MODE_MULTIPLE before setting adapter
//and set no setChoiceMode
String ItemsChecked = null;
ListView listview = (ListView) findViewById(R.id.ListLists);
SparseBooleanArray checked = listview.getCheckedItemPositions();
for (int i = 0; i < checked.size(); i++) {
if (checked.get(i)) {
ItemsChecked += Integer.toString(i) + ",";
}
}
//I then tried this and checked[] is empty
//I also set setChoiceMode = CHOICE_MODE_NONE before setting adapter
long checked[] = listview.getCheckedItemIds();
for (int i = 0; i < checked.length; i++) {
ItemsChecked += "" + checked[i] + ",";
}
//Layout for the ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/icon"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="4dp"
android:src="#drawable/ic_listit" >
</ImageView>
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
<TextView
android:id="#+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="22sp" >
</TextView>
</LinearLayout>
I am not sure you have provided enough information to solve the problem. But here are some troubleshooting steps that may help point you in the right direction:
1) Instead of getting an array based on the number of checked items in the listView, see if you can pull the array of items in the entire list, or at least the first 100 if the list is very large. Then output the index number of each item in a string like you had in your first attempt. You could also try and output whether the current item is checked or not.
this will tell you if you have a populated list to pull from. If you don't, well there's your problem.
2) I would also check to make sure that your listView's name is also correct. I would assume the compiler would catch this but you never know.
3) Finally, I can't see where or how the list is populated. It may be a good idea to check and see the rest of the code to see if maybe something is happening somewhere else.
Sorry if this is not particularly helpful. If all of this checks out and the problem is not being created in one of those areas this link may help:
Android: list.getCheckedItemPositions() always returns null
Good Luck and I hope this helps a little.
Max,
Well, you pointed me in the right direction for a 'solution'. This may not be the proper way to do it, but given this is my my first android app, I am ready to move on after spending the entire morning trying to get a list of just those items that are checked with a built-in method. I modified code from the link you posted and came up with the code below. It seems to work.
I wonder if I will have problems with lists that don't show everything at once. My test only has two items in the list. If items are checked and then scrolled out of view, will this work. More testing needs to be done.
Thanks,
Greg
ListView listview = (ListView) findViewById(R.id.ListLists);
View v;
CheckBox ck;
TextView tv;
for (int i = 0; i < listview.getCount(); i++) {
v = listview.getChildAt(i);
ck = (CheckBox) v.findViewById(R.id.checkBox1);
tv = (TextView) v.findViewById(R.id.label);
if (ck.isChecked()) {
Toast.makeText(getApplicationContext(), tv.getText() + "Checked" , Toast.LENGTH_LONG)
.show();
}
else {
Toast.makeText(getApplicationContext(), tv.getText() + "Not checked" , Toast.LENGTH_LONG)
.show();
}
}
Related
Click on the button event.
public void onClick(View view) {
Button result = view.findViewById(view.getId());
textNo[R.id.t1].setText("2");
Toast.makeText(getActivity(),"클릭 : " + result.getText().toString(),Toast.LENGTH_SHORT).show();
}
For example, is there a way to change the value of the first text view by clicking the first button?
There are countless buttons, so I gave resource id to each button and text
Now, for example, only 5 buttons and text views are given.
for (i = 0; i < 5; i++) {
String textId = "t" + (i + 1);
String buttonId = "b" + (i + 1);
textNo[i] = view.findViewById(getResources().getIdentifier(textId, "id", getActivity().getPackageName()));
buttonNo[i] = view.findViewById(getResources().getIdentifier(buttonId, "id", getActivity().getPackageName()));
When I press the button on the same line, I want to increase the number of text views located on it, but I kept trying, but I couldn't figure out how to do it in the fragment.
enter image description here
The outline of the XML code is as follows.
<TextView
android:id="#+id/t1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center"
android:text="#string/zero" />
<Button
android:id="#+id/b1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/button"
android:layout_weight="1"
android:text="#string/Click"
style="?android:attr/buttonBarButtonStyle" />
It's my first time asking this question, so I'm very inexperienced, but if you tell me, I'll try harder.
I'm sorry that I'm not good at English.
b1.setOnClickListener {
t1.text = "tttt"
}
If u have only a few buttons, you can write them in xml. For more, use horizontal RecyclerView.
You should use RecyclerView in this case. Your method isn'n correct
If I have too many checkboxes ( more than 50 ) , is there a way i could use the mapping of the checkboxes , inside for loop ? and how will i assign the int inside the findViewById(int).
Something like this : - (array of checkboxes)
for(int i=0 ; i<=99; i++)
checks[i] = (CheckBox)findViewById(what-about-this-int-id);
You can look up resource id's dynamically too using getResources().getIdentifier(..):
https://stackoverflow.com/a/14058142/1715829
If you have a container element where all those checkboxes reside then you can simply get all its checkbox children by casting it to ViewGroup
ViewGroup container = (ViewGroup)findViewById(R.id.container);
for (int i = 0; i < container.getChildCount(); i++){
CheckBox cb = (CheckBox)container.getChildAt(i);
// attach listener etc
}
I know you might have found your solution but just in case others couldn't find a proper one, i'll post mine here.
Let's say you labelled your "findViewById" like this:
<CheckBox
android:id="#+id/checkbox0"
android:layout_width="0dp"
android:layout_weight="1"
android:padding="5dip"/>
<CheckBox
android:id="#+id/checkbox1"
android:layout_width="0dp"
android:layout_weight="1"
android:padding="5dip"/>
.
.
.
<CheckBox
android:id="#+id/checkbox50"
android:layout_width="0dp"
android:layout_weight="1"
android:padding="5dip"/>
You can do something like this to "findViewById" using a few lines instead of
writing 50 "findViewById" lines:
CheckBox[] cb = new CheckBox[51];
for (int i = 0; i < 51; i++) {
String idCheckBox = "checkbox"+i;
cb[i] = (CheckBox) findViewById(YourActivity.this.getResources().getIdentifier(idCheckBox, "id", getPackageName()));
}
where "YourActivity.this" refers to the context.
1) What for are there 50+ checkboxes?
If you have a list with checkboxes you should use ViewHolder to store info about each row.
2) Try to avoid findViewById each time when you need an item.
findViewById is an expensive operation so you should cache you items (for this very purposes ViewHolder was created).
I have 5 checkboxes in my activity xml. I need to get the text of all the selected checkboxes.
One approach is to see if checkbox1 ischecked() and get the text.
if(checkbox1.isChecked())
{ String text=checkbox1.getText().toString();}
and so on.
This becomes quite a lengthy process.
Is there any other approach I can use?
A couple of basic suggestions:
You do not need to ==true operation above so a simple if(checkbox1.isChecked()) would suffice.
Store them all in an ArrayList so you can iterate as below:
List<CheckBox> items = new ArrayList<CheckBox>();
for (CheckBox item : items){
if(item.isChecked())
String text=item.getText().toString();
}
CheckBox[] nameString = new CheckBox[]{Array1, Array2, Array3, Array4, Array5, Array6, Array7, Array8};
for (int i=0; i<=7; i++)
{
if (nameString[i].isChecked())
{
Toast.makeText(getApplicationContext(), nameString[i].getText().toString(), Toast.LENGTH_SHORT).show();
}
}
Rather than looping through all your checkBoxes to find which one of them is checked, you could simply create a List of selected items at onCHeckedChanged() or onClick()
If(unChecked)==>Add to List==> if(Checked) ==> Remove from list
Kotlin sample code:
You can create an event and bind same event to all the check boxes, like
<CheckBox
android:id="#+id/chk1"
android:onClick="onCheckBoxClicked" ....
<CheckBox
android:id="#+id/chk2"
android:onClick="onCheckBoxClicked" ....
MainActivity:
fun onCheckBoxClicked(view:View){
view as CheckBox
if (view.isChecked){
var msg = view.text.toString()
Log.d("Checkbox", msg) //printing in log
}
I'm trying to make an HighscoreList for my App.
This List is based on a SQL Database. Save the name and the score is working very well.
The ListView is based on this row xml File:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingTop="4dip"
android:paddingBottom="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView android:id="#+id/NAME_CELL"
android:layout_width="250dip"
android:layout_height="wrap_content"
android:textSize="20dip" />
<TextView android:id="#+id/SCORE_CELL"
android:layout_width="20dip"
android:layout_height="wrap_content"
android:textSize="20dip" />
<ImageView android:id="#+id/PICTURE_CELL"
android:layout_width="50dip"
android:layout_height="20dip"
android:src="#drawable/no_picture" />
And I want that for example if the player reaches a score of 10 the PICTURE_CELL ImageView should show an Image.
For now I have a Cursor which is going through the Database and looks for the Highscores:
public void drawPictures()
{
if (dbCursor.moveToFirst()) {
do
{
if(dbCursor.getInt(2)<=4)
{
Log.d(TAG, "no picture");
}
else if((dbCursor.getInt(2) > 4) && (dbCursor.getInt(2) <= 9))
{
Log.d(TAG, "picture1");
}
else if((dbCursor.getInt(2) > 9) && (dbCursor.getInt(2) <= 19))
{
Log.d(TAG, "picture2");
}
else if(dbCursor.getInt(2) > 20)
{
Log.d(TAG, "picture3");
}
}
while (dbCursor.moveToNext());
But I have no Idea how I can change the Resource of every ImageView in each row.
Please help me, this is killing me for days!
Thanks!
You have to create a custom adapter to do this kind of processing. A simple cursor will not do that for you.
Sample:
http://android.vexedlogic.com/2011/04/02/android-lists-listactivity-and-listview-ii-%E2%80%93-custom-adapter-and-list-item-view/
While this example uses an ArrayAdapter, it doesn't matter that much to the processs. The process s the same. You must create your own custom adapter. Once you create your custom cursor class, then you will override the getView(...) method with your preprocessing logic.
Explanation of comment
In your database helper:
public static final int COL_NAME = 2;
In your code,
dbCursor.getInt([Database Helper Object].COL_NAME)
I don't fully follow your drawPictures method but I would suggest you make your query include an ORDER keyword so your values are ordered rather than searching.
Then in the adapter getView method use getCursor().getInt(<score column>) and check if the score is greater than 10
if(score > 10)
If it is you can do:
ImageView imageView = ( ImageView ) view.findViewById( R.id.PICTURE_CELL )
then call:
// where drawable is whatever image you would like to present
imageView.setImageDrawable(Drawable drawable)
UPDATE from comments
Your SimpleCursorAdapter is a sublcass of CursorAdapter which does have getView, you just need to extend your SimpleCursorAdapter and add the method below.
You need to over ride this methods like so:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int score = dbCursor.getInt(<score column>)
// You might need to call moveToPosition(position) or maybe you should use getItem(position) I have not tested it
if(score > 10) {
ImageView imageView = ( ImageView ) view.findViewById( R.id.PICTURE_CELL )
// where drawable is whatever image you would like to present
imageView.setImageDrawable(Drawable drawable)
}
}
I'm facing a problem while trying to create Checkboxes Dynamic in my application. The design works fine, and I'm able to create as many Checkboxes as i want. The Checkboxes are put into a TableRow together with a TextView so that the text is at left side of the checkbox. But my problem is, that in my activity i can get the "status" of the checkbox, whether it's checked or not.
I use the inflater to create my Checkboxes. The xml for the checkboxes:
<TableRow xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/TableRow" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:paddingLeft="20dip" android:id="#+id/tv_effect" android:gravity="left" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textColor="#000" android:textSize="18dip" android:layout_width="wrap_content"></TextView>
<CheckBox android:id="#+id/cb_effect" android:layout_height="wrap_content" android:text="" android:layout_gravity="right" android:layout_width="wrap_content"></CheckBox>
The function i call to create a new tablerow containing a textview and a checkbox:
public void layoutMakeSpeakerEffect(String effectName,int effectNumber)
{
LayoutInflater linflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View myViewSp = linflater.inflate(R.layout.speaker_settings, null);
final TextView tv_effect = (TextView) myViewSp.findViewById(R.id.tv_effect);
tv_effect.setId(effectNumber);
tv_effect.setText(effectName);
final CheckBox cb_effect = (CheckBox) myViewSp.findViewById(R.id.cb_effect);
cb_effect.setId(effectNumber);
cb_effect.setText("");
cb_effect.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(cb_effect.isChecked())
{
Toast toast = Toast.makeText(getApplicationContext(), ""+tv_effect.getText()+": ON", Toast.LENGTH_SHORT);
toast.show();
}
else
{
Toast toast = Toast.makeText(getApplicationContext(), ""+tv_effect.getText()+": OFF", Toast.LENGTH_SHORT);
toast.show();
}
}
});
tl_speakerSettings.addView(myViewSp);
}
And as mentioned, the design works fine.
But how am I able to outside this function to get the "status" off the checkbox?
And i also need a function that could clear the checkboxes status, and another function that could enable and disable the checkboxes?
I can't seem to figure this problem out by myself.
My only idea, is to make something that checks the "cb_effects" ID and afterwards checks the status of the desired checkbox.
Use setOnCheckedChangeListener instead. It will fire the onCheckedChanged(CompoundButton buttonView, boolean isChecked) method, where you can now the state of the checkbox reading the isChecked variable.
You can make use of a global integer array that will contain as many elements as there are rows in table. Set the value of the element to 1 if checkbox is checked and 0 for unchecked. By finding which element is having 1 you can fing which of the checkboxes are checked. Hope this works for you.