I have a quiz app, and every question has 4 answers, 2 of them are the correct ones. I use CheckBox for the answers. What I want is when the user clicks on 2 of the answers, then the remaining 2 to get unchecked. With other words, only 2 checked CheckBox at the time, and if the user has 2 checked and checks third one, then one of the two checked to get unchecked. I write a code that it is "half-working". When I check CheckBox starting from the first to the last is working, but clicking from the last to the first, nothing happens...
public void checkBoxClicked(View view) {
switch (view.getId()) {
case R.id.checkBoxOne:
case R.id.checkBoxTwo:
case R.id.checkBoxThree:
case R.id.checkBoxFour:
if (checkBoxOne.isChecked() && checkBoxTwo.isChecked()) {
checkBoxThree.setEnabled(false);
checkBoxFour.setEnabled(false);
}else {
checkBoxThree.setEnabled(true);
checkBoxFour.setEnabled(true);
}
if (checkBoxOne.isChecked() && checkBoxThree.isChecked()) {
checkBoxTwo.setEnabled(false);
checkBoxFour.setEnabled(false);
}else {
checkBoxTwo.setEnabled(true);
checkBoxFour.setEnabled(true);
}
if (checkBoxOne.isChecked() && checkBoxFour.isChecked()) {
checkBoxTwo.setEnabled(false);
checkBoxThree.setEnabled(false);
}else {
checkBoxTwo.setEnabled(true);
checkBoxThree.setEnabled(true);
}
if (checkBoxTwo.isChecked() && checkBoxThree.isChecked()) {
checkBoxOne.setEnabled(false);
checkBoxFour.setEnabled(false);
}else {
checkBoxOne.setEnabled(true);
checkBoxFour.setEnabled(true);
}
if (checkBoxTwo.isChecked() && checkBoxFour.isChecked()) {
checkBoxOne.setEnabled(false);
checkBoxThree.setEnabled(false);
}else {
checkBoxOne.setEnabled(true);
checkBoxThree.setEnabled(true);
}
if (checkBoxThree.isChecked() && checkBoxFour.isChecked()) {
checkBoxOne.setEnabled(false);
checkBoxTwo.setEnabled(false);
}else {
checkBoxOne.setEnabled(true);
checkBoxTwo.setEnabled(true);
}
break;
I would try tracking the boxes that are checked using an array, (a queue would work perfect for this). When the user clicks on a checkbox, check if your array has two entries. If it has less than 2 entries, add the new checkbox to the list. If it has two entries, remove the first checkbox from the list, and add the new checkbox.
After your tracking code, you can simply uncheck ALL of the check boxes and only check those that you want.
Here I use an ArrayList for simplicity, but even a simple array would work. You could also use the id's instead of the actual views.
***Update Very Simple Working example.
Activity
public class TestActivity extends AppCompatActivity implements View.OnClickListener{
private ArrayList<CheckBox> mChecks;
private ArrayList<CheckBox> mSelectedChecks;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
mChecks = new ArrayList<CheckBox>();
mSelectedChecks = new ArrayList<CheckBox>();
//Load All checkboxes
CheckBox check1 = (CheckBox)findViewById(R.id.check1);
CheckBox check2 = (CheckBox)findViewById(R.id.check2);
CheckBox check3 = (CheckBox)findViewById(R.id.check3);
CheckBox check4 = (CheckBox)findViewById(R.id.check4);
//Add to tracking list
mChecks.add(check1);
mChecks.add(check2);
mChecks.add(check3);
mChecks.add(check4);
//Add Click listener
for(CheckBox c : mChecks) {
c.setOnClickListener(this);
}
}
#Override
public void onClick(View view) {
CheckBox c = (CheckBox)view;
if(mSelectedChecks.contains(c)) {
mSelectedChecks.remove(c);
} else {
if(mSelectedChecks.size() < 2) {
mSelectedChecks.add(c);
} else {
mSelectedChecks.remove(0);
mSelectedChecks.add(c);
}
}
drawResults();
}
public void drawResults() {
for(CheckBox c : mChecks) {
c.setChecked(mSelectedChecks.contains(c));
}
}
}
Layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:text="Check 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/check1"/>
<CheckBox
android:text="Check 2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/check2"/>
<CheckBox
android:text="Check 3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/check3"/>
<CheckBox
android:text="Check 4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/check4"/>
</LinearLayout>
Related
I want to check if my Checkboxes are checked to change some values.
I got the answer for radioButton which is inserted to a RadioGroup and we can simply use :
radioGroup.setOnCheckedChangeListener(new new OnCheckedChangeListener(){
#Override
public void onCheckedChanged(RadioGroup group, int checkedId)
{ . . . }
}
i'm looking for something like this ,However this approach is differ from Checkboxes because there is no widget like CheckboxGroup to use setOnCheckedChangeListener On it .
For example i have checkbox1 and checkbox2. how can i get as long as these two checkboxes are checked to changing some value like :
if(checkbox1==isChecked && checkbox2==isChecked)
//Do sth ...
else
//Do sth Different
EDIT : Maybe i could not explain my problem perfectly , this is just like question below but for Checkboxes
How to check state Changing of Radio Button android?
As commented you can use checkboxRef.isChecked()
if(checkbox1.isChecked() && checkbox2.isChecked()){
}
else{
}
but I want to use them in a different function , may globally access
to this checkboxes
You can use sharedPreference and with a utility class to store the state of your checkbox.
SharedPreferences helper class
This is way to check which checkbox is checked..
if(checkbox1.isChecked())
{
//means checkbox1 is checked...
}else
{
//means checkbox2 is checked...
}
If you want to set an event listener to detect when a change is made you can use:
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
//Code here
} } );
On the other hand if you want to check if it is checked you can use:
if(checkbox.isChecked()){
//Code here
}
Finally i got the answer , first of all I need to set onclick attribute as the same for all of the checkboxes , and check my Needed for approach desire output in the onClick Function,
Xml:
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="func"
android:text="1"
android:id="#+id/c1"/>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2"
android:onClick="func"
android:id="#+id/c2"/>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="3"
android:onClick="func"
android:id="#+id/c3"/>
JavaCode:
public void func(View view) {
CheckBox checkBox1 = (CheckBox)findViewById(R.id.c1);
CheckBox checkBox2 = (CheckBox)findViewById(R.id.c2);
CheckBox checkBox3 = (CheckBox)findViewById(R.id.c3);
if(checkBox1.isChecked() && checkBox2.isChecked() && (!checkBox3.isChecked()))
{
Next = true;
}
else
{
Next = false;
}
}
checkBox1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(checkBox1.isChecked() && checkBox2.isChecked()){
}
}
});
please i need help on this.
I have searched here but the answers i have seen are not working for me, the posts being old, the functions are mostly deprecated.
I am trying to set the color of buttons on a single click in order to highlight them and unset the color on a second click. It's like making some choice from a number of buttons, and if I click on a selected button again maybe after changing my mind on my selection, the color should revert to the default. So that i am only left with the selected buttons highlighted.
The buttons are generated with an adapter in gridview and the onclicklistener applies to all of them.
The code i'm using is as shown:
public class ButtonAdapter extends BaseAdapter {
private Context context;
public View getView(int position, View convertView, ViewGroup parent)
{
final Button btn;
if (convertView == null) {
btn = new Button(context);
btn.setLayoutParams(new GridView.LayoutParams(40, 40));
btn.setPadding(2, 2, 2, 2);
}
else {
btn = (Button) convertView;
}
//exus
btn.setText(Integer.toString(gridNumbers[position]));
btn.setTextColor(Color.BLACK);
btn.setId(position);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//btn.setBackgroundColor(Color.GREEN);
//Toast.makeText(getBaseContext(), "Button clicked", Toast.LENGTH_LONG).show();
if (v.getSolidColor()!=Color.GREEN)
{
btn.setBackgroundColor(Color.GREEN);
}
else
{
btn.setBackgroundColor(Color.GRAY);
}
}
});
return btn;
}
}
}
My XML:
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="8"
android:columnWidth="20dp"
android:stretchMode="columnWidth"
android:gravity="center" />
You can use a list of boolean properties instead of doing this.
Set a public boolean list in your class (it should be public and outside of any functions otherwise the onclicklistener will have error)
List<boolean> blist=new Arraylist<boolean>(Size);
//Size is maximum number of buttons
int index;
Then whenever you create a new button add this:
blist.add(index,false);
index++;
in the onclicklistener; find the index of the button from its position and save the index in an integer named pos.
if(blist.get(pos)==false)
{
//not clicked yet
blist.remove(pos);
blist.add(pos,true);
//here write the code u need for this if
}
else
{
blist.remove(pos);
blist.add(pos,false);
//todo: ur code for else
}
I tried this way and it worked for me,if you want to change on click
counter = 1;
//By Default set color
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (counter == 1)
{
// Default color
counter = 2;
}
else
{
//your color
counter = 1;
}
}
});
View reused in GridView. So, you should define state for your buttons in your base adapters.
Take an ArrayList that will hold your selected index and remove it when grid is not selected.
Ex:
ArrayList<Integer> selectedItems;
In Construtor
selectedItems = new ArrayList<Integer>();
In OnClickListener
public void onClick(View v) {
if (selectedItems.contains(new Integer(position))) {
selectedItems.remove(new Integer(position));
notifyDataSetChanged();
} else {
selectedItems.add(new Integer(position));
notifyDataSetChanged();
}
}
In getView():
if (selectedItems.contains(new Integer(position))) {
btn.setBackgroundColor(Color.GREEN);
} else {
btn.setBackgroundColor(Color.GRAY);
}
Use toggle button insted of normal button. Like
<ToggleButton
android:id="#+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/check" //check.xml
android:layout_margin="10dp"
android:textOn=""
android:textOff=""
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_centerVertical="true"/>
and then make an xml file check.xml in drawable folder something like
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- When selected, use grey -->
<item android:drawable="#drawable/selected_image"
android:state_checked="true" />
<!-- When not selected, use white-->
<item android:drawable="#drawable/unselected_image"
android:state_checked="false"/>
</selector>
refrence.
I'm curious about how other people solve this problem:
When having an application which allows users to subscribe to each other, should you better use two buttons, one with a "Subscribe" text and the other with a "Unsubscribe" text or just use one button in the layout and change the text after clicking the button?
2 buttons solution
XML:
<Button
android:id="#+id/subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Subscribe"
android:visibility="gone" />
<Button
android:id="#+id/unsubscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Unsubscribe"
android:visibility="gone" />
Java:
// update subscribe buttons
if (userProfile.getID() != user.getUserID()) {
if (userProfile.hasSubscribed()) {
unsubscribeView.setVisibility(View.VISIBLE);
}
else {
subscribeView.setVisibility(View.VISIBLE);
}
}
subscribeView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
subscribe = 1;
subscribe();
}
});
unsubscribeView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
subscribe = -1;
subscribe();
}
});
1 button solution
XML:
<Button
android:id="#+id/subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
Java:
// update subscribe buttons
if (userProfile.getID() != user.getUserID()) {
if (userProfile.hasSubscribed()) {
subscribeView.setText("Unsubscribe");
}
else {
subscribeView.setText("Subscribe");
}
}
subscribeView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (userProfile.hasSubscribed()) {
subscribe = -1;
}
else {
subscribe = 1;
}
subscribe();
}
});
Use the one-button approach.
Try to keep the UI as clean as possible, and avoid having buttons that are visible, but don't have any effect.
Hi I'd like to create 2 sets of images where one set is displayed if the user selects something from a radio button and the other is displayed if the user selects the other radio button,
In truth I'm an amateur at this and it may not even be radio buttons that I want but its one set of images for a girl and another for a boy, any suggestions welcome
this is what I did... its inside an edittext but it shouldnt make any difference :
<EditText
android:id="#+id/exerciseInputFilter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:ems="10"
android:hint="search..."
android:textColor="#android:color/holo_blue_light" />
<ImageView
android:id="#+id/drillListSearchImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/exerciseInputFilter"
android:layout_alignParentRight="true"
android:src="#drawable/search_white" />
in the xml for example... frame is also possible...
and in code...
SearchImage = (ImageView) findViewById(R.id.drillListSearchImage);
SearchImage.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (!filterText.getText().equals(null)) {
filterText.setText("");
SearchImage.setImageResource(R.drawable.search_white);
}
return false;
}
});
so just create 1 image view and then on touch do something...
if you want to use a radio or checkbox its the same principle... on item click... set imageview to whatever you want...
rd2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
rd1.setChecked(false);
SearchImage.setImageResource(R.drawable.search_white);
}
});
for example... does this answer your question?
Edit
after reading your comment (which wasnt understandable from your original question)... what you want is just to pass information between activities to do that use this:
Activity A:
create a boolean and a 2 check or radios and
CheckBox maleBox = (CheckBox) findViewById(R.id.Male);
maleBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (((CheckBox) v).isChecked()) {
isMale = true;
isFemale = false;
femaleBox.setChecked(false);
}
}
});
you can do the same for female if you want several radios or checkboxs... then...you pass the information to activity two... like so:
intent = new Intent(whateverclass.this, whoeverclass.class);
intent.putExtra("Gender", isMale);
startActivity(intent);
now you can read it in activity two with:
if (getIntent().getBooleanExtra("Gender", false)) {
// set Images or buttons or what ever...(like i showed you above)
SetImage1.setImageResource(R.drawable.boy);
.
.
.
}
you can also use bundle to get your variables...
Intent intent = new Intent();
intent = getIntent();
Bundle bundle = intent.getExtras();
then just get the boolean...
How can I keep an item, in an MvxListView, highlighted until it is unselected or until another item is selected?
My program has an MvxListView that correctly displays a list of items. The user can select an item, by clicking it, and then click a save button. The selected item is stored in MyChosenItem until it is needed by the save button code. Currently, the selected item stays highlights for a split second before returning to the unselected color.
This is how the MvxListView is created:
<Mvx.MvxListView
android:layout_width="match_parent"
android:layout_height="260dp"
android:layout_marginTop="40dp"
android:id="#+id/MyMvxListViewControl"
local:MvxBind="ItemsSource MyItems; SelectedItem MyChosenItem"
local:MvxItemTemplate="#layout/my_item_layout" />
This is Layout/my_item_layout.xaml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res/Project.Ui.Droid"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="300.0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="20dp"
android:textColor="#000000"
local:MvxBind="Text Field1" />
<TextView
android:layout_width="250.0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="20dp"
android:textColor="#000000"
local:MvxBind="Text Field2" />
</LinearLayout>
This method provides an easy way to customize which items remain highlighted. I settled on this because it gives me full control over what is highlighted and how it is displayed in the list. (This example shows highlighting only one item, but it could easily be extended to highlight more.)
The MvxListView, in the original question, links to MyItems and MyChosenItem in the associated view model. MyItems is a collection of Item, and MyChosenItem is just a single Item. I added isItemSelected to Item. The Item class looks like this now:
public class Item : MvxViewModel
{
private string _field1;
private string _field2;
private bool _isItemSelected = false;
public string Field1
{
get { return _field1; }
set
{
_field1= value;
RaisePropertyChanged("Field1");
}
}
public string Field2
{
get { return _field2; }
set
{
_field2= value;
RaisePropertyChanged("Field2");
}
}
public bool isItemSelected
{
get { return _isItemSelected; }
set
{
_isItemSelected = value;
RaisePropertyChanged("isItemSelected");
}
}
}
Note: The Item class extends MvxViewModel so that RaisePropertyChange() can be called. This allows my_item_layout.xaml to be notified when that property changes.
Update each instance of isItemSelected from the property that the MvxListView's SelectedItem binds to. In this case, that's the MyChosenItem property in the associated view model. This is what the new code looks like:
public Item MyChosenItem
{
get { return _myChosenItem; }
set
{
if (_myChosenItem != value)
{
_myChosenItem = value;
UpdateItemSelections();
RaisePropertyChanged("MyChosenItem");
}
}
}
// Select MyChosenItem and unselect all other items
private void UpdateItemSelections()
{
if( MyItems.Count > 0)
{
for (int index = 0; index < MyItems.Count; index++)
{
// If the chosen item is the same, mark it as selected
if (MyItems[index].Field1.Equals(MyChosenItem.Field1)
&& MyItems[index].Field2.Equals(MyChosenItem.Field2))
{
MyItems[index].isItemSelected = true;
}
else
{
// Only trigger the property changed event if it needs to change
if (MyItems[index].isItemSelected)
{
MyItems[index].isItemSelected = false;
}
}
}
}
}
It would be pretty easy to modify UpdateItemSelections() to any selection behavior you want.
Make each row do something based on the isItemSelected property. I just made the background change colors by controlling the visibility property of a view. However, all sorts of things are possible. isItemSelected could even be passed to a custom control for some really interesting visuals. My new Layout/my_item_layout.xaml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res/Project.Ui.Droid"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- SELECTED BACKGROUND COLOR -->
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF0000"
local:MvxBind="Visibility isItemSelected,Converter=BoolToViewStates" />
<TextView
android:layout_width="300.0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="20dp"
android:textColor="#000000"
local:MvxBind="Text Field1" />
<TextView
android:layout_width="250.0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="20dp"
android:textColor="#000000"
local:MvxBind="Text Field2" />
</LinearLayout>
EDIT
It might be better to use an MvxCommand instead of triggering the highlighted action when the SelectedItem is set. It seems the SelectedItem is only set if it is not already selected. Tapping an item will select it. Tapping another item will change the selection. Tapping the same item again will not unselect it. This means that once an item is selected, one item must remain selected. If you need the ability to unselect all the items in the list, follow these modifications to the original instructions:
Add an MvxCommand to the view model. Call UpdateItemSelections() from the MvxCommand instead of from MyChosenItem.
public MvxCommand ItemSelectedCommand { get; private set; }
// Constructor
public ItemSelectionViewModel()
{
ItemSelectedCommand = new MvxCommand(OnItemSelected);
}
public Item MyChosenItem
{
get { return _myChosenItem; }
set
{
if (_myChosenItem != value)
{
_myChosenItem = value;
//UpdateItemSelections(); // Move this to OnItemSelected()
RaisePropertyChanged("MyChosenItem");
}
}
}
private void OnItemSelected()
{
UpdateItemSelections();
}
Change UpdateItemSelections() to toggle the isItemSelected property instead of always setting it to true:
// Select MyChosenItem and unselect all other items
private void UpdateItemSelections()
{
if( MyItems.Count > 0)
{
for (int index = 0; index < MyItems.Count; index++)
{
// If the chosen item is the same, mark it as selected
if (MyItems[index].Field1.Equals(MyChosenItem.Field1)
&& MyItems[index].Field2.Equals(MyChosenItem.Field2))
{
// Toggle selected status
MyItems[index].isItemSelected = !MyItems[index].isItemSelected;
}
else
{
// Only trigger the property changed event if it needs to change
if (MyItems[index].isItemSelected)
{
MyItems[index].isItemSelected = false;
}
}
}
}
}
Remember to check MyChosenItem.isItemSelected == true when saving or doing anything that acts on the selected item in the list. There might be a value in MyChosenItem that is unselected in the list view the user sees.
Bind the MvxCommand to ItemClick in layout definition of the MvxListView:
<Mvx.MvxListView
android:layout_width="match_parent"
android:layout_height="260dp"
android:layout_marginTop="40dp"
android:id="#+id/MyMvxListViewControl"
local:MvxBind="ItemsSource MyItems; SelectedItem MyChosenItem; ItemClick ItemSelectedCommand"
local:MvxItemTemplate="#layout/my_item_layout" />