I am making a question that could be like a duplicated question, but i have tried everything and nothing worked for me. I have created a listview witch every item has two views, one textview and one checkbox. Its like a multiselect listview. Every item has a level on its own: easy, normal, hard. When a level is chosen from a dropdown: All, Easy, Normal, Hard.. the list changes, just like a filter system.
But when i write listView.getChildAt(i).setVisibility(View.GONE); the content of the row is removed but the space occupied is not released.
Any help?
This is my code:
public class CreatePresentation extends Activity
{
DatabaseHelper db = new DatabaseHelper(this);
MyCustomAdapter dataAdapter = null;
List<Slider> list;
ListView listView;
String Text;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.create_presentation);
displayListView();
checkButtonClick();
}
private void displayListView()
{
list = new ArrayList<Slider>();
ArrayList<Slider> oldList = db.getAllSliders();
for (Slider anOldList : oldList) {
String s = anOldList.toString();
int in = anOldList.getId();
String lev = anOldList.getLevel();
Slider slider = new Slider(in, s, lev, false);
list.add(slider);
}
dataAdapter = new MyCustomAdapter(this, R.layout.list_check_box, list);
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(dataAdapter);
}
private class MyCustomAdapter extends ArrayAdapter<Slider> {
private ArrayList<Slider> list;
public MyCustomAdapter(Context context, int textViewResourceId, List<Slider> list) {
super(context, textViewResourceId, list);
this.list = new ArrayList<Slider>();
this.list.addAll(list);
}
private class ViewHolder {
TextView text;
CheckBox checkbox;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
final Slider slider = list.get(position);
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_check_box, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.sliderTitle);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkBox);
convertView.setTag(holder);
Spinner dropdown = (Spinner)findViewById(R.id.spinner);
String[] items = new String[]{"Tutto", "Facile", "Medio", "Difficile"};
ArrayAdapter<String> adapter = new ArrayAdapter<String (CreatePresentation.this, android.R.layout.simple_spinner_item, items);
dropdown.setAdapter(adapter);
Text = dropdown.getSelectedItem().toString();
holder.checkbox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
Slider slider = (Slider) cb.getTag();
slider.setSelected(cb.isChecked());
}
});
try {
if (list.get(position).getLevel().equals("Facile"))
convertView.setBackgroundColor(Color.parseColor("#477C3D"));
else if (list.get(position).getLevel().equals("Medio"))
convertView.setBackgroundColor(Color.parseColor("#936019"));
else if (list.get(position).getLevel().equals("Difficile"))
convertView.setBackgroundColor(Color.parseColor("#A02307"));
} catch (Throwable e) {
e.printStackTrace();
}
dropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, final int position, long id) {
Text = parentView.getItemAtPosition(position).toString();
try {
if (Text.equals("All")){
Runnable run = new Runnable(){
public void run(){
for (int i = 0; i < list.size(); i++) {
listView.getChildAt(i).setVisibility(View.VISIBLE);
}
}
};
runOnUiThread(run);
}
if (Text.equals("Easy")){
Runnable run = new Runnable(){
public void run(){
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getLevel().equals("Easy")) {
listView.getChildAt(i).setVisibility(View.VISIBLE);
}
else {
listView.getChildAt(i).setVisibility(View.GONE);
}
}
}
};
runOnUiThread(run);
}
if (Text.equals("Normal")){
Runnable run = new Runnable(){
public void run(){
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getLevel().equals("Normal"))
listView.getChildAt(i).setVisibility(View.VISIBLE);
else {
listView.getChildAt(i).setVisibility(View.GONE);
}
dataAdapter.notifyDataSetChanged();
}
}
};
runOnUiThread(run);
}
if (Text.equals("Hard")){
Runnable run = new Runnable(){
public void run(){
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getLevel().equals("Hard"))
listView.getChildAt(i).setVisibility(View.VISIBLE);
else
listView.getChildAt(i).setVisibility(View.GONE);
}
}
};
runOnUiThread(run);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
}
});
holder.checkbox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
Slider slider = (Slider) cb.getTag();
slider.setSelected(cb.isChecked());
}
});
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(slider.getQuestion());
holder.checkbox.setChecked(slider.isSelected());
holder.checkbox.setTag(slider);
return convertView;
}
}
the best way to do this is to remove the item from the list and call dataAdapter.notifyDataSetChanged()
As you want to remove your view but keep your item inside your List I suggest you to use a different method. When the user choose a value that will cause the item to be hide just set that value to your item and then call
dataAdapter.notifyDataSetChanged();
Doing this you have to modify the logic inside your getView(), I mean if you find an item that is eligible to get hide instead of return convertView inside the getView() method of your customAdapter just return an empty view, like this you item won't be shown but it will still be in your list;)
You can use a parent Layout for Yuor item to resolve the issue:
For example:
<LinearLayout ...>
<!-- Here Your item content starts -->
<LinearLayout android:id="#+id/content">
...
</LinearLayout>
<!-- Here Your content ends -->
</LinearLayout>
Java code:
listView.getChildAt(i).getChildAt(0).setVisibility(View.GONE);
just like a filter system. Why "like", why not make it actually filterable? There are two options. Easier one is overriding toString of your slider. Other one is creating custom filter, which wouldn't use object's toString method. However, I don't remember how exactly to do second one, only that it's possible.
Slider:
String toString(){
return this.type;
}
When spinner selection changes:
adapter.getFilter().filter(selectedDifficulty);
This will automatically display items you want to see.
You shouldnt change visibility of views generated by adapter - they change every time when you scroll listview. Instead you should change the behaviour of underlying adapter.
You can try this layout instead of the ListView since there's only 4 filters:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<include
android:id="#+id/filter_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="#layout/<your_listview_adapter>"
android:visibility="visible" />
<include
android:id="#+id/filter_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="#layout/<your_listview_adapter>"
android:visibility="visible" />
<include
android:id="#+id/filter_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="#layout/<your_listview_adapter>"
android:visibility="visible" />
<include
android:id="#+id/filter_4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="#layout/<your_listview_adapter>"
android:visibility="visible" />
</LinearLayout>
When you want to hide one of the filters you can just do something like:
findViewById(R.id.filter_4).setVisibility(View.GONE);
EDIT:
For instance, if you want to add information to a TextView inside the first include you just have to call the View like this:
View filter1 = findViewById(R.id.filter_1);
TextView tv1 = (TextView) filter1.findViewById(R.id.<the_id_of_the_textview);
tv1.setText("StackOverflow filter");
To prevent add another layout in outside of your layout. You just hide the item's all child views, not item itself.
For example:
if(i == 1){ // assume we need hide the first item.
//item itself
ViewGroup parent = ((ViewGroup) holder.convertView);
for (int j = 0; j < parent.getChildCount(); j++) {
parent.getChildAt(j).setVisibility(View.GONE);
}
}
And i have test this code, works fine for me.
Related
I am completely lost and have no idea why my ListView is not being populated. In my method where I am inserting data into my ArrayList, it says my adapter symbol cannot be resolved, but as far as I know I have properly declared the adapter in my onCreate.
Am I correct in assuming that if I have a ListView inside of my activity, set up an ArrayList that fills my adapter, and then tie that adapter to the ListView that my ListView will auto-populate in my activity whenever the array receives information?
Here are my declarations inside of my onCreate.
ListView listView = (ListView) findViewById(R.id.dispScores);
ArrayList<viewScores> savedScores = new ArrayList<viewScores>();
ScoreAdapter adapter = new ScoreAdapter(this, savedScores);
adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
listView.setAdapter(adapter);
These are the methods I am using to add data into my ArrayList.
public View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
EditText input1 = (EditText) findViewById(R.id.scorePrompt);
TextView output1 = (TextView) findViewById(R.id.textTotal);
String blankCheck = input1.getText().toString(); //CHANGE INPUT IN scorePrompt TO STRING
switch (view.getId()) {
case R.id.buttTotal:
if (blankCheck.equals("")) {
Toast blankError = Toast.makeText(getApplicationContext(), "YOU CANT SKIP HOLES JERK", Toast.LENGTH_LONG);
blankError.show();
break;
} else {
int num1 = Integer.parseInt(input1.getText().toString()); //Get input from text box
int sum = num1 + score2;
score2 = sum;
output1.setText("Your score is : " + Integer.toString(sum));
//ATTEMPTING TO WRITE TO ARRAYLIST
viewScores addScore = new viewScores(input1.getText().toString());
adapter.notifyDataSetChanged();
adapter.add(addScore); //WHY DOESNT THIS WORK?
j++;
input1.setText(""); //Clear input text box
break;
}
case R.id.allScores: //CHANGE THIS TO AN EDIT BUTTON, ADD A HOLE NUMBER COUNTER AT TOP OF SCREEN!!!!!
output1.setText("you messed up");
break;
case R.id.editScore: //Need to set up Save Array before we can edit
//CURRENTLY ONLY DISPLAYS THE LAST NUNMBER IN THE TEXTEDIT, NEED TO SET UP LISTVIEW!!!!!!
for (int i=0; i < j; i++){
// output1.setText(savedScores.get(i));
} break;
}
}
};
public class viewScores {
public String hole;
public viewScores(String holeNum) {
this.hole = holeNum;
}
}
public class ScoreAdapter extends ArrayAdapter<viewScores> {
public ScoreAdapter(Context context, ArrayList<viewScores> scores) {
super(context, 0, scores);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
viewScores score1 = getItem(position);
if (convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_main, parent, false);
}
TextView ListView1 = (TextView) convertView.findViewById(R.id.dispScores);
ListView1.setText(score1.hole);
return convertView;
}
}
The app doesn't crash and I am able to enter values into my EditText. Below is the XML for the ListView.
<ListView
android:id="#+id/dispScores"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
app:layout_constraintLeft_toLeftOf="parent"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1"
tools:layout_editor_absoluteY="244dp" />
Whenever you update the model observed by your adapter, you need to call
adapter.notifyDataSetChanged()
So in your case,
viewScores addScore = new viewScores(input1.getText().toString());
savedScores.add(addScore);
adapter.notifyDataSetChanged()
I'm facing a strange behaviour using an ArrayAdapter.
When the number of listview item exceed the height of the listView (say after item 8), the next item get the id 0 instead the id 9.
In my opinion this type of issue was explained here with the convertView, but i use it in the same way (i think).
The following code is my ArrayAdapter.
public class StepsAdapter extends ArrayAdapter<String> {
Context context;
List<String> steps;
public StepsAdapter(Context context, int resourceId, List<String> steps) {
super(context, resourceId, steps);
this.context = context;
}
private class ViewHolder {
EditText stepValue;
ImageView removeStep;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final String step = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row_step, null);
holder = new ViewHolder();
holder.stepValue = (EditText) convertView.findViewById(R.id.stepEdit);
holder.removeStep = (ImageView) convertView.findViewById(R.id.removeStep);
holder.stepValue.setText(step);
holder.removeStep.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"* Remove id step " + position, Toast.LENGTH_LONG).show();
steps.remove(position);
notifyDataSetChanged();
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
Then my main activity where i get existing data and put it in my listView, the add button and the save button.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_game);
mContext = getApplicationContext();
steps = new ArrayList<String>();
stepsAdapter = new StepsAdapter(mContext,R.layout.row_step,steps);
Gson gson = new GsonBuilder().create();
game = gson.fromJson(gameJson, Games.class);
/*
* Settings values
*/
gameNameValue.setText(game.getName());
gameBackgroundPreview.setBackgroundColor(game.getColor());
colorSelected = game.getColor();
for(int i = 0; i < game.getSteps().size() ; i++){
//steps.add(game.getSteps().get(i).toString());
//notifyDataSetChanged();
stepsAdapter.add(game.getSteps().get(i).toString());
}
final ListView listSteps = (ListView) findViewById(R.id.listViewSteps);
listSteps.setAdapter(stepsAdapter);
gameNameValue.setText(gameName);
addSteps.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stepsId = steps.size();
Toast.makeText(getApplicationContext(), "addSteps : " + stepsId, Toast.LENGTH_LONG).show();
stepsAdapter.insert("newstep", stepsId);
}
});
buttonSaveGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String valueEditGameName = gameNameValue.getText().toString();
int valueColorBackaground = colorSelected;
String picture = "testPic";
for(int i=0; i < listSteps.getChildCount(); i++) {
LinearLayout rowLayout = (LinearLayout) listSteps.getChildAt(i);
//Log.e(TAG, ">> :) layout >>" + listSteps.getChildAt(i).getClass().getName());
EditText editRow = (EditText) rowLayout.getChildAt(0);
stepsValues.add(editRow.getText().toString());
//Log.e(TAG, ">> :) inside layout >>" + editRow.getText().toString());
}
if(valueEditGameName.trim().length() > 0 && picture.trim().length() >0 ){
Games game = new Games(valueEditGameName,valueColorBackaground,picture,stepsValues);
String goToSave = game.createJson();
Log.e(TAG, ">>Saved>>" + goToSave);
final CkdFile file = new CkdFile();
String saved = file.writeToSDFile(game.getName(), goToSave);
Toast.makeText(mContext, saved, Toast.LENGTH_LONG).show();
Intent backToMain = new Intent(mContext,MainActivity.class);
startActivity(backToMain);
} else {
Toast.makeText(mContext, "Fill all texts", Toast.LENGTH_LONG).show();
}
}
});
}
I try to add items in 2 different ways :
add item through : List steps
add item through : StepsAdapter stepsAdapter
Both give me same behaviour.
If someone has a clue to help understanding what i'm doing wrong with my implementation of ListView/ArrayAdapter.
Thanks in advance !
EDIT 1 :
After pushing some logs everywere, it understand the strange behaviour :
My adapter have only 6 slots (the limit came from the size of the listview in layout), and when my arraylist have more than 6 items, the getView select items only between 0 and 5.
I'm searching now a way to get the position in ArrayList and not the position in arrayadapter.
I faced same issue recently. Add following overrides to Adapter:
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
I found a simple xml "trick" to avoid this behaviour : i set a biger height to listView.
<ListView
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_gravity="center_horizontal"
android:id="#+id/listViewSteps"
android:layout_margin="10dp">
</ListView>
It's not really resolve but a take it ...
I have a ListView setup which I dynamically add items to with each item having different data. One of the pieces of data is a time/date which is shown in a TextView in my custom List item layout. In the onResume() method of my Fragment I would like to remove items that have a date shown which is before the current date.
The List item layout is as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pi_rl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/pi_tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp" />
<TextView
android:id="#+id/pi_tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/pi_tv_title"
android:textSize="24sp" />
</RelativeLayout>
The idea that I had to solve this was to create a loop, which iterated through all the items checking the content of the date TextView for each item. Then, if the date was before the current date, it would remove the item.
I am currently able to delete items based on there position, but I can't work out how to delete individual list items if they have a certain content.
This is what I have so far:
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
int items = DataModel.getInstance().getPendingItemList().size(); // Number of items in the list
if (items > 0) {
for (int i = 1; i <= items; i++) { // This loops through all my items. Do I want to use position instead?
Log.i("for loop", "" + i);
// This doesn't work because it tries to get the content for all the items not just one.
TextView tv_date = (TextView) getView()
.findViewById(R.id.pi_tv_date);
CharSequence c = tv_date.getText(); // Causes force close
// Here I will have my if(date shown != current date){
//deleteItem
//}
}
}
}
EDIT: This is my adapter code:
private class PendingAdapter extends BaseAdapter { // This happens whenever
// onCreate is called.
private List<Map<String, Object>> mPendingItemList;
public PendingAdapter() {
mPendingItemList = DataModel.getInstance().getPendingItemList();
}
#Override
public int getCount() {
return mPendingItemList.size();
}
#Override
public Object getItem(int position) {
return mPendingItemList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == convertView) {
convertView = LayoutInflater.from(getActivity()).inflate(
R.layout.pending_item, null);
// Log.i("convertView", "was null");
}
TextView tv_title = (TextView) convertView
.findViewById(R.id.pi_tv_title);
TextView tv_date = (TextView) convertView
.findViewById(R.id.pi_tv_date);
HashMap<String, String> itemDataHashMap = (HashMap<String, String>) getItem(position);
tv_title.setText(itemDataHashMap.get("planet"));
tv_date.setText(itemDataHashMap.get("date"));
return convertView;
}
}
EDIT 2:
As per Ali AlNoaimi's answer, I have added this inside my Adapter:
public void refreshMyAdapter() {
if(mPendingItemList.size() > 0) {
List<Map<String, Object>> newPendingList = mPendingItemList;
for (int i = 0; i < mPendingItemList.size(); i++) {
Map<String, Object> item = mPendingItemList.get(i);
TextView tv_title = (TextView) histView
.findViewById(R.id.pi_tv_title);
String s_title;
s_title = tv_title.getText().toString();
Log.i("s_title", s_title);
if(s_title == "foo") {
newPendingList.remove(item);
}
}
mPendingItemList = newPendingList;
}
}
and this to the onResume():
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
final Handler handler = new Handler(); new Thread(new Runnable() {
#Override
public void run() {
while(true) {
handler.post(new Runnable() {
#Override
public void run() {
simpleAdpt.refreshMyAdapter();
simpleAdpt.notifyDataSetChanged();
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
This still does not work.
FINAL EDIT: Ali AlNoaimi's answer did work, I was just comparing strings incorrectly.
I hope this makes sense! Thank you
I'm not sure you understand how ListView works. A ListView is the visual representation of the data in your adapter, so you should never try to edit, add or delete views of a ListView directly, but instead edit the data and then call notifyDataSetChanged() on your adapter.
The ListView will then check for changes in your adapter's data and refresh the views accordingly.
For your specific problem, it means that you should work directly with mPendingItemList, find the items that have a specific content, remove them and then call notifyDataSetChanged().
Add this method to your adapter:
public void refreshMyAdapter() {
private List<Map<String, Object>> newPendingList;
for (int i = 0; i < mPendingItemList.size(); i++) {
Map<String, Object> item = mPendingItemList.get(i);
if(it matches) {
newPendingList.add(item);
}
}
mPendingItemList = newPendingList;
}
and in your main activity, fragment
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
while(true) {
handler.post(new Runnable() {
#Override
public void run() {
yourPendingAdapter.refreshMyAdapter();
yourPendingAdapter.notifyDataSetChanged();
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
Bedst way is to remove the items in the ArrayList you used when creating the adapter then call notifyDataSetChanged(); on the adabter to update the listview.
to have a coherent implementation, keep data processing on the DataModel.
add to DataModel class this method:
public void clearObsoleteItems(){
//TODO: add you implementation to clear the obsolete items from the List of items holded by the singleton class.
}
add on your adapter class PendingAdapter a setter for items list:
public void setPendingItemList(List<Map<String, Object>> mPendingItemList) {
this.mPendingItemList = mPendingItemList;
notifyDataSetChanged();
}
from the activity onResume call:
DataModel.getInstance().clearObsoleteItems();
mAdapter.setPendingItemList(DataModel.getInstance().getPendingItemList());
I'm new to programming and having problem with using getCheckedItemPositions() for check boxes and getting edit values from edit text in custom list view. Can anyone help me with an example to create custom list view which has above functionality. Thanks.
*this is custom listview xml code
<CheckBox android:id="#+id/checkBox" android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:text="CheckBox"
android:onClick="clickHandler"
></CheckBox>
<TextView android:layout_height="wrap_content"
android:layout_width="fill_parent" android:text="TextView"
android:id="#+id/textView1"
android:layout_alignParentLeft="true"
android:layout_centerHorizontal="true" android:layout_marginBottom="14dp"
android:layout_toLeftOf="#+id/checkBox">
*This is code for set up listview
lv1 = (ListView)dialog.findViewById(R.id.l1);
adapter2 = new SimpleCursorAdapter(
this,
R.layout.custom,
cursor2,
new String[] {"ItemName"},
new int[] {R.id.textView1});
lv1.setItemsCanFocus(false);
lv1.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv1.setAdapter(adapter2);
*this what I tried to do when checked
public void onClick(View v) {
int len = lv1.getCount();
SparseBooleanArray checked = lv1.getCheckedItemPositions();
for (int i = 0 ; i < len; i++)
if (checked.get(i)) {
String item = mArrayList.get(i);
mItems.add(mArrayList.get(i));
System.out.println(item);
/* do whatever you want with the checked item */
}
But this is not working. And also I want to use edit text in this manner for getting values.when I checked and click the button app terminate.
The following code will solve your problem.
public class SimpleCursorAdapter extends ArrayAdapter {
private Context mcontext;
private View rowview;
LayoutInflater inflater;
public static ArrayList<Boolean > itemchecked=new ArrayList<Boolean>();
public SimpleCursorAdapter(Context context,ArrayList<String> mylist)
{
super(context,your layout id);
mcontext=context;
//this is the important step
for (int i = 0; i < this.getCount(); i++)
{
itemchecked.add(i,false); // initializes all items value with false
}
}
public View getView(final int position, View convertView, ViewGroup parent) {
rowview=convertView;
if(convertView==null)
{
rowview = inflater.inflate(R.yourlayout, parent, false);
}
TextView textView_heading = (TextView) rowview.findViewById(R.id.textView1);
CheckBox checkbox_detail=(CheckBox) rowview.findViewById(R.id.checkBox1);
checkbox_detail.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
CheckBox cb = (CheckBox) v.findViewById(R.id.checkBox1);
if (cb.isChecked()) {
itemchecked.set(position, true);
// do some operations here
} else if (!cb.isChecked()) {
itemchecked.set(position, false);
// do some operations here
}
}
});
checkbox_detail.setChecked(itemchecked.get(position));
textView_heading.setText(userheading_list.get(position));
return rowview;
}
}
//now the custom list part finish
Now, to get all the information from list and also watch which checkbox is checked:
for(int i=0;i<yourlistadapterobject.getCount();i++)
{
View content_view=msg_adapter.getView(i,null , user_detail_list);
System.out.println("the list count"+user_detail_list.getCount());
if(MyContactAdapter.itemchecked.get(i))
{
System.out.println("is checked true");
TextView tv_heading= (TextView) content_view.findViewById(R.id.textView1);
String text=tv_heading.getText();
}
}
By doing this, you can get all the information against checkbox which is checked.
The code below does NOT change the text of all of a ListView's rows because getChildCount() does not get all of a ListView's rows, but just the rows that are visible.
for (int i = 0; i < listView.getChildCount(); i++)
{
View v = listView.getChildAt(i);
TextView tx = (TextView) v.findViewById(R.id.mytext);
tx.setTextSize(newTextSize);
}
So, what SHOULD I do?
Is there code for getting a notification when a ListView's row becomes visible, so I can set its text size then?
In a ListView the only children are the visible ones. If you want to do something with "all the children," do it in the adapter. That's the best place.
List13 from the API Demos does something similar using OnScrollStateChanged. There may be a better way, though:
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE:
mBusy = false;
int first = view.getFirstVisiblePosition();
int count = view.getChildCount();
for (int i=0; i<count; i++) {
TextView t = (TextView)view.getChildAt(i);
if (t.getTag() != null) {
t.setText(mStrings[first + i]);
t.setTag(null);
}
}
mStatus.setText("Idle");
break;
.
.
.
EDIT BY Corey Trager:
The above definitely pointed me in the right direction. I found handling OnScrollListener.onScroll worked better than onScrollStateChanged. Even if I removed the case statement in onScrollSgtaetChanged and handled every state change, some text wasn't getting resized. But with onScroll, things seem to work.
So, my seemingly working code looks like this:
public void onScroll(AbsListView v, int firstVisibleItem, int visibleCount, int totalItemCount)
{
ListView lv = this.getListView();
int childCount = lv.getChildCount();
for (int i = 0; i < childCount; i++)
{
View v = lv.getChildAt(i);
TextView tx = (TextView) v.findViewById(R.id.mytext);
tx.setTextSize(textSize);
}
}
Not so sure about the performace effect but u can try this.
//declare the list
ListView list = (ListView)findViewById(R.id.yourListID);
// in my case i have spinners and made a test just to know if this works
Spinner spnWhatever;
View view;
int i =0;
do{
view =list.getAdapter().getView(i,null,null);
//get the spinners from each row
spnWhatever =(Spinner)view.findViewById(R.id.spnTarifas);
i++;
}while(list.getAdapter().getCount() !=i);
//Create layout file containing views you want to read input from
//layout/gen_edt_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parLay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edtGName"
android:layout_width = "match_parent"
android:layout_height ="wrap_content"
android:hint="Name"
android:inputType="text" />
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edtGIdPass"
style="#style/edt"
android:hint="Id number"
android:inputType="number" />
</LinearLayout>
//Create Empty Activity -> MultipleInput
//layout/activity_multiple_input.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".OpenAccount">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ListView
android:id="#+id/inputLView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp" />
</LinearLayout>
<Button
android:layout_width="wrap_content
android:layout_height="wrap_content"
android:text="Read"
android:onClick="readInput"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent>
</androidx.constraintlayout.widget.ConstraintLayout>
public class MultipleInput extends AppCompatActivity {
//Declare and intialize arrays to store input fields as public modifiers
ArrayList<TextInputEditText> edtNameArr = new ArrayList<>();
ArrayList<TextInputEditText> edtIdsArr = new ArrayList<>();
//Intialize arrays to store input values as public modifiers
ArrayList<String> arr0 = new ArrayList<>();
ArrayList<String> arr1 = new ArrayList<>();
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
listView = findViewById(R.id.listView);
edtNameArr.clear();
edtIdsArr.clear();
arr0.clear();
arr1.clear();
//set number of group fields to be generated
int members = 4;
//initialize class passing fields number and context
edtAdapter = new EdtAdapter(members, getApplicationContext());
//Set retured fields in listView
listView.setAdapter(edtAdapter);
}
public class EdtAdapter extends BaseAdapter {
class ViewHolder {
TextInputEditText edtGName, edtGIdPass;
}
public Context context;
ArrayList<EdtClass> edtArrayList;
int members;
EdtAdapter(int members, Context context) {
this.members = members;
this.context = context;
}
#Override
public int getCount() {
return members;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View contentView, ViewGroup parent) {
View rowView = contentView;
if (rowView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = getLayoutInflater();
rowView = inflater.inflate(R.layout.gen_edt_layout, parent, false);
viewHolder.edtGName = rowView.findViewById(R.id.edtGName);
viewHolder.edtGIdPass = rowView.findViewById(R.id.edtGIdPass);
viewPosition = position;
//loop adding input fields in arrays
for (int i = 0; i < members; i++) {
edtNameArr.add(viewHolder.edtGName);
edtIdsArr.add(viewHolder.edtGIdPass);
}
} else {
viewHolder = (ViewHolder) contentView.getTag();
}
return rowView;
}
}
//Read input when button clicked
public void readInput(View view){
for(int edt = 0; edt<edtNameArr.size(); edt++){
String name = Objects.requireNonNull(edtNameArr.get(edt).getText()).toString();
if(!arr0.contains(name)) {
arr0.add(name);
}
String ids = Objects.requireNonNull(edtIdsArr.get(edt).getText()).toString();
if(!arr1.contains(ids)) {
arr1.add(ids);
}
}
StringBuilder name = new StringBuilder();
StringBuilder idno = new StringBuilder();
//loop through arrays with input, reading and appending values in StringBuilder
for (int m = 0; m < arr0.size(); m++) {
name.append(arr0.get(m)).append(",");
idno.append(arr1.get(m)).append(",");
}
//Show input values in logcat/Toast
Log.e("Names ", name.toString());
Log.e("Ids ", idno.toString());
Toast.makeText(MultipleInput.this, "Names "+ name.toString(), Toast.LENGTH_LONG).show();
}