how can I limit the number of checked checkboxes in android? I have multiple checkboxes being added programatically and it's difficult to keep track of them.
here's the code used to add them:
final CheckBox currentVariantCheckbox = new CheckBox(getApplicationContext());
checkBoxGroupList.add(currentVariantCheckbox);
Log.d(TAG, "onDataChange: added " + currentVariantCheckbox + " to the checkboxgrouplist; size = " + checkBoxGroupList.size());
currentVariantCheckbox.setChecked((Boolean) currentVariant.child("checked").getValue());
LinearLayout checkboxGroupLayout = new LinearLayout(getApplicationContext());
checkboxGroupLayout.setOrientation(LinearLayout.HORIZONTAL);
currentVariantCheckbox.setText(currentVariant.child("name").getValue(String.class));
TextView currentVariantPriceTag = new TextView(getApplicationContext());
checkboxGroupLayout.addView(currentVariantCheckbox);
if (currentVariant.child("price").exists()) {
currentVariantPriceTag.setText("+" + currentVariant.child("price").getValue(float.class).toString() + " €");
checkboxGroupLayout.addView(currentVariantPriceTag);
ok so instead of using a onCheckedStateChangedLister I used OnClickListener. And I created an ArrayList to keep track of all the checked checkboxes:
final ArrayList<CheckBox> checkedList = new ArrayList<>();//this is the list to keep track of checked checkboxes
int maxOptions = 3
int minOptions = 1
currentVariantCheckbox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Boolean currentCheckState = currentVariantCheckbox.isChecked();
if (currentCheckState) {//if the clicked checkboxes was unchecked and is now checked
checkedList.add(currentVariantCheckbox);
Log.d(TAG, "onClick: added " + currentVariantCheckbox + " ;checkedList.size is now: " + checkedList.size());
if (checkedList.size() >= maxOptions) {
checkedList.get(0).setChecked(false);
checkedList.remove(0);// if limit exceeded remove the first element from the checked list
Log.d(TAG, "onCheckedChanged: checkedList's size is now: " + checkedList.size());
}
} else if (checkedList.size() <= minOptions) {
currentVariantCheckbox.setChecked(true);
// if the list is empty just add the clicked checkbox to the list for example here 0
// and it will be checked automatically
} else {
checkedList.remove(currentVariantCheckbox);
// if the checkbox was already checked and no limit is exceeded
// then it will be unchecked therfore it should be removed from checkedList
}
}
});
Related
I have a custom view called TinderStackLayout.
At a certain part of the code I am deleting a child view of it and re-adding it back at the last position possible -
private void handleViewAfterAnimation(View view, boolean shouldSkipView) {
Log.d("card view - ", "inside handleViewAfterAnimation");
isCardAnimating = false;
TinderStackLayout tinderStackLayout = (TinderStackLayout) view.getParent();
if (tinderStackLayout == null)
return;
tinderStackLayout.removeView(view);
if (shouldSkipView)
tinderStackLayout.addCard((TinderCardView) view, tinderStackLayout.getChildCount() - 1);
//this part is for debugging purpose
for (int i = 0; i < tinderStackLayout.getChildCount(); i++) {
View childAt = tinderStackLayout.getChildAt(i);
if (childAt instanceof TinderCardView)
Log.d("card view - ", "child cards after deletion - " + (((TinderCardView) childAt).usernameTextView.getText()));
}
}
here is my addCard() method -
public void addCard(TinderCardView tinderCardView, int addToPosition) {
View topCard = getChildAt(0);
if (topCard != null && topCard.equals(tinderCardView)) {
return;
}
topCardOnStack = tinderCardView;
ViewGroup.LayoutParams layoutParams;
layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
addView(tinderCardView, addToPosition, layoutParams);
// tinderCardView.animate()
// .x(0)
// .setInterpolator(new AnticipateOvershootInterpolator());
}
What I don't understand is what I get in the UI -
I have 3 cards.
I press the button, one card is being animated away, the second one is being shown. I press the button again, the second one animates away. I press the last one and the button does not work anymore. What I want to achieve is the first card appearing now behind the last one.
Here is what I get when logging the values out -
seems correct, it was before clicking 3 2 1 and now 2 3 1. The next one should be 1 2 3, but this is what I get for the next one -
goes back to 3 2 1 instead of 1 2 3. I can't figure out why. ?
Edit:
found the reason why this is happening, I am giving a view which should always be the top card on the stack but I am actually not giving the top card because I am always adding a new card. Here is the method -
public void handleButtonPressed(int buttonTag) {
Log.d("card view - ", "inside handleButtonPressed");
TinderStackLayout tinderStackLayout = ((TinderStackLayout) this.getParent());
TinderCardView topCard = (TinderCardView) tinderStackLayout.getChildAt(tinderStackLayout.getChildCount() - 1);
if (isCardAnimating) {
return;
}
switch (buttonTag) {
case DELETE_BUTTON_PRESSED:
isCardAnimating = true;
deleteCard(topCard);
break;
case PASS_BUTTON_PRESSED:
Log.d("card view - ", "inside pass button pressed");
isCardAnimating = true;
passCard(topCard);
Log.d("card view - ", "top card Value before pass - " + topCard.displayNameTextView.getText());
Log.d("card view - ", "child count - " + tinderStackLayout.getChildCount());
for (int i = 0; i < tinderStackLayout.getChildCount(); i++) {
View childAt = tinderStackLayout.getChildAt(i);
if (childAt instanceof TinderCardView)
Log.d("card view - ", "child cards before deletion - " + (((TinderCardView) childAt).usernameTextView.getText()));
}
break;
case APPROVE_BUTTON_PRESSED:
showLawyerContactDetailsFragment(topCard);
break;
}
}
I am trying to do TinderCardView topCard = (TinderCardView) tinderStackLayout.getChildAt(tinderStackLayout.getChildCount() - 1) in order to get the top card in my stack, which would be correct if I delete the cards and not re-add them to my stack but that is not the case when re-adding them. What should be the solution for always getting the top card when I am adding new views all the time?
If you want to shuffle cards, then you don't need to delete and re-add them. You simply need a data structure, which will do it for you. For your use case you can use Circular Array.
private CircularArray cardArray; //declaration
Now when you are adding your views, add it to your card array also.
cardArray.addLast(tinderCardView);
addView(tinderCardView); // add to your layout.
Then use this code to check.
int shuffleCount = 3;
for (int i = 1; i <= shuffleCount; i++)
shuffleTopCard(i);
Finally shuffleTopCard() method.
private void shuffleTopCard(int shuffleID) {
Log.d(TAG, "shuffleTopCard: cards before shuffle");
for (int i = 0; i < cardCount; i++)
Log.d(TAG, "shuffleTopCard: " + ((TinderCardView) cardArray.get(i)).getTag());
TinderCardView cardView = (TinderCardView) cardArray.popLast();
Log.e(TAG, "shuffleTopCard: top cardID = " + cardView.getTag());
cardArray.addFirst(cardView);
Log.d(TAG, "shuffleTopCard: cards after shuffling " + shuffleID + " time");
for (int i = 0; i < cardArray.size(); i++)
Log.d(TAG, "shuffleTopCard: " + ((TinderCardView) cardArray.get(i)).getTag());
Log.e(TAG, "shuffleTopCard: after shuffle top card = " + ((TinderCardView) cardArray.getLast()).getTag());
}
Use of CircularArray will free you from head-ache of maintaining card position manually and also separates your CustomViewGroup and card shuffling logic thereby resulting in loosely-coupled code.
I am using counter value for counting my ListView items. But when I am scrolling down and back scrolling up it still count value inside of my code and changes values.
This values should 1 and 2 instead of 7 and 8...
Here is my code
DatabaseReference myQuery = databaseReference.child("Tests").child(PIN).child("Questions");
FirebaseListAdapter<QuizStatistic_list> adapter = new FirebaseListAdapter<QuizStatistic_list>(this, QuizStatistic_list.class, R.layout.list_quiz_statistic, myQuery) {
#Override
protected void populateView(View v, QuizStatistic_list model, int position) {
TextView quizQuestion, questionNumber, ansA, ansB, ansC, ansD;
quizQuestion = (TextView) v.findViewById(R.id.textView_quizQuestion);
questionNumber = (TextView) v.findViewById(R.id.textView_questionNumber);
ansA = (TextView) v.findViewById(R.id.textView_ansA);
ansB = (TextView) v.findViewById(R.id.textView_ansB);
ansC = (TextView) v.findViewById(R.id.textView_ansC);
ansD = (TextView) v.findViewById(R.id.textView_ansD);
quizQuestion.setText(model.getQuestion());
questionNumber.setText(counter.toString());
ansA.setText("A: " + model.getAnswerA());
ansB.setText("B: " + model.getAnswerB());
ansC.setText("C: " + model.getAnswerC());
ansD.setText("D: " + model.getAnswerD());
//This value counts listview items
counter++;
}
};
questionsList.setAdapter(adapter);
use position instead of counter.!
questionNumber.setText(""+position+1);
position is index number of your array list .!
so it will start from 0 by adding one it will show your desired result first number will be index 0+1=1;
maybe it will help u like
I have 4 textviews which take their values from dropdown list (spinner) selected at previous screen.
There can be either 2 or 4 numbers/letters as result of this selection.
The first position will always be a number and the second position will always be a letter. The third position can be a number or blank and the fourth position can be a letter or blank.
If position 3 and position 4 are blank then I need to make them equal to positions 1 & 2 respectively.
String myGrade = intent.getStringExtra("parameter_name_grade");
// above takes value of 'myGrade' from spinner selection at previous screen
String mDisplayGradeNumberEff = (" " + myGrade.charAt(0));
TextView displayGradeNumberEff = (TextView) findViewById(R.id.gradeNumberEffTV);
displayGradeNumberEff.setText(mDisplayGradeNumberEff);
String mDisplayGradeLetterEff = (" " + myGrade.charAt(1));
TextView displayGradeLetterEff = (TextView) findViewById(R.id.gradeLetterEffTV);
displayGradeLetterEff.setText(mDisplayGradeLetterEff);
// above works correctly
// from here down only works when a character is present in both positions
// if positions 3(2) and 4(3) are empty app stops running.
String mDisplayGradeNumberDia = (" " + myGrade.charAt(2));
if (mDisplayGradeNumberDia.isEmpty()) {
mDisplayGradeNumberDia = mDisplayGradeNumberEff;
}
TextView displayGradeNumberDia = (TextView) findViewById(R.id.gradeNumberDiaTV);
displayGradeNumberDia.setText(mDisplayGradeNumberDia);
String mDisplayGradeLetterDia = (" " + myGrade.charAt(3));
if (mDisplayGradeLetterDia.isEmpty()) {
mDisplayGradeLetterDia = mDisplayGradeLetterEff;
}
TextView displayGradeLetterDia = (TextView) findViewById(R.id.gradeLetterDiaTV);
displayGradeLetterDia.setText(mDisplayGradeLetterDia);
}
I Guess you have a array out of bounds exception, please provide Logcat....
Check if "myGrade" has 3/4 Characters, if it does not you can't read them with charAt(3)...
You can check the length of the String with "myGrade.length()"
When I asked this question I was fairly new to the site and didn't understand that I should post back the solution for future reference. Solution below worked so thanks to rocket for your help and sorry for the delay!
int myGradeLength = mGrade.length();
if (myGradeLength != 4) {
mDisplayGradeNumberEff = ("" + mGrade.charAt(0));
mDisplayGradeLetterEff = ("" + mGrade.charAt(1));
mDisplayGradeNumberDia = ("" + mGrade.charAt(0));
mDisplayGradeLetterDia = ("" + mGrade.charAt(1));
} else {
mDisplayGradeNumberEff = ("" + mGrade.charAt(0));
mDisplayGradeLetterEff = ("" + mGrade.charAt(1));
mDisplayGradeNumberDia = ("" + mGrade.charAt(2));
mDisplayGradeLetterDia = ("" + mGrade.charAt(3));
}
This is how i add shared preferences
ct = sp.getInt("count", 0);
if (ct > 0) {
for (int i = 0; i <= ct; i++) {
list.add(sp.getString("Value[" + i + "]", ""));
}
}
adp = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, list);
Listtt.setAdapter(adp);
btnad.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
sped.putString("Value[" + ct + "]", editText.getText().toString());
sped.commit();
list.add(sp.getString("Value[" + ct + "]", ""));
ct += 1;
sped.putInt("count", ct);
adp.notifyDataSetChanged();
}
});
And by this i can successfully delete Sharedprefrences Value and remove it from list
sp.edit().remove("key_to_remove").apply();
adp.remove("name_to_rmv");
adp.notifyDataSetChanged();
Now my problem is that it leaves the blank space when i call it back just like closing activity and opening it again the value i have deleted has the blank space . Just like this image below i have deleted " two " but when i close and open my application it gives me blank space
how i fill adapter
ct = sp.getInt("count", 0);
if (ct > 0) {
for (int i = 0; i <= ct; i++) {
list.add(sp.getString("Value[" + i + "]", ""));
}
}
adp = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, list);
Listtt.setAdapter(adp);
.
I've met the same problem. I figured out a way to do this. This may not be the best way but it do what needs to be done. You will have to
decrease each and every value after the deleted value in SP by 1
if you have values in sp like
"value[0]","one"
"value[1]","two"
"value[2]","three"
"value[3]","four"
after deleted "value[1]", it would be
"value[0]","one"
"value[2]","three"
"value[3]","four"
(that's why it returns null string when you try to fetch "value[1]" because there are no such a value)
so make them a continues by inserting "value[1]". That means modify your existing value ("value[2]","three") as ("value[1]","three"). and apply this to other values also. you can simply do this by with a for loop. Then your final values would be like this.
"value[0]","one"
"value[1]","three"
"value[2]","four"
As you can see there won't be any blank spaces when you reading back. You will have to decrease counter by 1 because now there are only 3 values.
void deleteItem(int element_num,int counter,SharedPreferences sp,ArrayAdapter<String> adp){
//element_num is the element number that you want to delete
String name_to_rmv=sp.getString("Value[" + element_num + "]", ""); //backup the value that needs to be deleted
SharedPreferences.Editor editor=sp.edit();
for(int i=element_num;i<counter;i++)
editor.putString("Value[" + i + "]", sp.getString("Value[" + (i+1) + "]", "")); //read i+1 value and store it to i
counter--; //decrease counter
editor.putInt("count", counter);
editor.commit();
adp.remove(name_to_rmv);
adp.notifyDataSetChanged();
}
I have developed a code in which i have populated list view dynamically.
now i want to delete the selected item from list view on button click(on pressing delete button)
I have searched out this in this site but didn't got any exact solution so i am posting this question
please help me how to do this :
code on delete buttons onClickListener is as shown below :
DeleteButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if (idx >= 0) {
Log.v("Item index deleted", idx + "");
idx = OdrLst.getCheckedItemPosition();
String delete = (String) ((OdrLst.getAdapter())
.getItem(idx));
// Long deteteId = OdrLst.getAdapter().getItemId(idx);
Log.d("Item deleted", delete);
Log.d("adapter count before", adapter.getCount() + "");
Log.d("lv count before", OdrLst.getCount() + "");
// Log.d("listitems count before", listItems.+"");
adapter.remove(delete);
//listItems.remove(idx);
adapter.notifyDataSetChanged();
OdrLst.setAdapter(adapter);
// OdrLst.removeViewAt(idx);
// adapter.clear();
Log.d("adapter count after", adapter.getCount() + "");
Log.d("lv count after", OdrLst.getCount() + "");
//adapter.notifyDataSetChanged();
// Log.v("adapter count after 1", adapter.getCount()+"");
}
// cleared = false; // <--- nope, we did not clear the value yet
// delItem();
}
});
This code shows exact position and item to be deleted but the item not gets removed from the listview...
Try adding this after removing the item.
adapter.notifyDataSetChanged();
You can make a customized Listview containing check boxes or imageview and then use Arraylist to get the items which were clicked in the list.
refer these link:
Remove item from the listview in Android