I have three checkboxes and if any two of them are selected I want to disable the third checkbox immediately. I am not getting how to proceed.
Manage your CheckBoxes in a List, so you can iterate over them.
List<CheckBox> boxes = new ArrayList<>();
Assign them like so (in onCreate() of your activity)
boxes.add((CheckBox) findViewById(R.id.checkbox1));
boxes.add((CheckBox) findViewById(R.id.checkbox2));
boxes.add((CheckBox) findViewById(R.id.checkbox3));
Add an onCheckedChangeListener like this:
for(CheckBox box : boxes){
box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
manageBoxes();
}
});
}
and finally your manageBoxes()
private void manageBoxes(){
int count = 0;
for(CheckBox box : boxes){
count += box.isChecked()?1:0;
}
if(count>=2){
for(CheckBox box : boxes){
box.setEnabled(box.isChecked());
box.setClickable(box.isChecked()); // not sure if needed
}
}else{
// reset all boxes
for(CheckBox box : boxes){
box.setEnabled(true);
box.setClickable(true);
}
}
}
Just a quick and dirty thought. Hope this works.
Plus: This is scalable, so you could include some more checkboxes if needed.
Try to implement this way :
private ArrayList<Integer> integers = null;
integers = new ArrayList<>();
chkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
int position = (int) yourview.getTag();
if (chkBox.isChecked()) {
integers.add(position);
chkBox.setChecked(true);
} else {
if (integers.size() > 0) {
for (int i=0; i<integers.size(); i++) {
if (integers.get(i) == position) {
integers.remove(i);
}
}
});
if (integers.size() > 2) {
//Disable your third checkbox
}
Add a change handler or a click handler on each of the checkboxes and let it call a small method that is responsible for checking the value of each checkbox: if two of them are true disable the third one.
For example:
checkbox1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
handleCheckBoxes();
}
});
//Do this for all the checkboxes
private void handleCheckBoxes(){
int checkedCount = 0;
CheckBox uncheckedBox = null;
if(checkBox1.isChecked()){
checkedCount++;
}
else{
uncheckedBox = checkBox1;
}
if(checkBox2.isChecked()){
checkedCount++;
}
else{
uncheckedBox = checkBox2;
}
if(checkBox3.isChecked()){
checkedCount++;
}
else{
uncheckedBox = checkBox3;
}
if(checkedCount == 2){
uncheckedBox .setEnabled(false);
}
else{
//enable all checkboxes
checkBox1.setEnables(true);
checkBox2.setEnables(true);
checkBox3.setEnables(true);
}
In pseudo code this would be:
Create variable to hold the number of checkboxes checked, let's call it amountChecked
When a checkbox gets checked => increment the amountChecked
When a checkbox gets checked => check if the amountChecked is equal or greater than the allowedAmountChecked (in your case this is 2)
=> if it is greater or equal to the allowedAmountChecked then disable the remaining checkboxes
Related
I have three text input layouts in my activity, I apply a listener on them and it changes background color when I click on it .but need to click again if I want to click the other two .my question is that how I implement such type of logic that when it 1st clicked and I click on one of the other two, the first one clickable color disappear and 2nd one or third one clicked and its background color change and same for others
View.OnClickListener listener = new View.OnClickListener() {
#SuppressLint("NonConstantResourceId")
#Override
public void onClick(View v) {
if (v.getId() == R.id.textViewLoseWeightSubtitle) {
if (mStateChanged) {
v.setBackgroundResource(R.drawable.textview_after_click);
// mLoseWgt.setTextColor(Color.WHITE);
mStateChanged = false;
mFittedToned.setClickable(false);
mBuildMuscle.setClickable(false);
} else {
v.setBackgroundResource(R.drawable.textview_outline_style);
//mLoseWgt.setTextColor(Color.parseColor("#363C60"));
mStateChanged = true;
mFittedToned.setClickable(true);
mBuildMuscle.setClickable(true);
}
}
if (v.getId() == R.id.textViewBuildMusclesSubtitle) {
if (mStateChanged) {
v.setBackgroundResource(R.drawable.textview_after_click);
// mLoseWgt.setTextColor(Color.WHITE);
mStateChanged = false;
mLoseWgt.setClickable(false);
mFittedToned.setClickable(false);
} else {
v.setBackgroundResource(R.drawable.textview_outline_style);
//mLoseWgt.setTextColor(Color.parseColor("#363C60"));
mStateChanged = true;
mLoseWgt.setClickable(true);
mFittedToned.setClickable(true);
}
}
if (v.getId() == R.id.textViewFittedAndTonedSubtitle) {
if (mStateChanged) {
v.setBackgroundResource(R.drawable.textview_after_click);
// mLoseWgt.setTextColor(Color.WHITE);
mStateChanged = false;
mLoseWgt.setClickable(false);
mBuildMuscle.setClickable(false);
} else {
v.setBackgroundResource(R.drawable.textview_outline_style);
//mLoseWgt.setTextColor(Color.parseColor("#363C60"));
mStateChanged = true;
mLoseWgt.setClickable(true);
mBuildMuscle.setClickable(true);
}
}
}
};
mLoseWgt.setOnClickListener(listener);
mBuildMuscle.setOnClickListener(listener);
mFittedToned.setOnClickListener(listener);
}
What you need is a onFocusChangedListener(). It gives a callback with a boolean which can be used to identify whether the current view is selected or not.
Declare it as:
View.OnFocusChangeListener listener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
v.setBackgroundResource(R.drawable.textview_after_click);
// mLoseWgt.setTextColor(Color.WHITE);
} else {
v.setBackgroundResource(R.drawable.textview_outline_style);
//mLoseWgt.setTextColor(Color.parseColor("#363C60"));
}
}
});
Set it as:
mLoseWgt.setOnFocusChangeListener(listener);
mBuildMuscle.setOnFocusChangeListener(listener);
mFittedToned.setOnFocusChangeListener(listener);
That's it. Your other code seems redundant. For EditText specific functions, you can typecast the view provided by onFocusChange().
I've read that you have to store the item's state and set it again because it gets cleared from the RAM. For me, If I keep scrolling up and down in a bit longer list (10-15 item) random checks will appear and disappear. Below is how I store it and set it. What should I set apart from these? I'm using this inside a fragment.
#Override
public void onBindViewHolder(#NonNull BettingViewHolder holder, int position) {
BettingItem item = items.get(position);
holder.homeTextView.setText(item.homeTeam);
holder.awayTextView.setText(item.awayTeam);
holder.dateTextView.setText(item.date);
holder.leagueTextView.setText(item.league);
holder.sportsTextView.setText(item.sport);
holder.homeOddsTextView.setText(Double.toString(item.homeOdds));
holder.drawOddsTextView.setText(Double.toString(item.drawOdds));
holder.awayOddsTextView.setText(Double.toString(item.awayOdds));
switch (item.outcome) {
case HOME:
holder.homeCheckBox.setChecked(true);
break;
case DRAW:
holder.drawCheckBox.setChecked(true);
break;
case AWAY:
holder.awayCheckBox.setChecked(true);
break;
default:
holder.homeCheckBox.setChecked(false);
holder.drawCheckBox.setChecked(false);
holder.awayCheckBox.setChecked(false);
break;
}
holder.item = item;
}
//its a part from ViewHolder's constructor
homeCheckBox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
if (item != null) {
homeCheckBox.setChecked(isChecked);
if (isChecked) {
item.outcome = BettingItem.Outcome.valueOf("HOME");
drawCheckBox.setChecked(false);
awayCheckBox.setChecked(false);
} else {
if (item.outcome == BettingItem.Outcome.valueOf("HOME"))
item.outcome = BettingItem.Outcome.valueOf("NONE");
}
listener.onEventSelected(item);
}
}
});
drawCheckBox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
if (item != null) {
drawCheckBox.setChecked(isChecked);
if (isChecked) {
item.outcome = BettingItem.Outcome.valueOf("DRAW");
homeCheckBox.setChecked(false);
awayCheckBox.setChecked(false);
} else {
if (item.outcome == BettingItem.Outcome.valueOf("DRAW"))
item.outcome = BettingItem.Outcome.valueOf("NONE");
}
listener.onEventSelected(item);
}
}
});
awayCheckBox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
if (item != null) {
awayCheckBox.setChecked(isChecked);
if (isChecked) {
item.outcome = BettingItem.Outcome.valueOf("AWAY");
drawCheckBox.setChecked(false);
homeCheckBox.setChecked(false);
} else {
if (item.outcome == BettingItem.Outcome.valueOf("AWAY"))
item.outcome = BettingItem.Outcome.valueOf("NONE");
}
listener.onEventSelected(item);
}
}
});
you need to uncheck the old checkboxes, because the viewHolders got recycled (if the old checkBoxes were selected, it'll remain selected).
switch (item.outcome) {
case HOME:
holder.homeCheckBox.setChecked(true);
holder.drawCheckBox.setChecked(false);
holder.awayCheckBox.setChecked(false);
break;
case DRAW:
holder.homeCheckBox.setChecked(false);
holder.drawCheckBox.setChecked(true);
holder.awayCheckBox.setChecked(false);
break;
case AWAY:
holder.homeCheckBox.setChecked(false);
holder.drawCheckBox.setChecked(false);
holder.awayCheckBox.setChecked(true);
break;
default:
holder.homeCheckBox.setChecked(false);
holder.drawCheckBox.setChecked(false);
holder.awayCheckBox.setChecked(false);
break;
}
I would only want this behaviour if the user taps on it. I don't know
yet how to seperate these.
in this case, do something like this in your onCheckedChangedListener
homeCheckBox.setOnCheckedChangedListener(buttonView, isChecked -> {
if(buttonView.isPressed()){
//user pressed the button. (handle user clicks)
} else {
//the program toggled the checkbox (do nothing)
}
});
You can basically create list of objects to store your checkbox status with default status (you can use Boolean) and you need to set your recycler view checkbox status from that list. By the way, your status list need to have same size as your total cell size to avoid index out of range error. Also, when your status change you need to change your list of object in your already created list.
I have one quote application which has a "Load more" button visible only if the quote list size is 15. Now I want change the condition so that it must show the button only if the quote list size is more than 15. My current code is like below and I have tried to change it to:
if(c.getCount()<=15){
// Not Showing Load More Button
}
but it's not showing my button.
My code for that button is below:
final Button btnLoadMore=new Button(this);
btnLoadMore.setBackgroundColor(Color.parseColor("#351802"));
btnLoadMore.setTextColor(Color.parseColor("#e8d8a7"));
btnLoadMore.setTypeface(btnLoadMore.getTypeface(), Typeface.BOLD);
btnLoadMore.setText("Load More Quotes");
if(c.getCount()<15){
// Not Showing Load More Button
}
else {
list.addFooterView(btnLoadMore);}
list.setAdapter(adapter);
anifadein=AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slidedown);
list.startAnimation(anifadein);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
map = quotesList.get(position);
Intent intent = new Intent(QuotesActivity.this,
QuoteDialogActivity.class);
int itemPosition = position;
if(startingPoint>=30){
intent.putExtra("Pos", itemPosition+1);
intent.putExtra("LstCount", list.getCount()-1);
}else{
intent.putExtra("Pos", itemPosition+1);
intent.putExtra("LstCount", list.getCount());}
intent.putExtra("QuoteId", map.get(KEY_ID));
intent.putExtra("quotesType", quType);
intent.putExtra("startFrom", getIntent().getStringExtra("startFrom"));
intent.putExtra("Quotes", quotesList);
// Log.i("COUNT",""+(itemPosition+1)+"-"+list.getCount());
intent.putExtra("Fav", map.get(KEY_FAVORITE));
startActivity(intent);
if (mInterstitial.isLoaded()) {
mInterstitial.show();
}
}
});
btnLoadMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if(btnLoadMore.getVisibility()==View.VISIBLE){
Cursor newC = null;
if (quType != 0) {
switch (quType) {
case 1:
newC = db.getQuotes(""+startingPoint);
break;
case 2:
newC = db.getFavoriteQuotes(""+startingPoint);
//page.setVisibility(View.GONE);
break;
case 3:
newC = db.getAuthorQuotes(getIntent().getStringExtra("AuthorId"),""+startingPoint);
// page.setVisibility(View.GONE);
break;
}
}
// Starting a new async task
if(newC.getCount()<15){
btnLoadMore.setVisibility(View.INVISIBLE);
}
startingPoint+=15;
do{
map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(KEY_ID, newC.getString(newC.getColumnIndex(KEY_ID)));
map.put(KEY_TEXT, newC.getString(newC.getColumnIndex(KEY_TEXT)));
map.put(KEY_AUTHOR, newC.getString(newC.getColumnIndex(KEY_AUTHOR)));
map.put(KEY_PICTURE, newC.getString(newC.getColumnIndex(KEY_PICTURE)));
map.put(KEY_PICTURE_SDCARD, String.valueOf(newC.getInt(newC
.getColumnIndex(KEY_PICTURE_SDCARD))));
map.put(KEY_WEB_ID,
String.valueOf(newC.getInt(newC.getColumnIndex(KEY_WEB_ID))));
//Log.i("web_id",String.valueOf(newC.getInt(newC.getColumnIndex(KEY_ID))));
map.put(KEY_FAVORITE, newC.getString(newC.getColumnIndex(KEY_FAVORITE)));
// adding HashList to ArrayList
quotesList.add(map);
if (mInterstitial.isLoaded()) {
mInterstitial.show();
}
} while (newC.moveToNext());
adapter.notifyDataSetChanged(); }}
});
}
}
I not sure from where Object "c" is coming but i m assuming it list object and getCount is return the current count of list. So, If you want to show "Show more" button when the size of list is greater than or equals to 15 then use this condition.
if(c.getCount() >= 15){
// Will show Load More Button
}
Put the Button in a layout XML File. Inflate it, then:
if (c.getCount() > 15) {
btnLoadMore.setVisibility(View.INVISIBLE);
}
If you want the Button to be invisible.
I want to increase the score by 1, when someone clicks on the right radio button. If someone clicks 2 times, the score is increased by 2. I am trying to prevent that with a boolean but it doesn't work. Were am i wrong?
This is my code:
boolean isChecked;
answer[j].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RadioButton checkedRadioButton = ((RadioButton) v);
if (isChecked) {
if (checkedRadioButton.isChecked() & CorrectAnswer == 1) {
score++;
isChecked = false;
}
}
}
});
Thanks!
Assuming you don't need the value outside the OnClickListener, the easiest thing to do is to make it a member variable of that class:
new View.OnClickListener() {
private boolean isChecked = true; // HERE
#Override
public void onClick(View v) {
RadioButton checkedRadioButton = ((RadioButton) v);
if (isChecked) {
if (checkedRadioButton.isChecked() && CorrectAnswer == 1) {
score++;
isChecked = false;
}
}
}
};
You also need to set its value to true initially, since it will otherwise be false and so the conditional's body never runs.
You could also simply use
if (!checkedRadioButton.isChecked())
instead of a dedicated checker
if (isChecked)
I have a for loop that displays 2 textviews and a checkbox in each of my tablerow in a table layout. I have an if statement that shows a toast to test the isChecked function of a checkbox, but the if statement works inversely except for the last table row. Why is that, and how do I fix it?
for (Integer j = 0; j < count; j++)
{
tableRow1 = new TableRow(getApplicationContext());
textViewMaster = new TextView(getApplicationContext());
textViewMaster.setText(c.getString(c.getColumnIndex("StudentID")));
textViewMaster.setPadding(20, 20, 20, 20);
textViewMaster.setTextColor(getResources().getColor(R.color.redactionbar));
textViewMaster.setTextSize(TypedValue.COMPLEX_UNIT_DIP,25);
textViewMaster.setTypeface(null, Typeface.BOLD);
tableRow1.addView(textViewMaster);
textViewMaster2 = new TextView(getApplicationContext());
textViewMaster2.setText(c.getString(c.getColumnIndex("LastName")));
textViewMaster2.setPadding(20, 20, 20, 20);
textViewMaster2.setTextColor(getResources().getColor(R.color.redactionbar));
textViewMaster2.setTextSize(TypedValue.COMPLEX_UNIT_DIP,25);
textViewMaster2.setTypeface(null, Typeface.BOLD);
tableRow1.addView(textViewMaster2);
tableRow1.setClickable(true);
tableRow1.setLongClickable(true);
tableLayout1.setClickable(true);
checkBox = new CheckBox(getApplicationContext());
checkBox.setChecked(true);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
{
if (checkBox.isChecked())
{
searchView.setEnabled(false);
arrayList.add(container1);
arrayList2.add(container2);
arrayList3.add(container3);
Toast toast = Toast.makeText(getApplicationContext(),"Its checked", Toast.LENGTH_SHORT);
toast.show();
}
else
{
arrayList.remove(container1);
arrayList2.remove(container2);
arrayList3.remove(container3);
Toast toast = Toast.makeText(getApplicationContext(), "Its not checked", Toast.LENGTH_SHORT);
toast.show();
}
}
});
checkBox.setVisibility(View.VISIBLE);
tableRow1.addView(checkBox);
tableLayout1.addView(tableRow1);
c.moveToNext() ;
}
Any help is greatly appreciated!
In Current implementation checkBox hold last CheckBox object which is created during last iteration of for loop so use second parameter of onCheckedChanged method which is if true means CheckBox is checked otherwise unchecked:
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
{
if (b){ // or use compoundButton.isChecked()
// code if checkbox is checked
} else{
// code if checkbox is not checked
}
}
You should use suggestion in other answer, but this would also work and would be a technique to use when you do not have a parameter you can use:
Create a new local variable, not a field so is different for each loop and mark is as final in order to be able to use it from the anonymous class.
final CheckBox checkBox = new CheckBox(getApplicationContext());
//rest is same
checkBox.setChecked(true);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
{
if (checkBox.isChecked())
{
}
else
{
}
}
});