How to find the class of a checkbox that was clicked - java

I have a 'ChecklistItem' class that has the following properties:
private CheckBox checkBox;
private ImageButton noteButton;
private TextView vitalField;
I have an onClick Listener for my checkbox. Now the problem is, when I click on that checkbox and the OnClick() method gets called, how can I figure out what ChecklistItem that checkbox is a part of?
Whenever I click on a checkbox, I want to add the ChecklistItem that the checkbox is a part of to an array, but the OnClick() only knows about the checkbox that called it.
How can I get around this?

Ok so this answer is according to the "long discussion" we had
let's assume you want to make a - re usable - view of your list and you wrote a separate xml layout file called list_item as the following:
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/checkbox"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/text_view"/>
so now let's assume you are in the activity or fragment or wherever you want to host your view , NOW I have to point out this is just an example , usually a list view is what you would need in this case but again I have very little details about your app so I'm going to keep it simple
Assuming you have a vertical linear layout and you want to add these "rows" to it, each row represents one of your custom view
LinearLayout layout = findViewById(R.id.layout);
LayoutInflater inflater = LayoutInflater.from(this); // This inflater is responsible of creating instances of your view
View myView = inflater.inflate(R.layout.list_item, layout, false); // This view objects is the view you made in your xml file
CheckBox checkBox = (CheckBox) myView.findViewById(R.id.checkbox);
TextView textView = (TextView) myView.findViewById(R.id.text_view);
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//if checkbox is checked enable textview for example
// here you have a reference to all the views you just created
// Weather you want to save them in a class together that's up to you and your app's logic
}
});
layout.addView((myView));
if the list is might exceed the screen height you may want to wrap your linear layout in a scroll view.
BTW: ListView is just a neat way to do this automatically by defining how you want each row to appear, and of course it manages your views for you and recycle them when they get of screen, but I just wanted to point out the concept.
Hope this helps you

Related

Registering multiple click events programatically (Android/Java)

So i have this program which create my list of cards which are relative layouts and they look like this.
Here is the code of it creation. Ps its in a for loop
LayoutInflater mInflater = (LayoutInflater) atv.getSystemService(atv.LAYOUT_INFLATER_SERVICE);
LinearLayout relativeLayoutz = (LinearLayout) mInflater.inflate(R.layout.rtl_enterprise, parent);
RelativeLayout rl = (RelativeLayout) relativeLayoutz.findViewById(R.id.rl_empresa);
rl.setId(i);
ImageView img = (ImageView) rl.getChildAt(0);
//
//Performance bottleneck needs fixing/ not loading all images and overloading thread
//
//loadImageByUrl(atv, enterprises.getEnterprises().get(k).getPhoto().toString(), img);
TextView txt = (TextView) rl.getChildAt(1);
txt.setText(enterprises.getEnterprises().get(i).getEnterpriseName());
TextView txt2 = (TextView) rl.getChildAt(2);
txt2.setText(enterprises.getEnterprises().get(i).getEnterpriseType().getEnterpriseTypeName());
TextView txt3 = (TextView) rl.getChildAt(3);
txt3.setText(enterprises.getEnterprises().get(i).getCountry());
LinearLayout relativeLayout = (LinearLayout) mInflater.inflate(R.layout.rtl_enterprise, parent);
relativeLayout.setId(i);
everything there works kinda ok, but i have a problem, i need to create a
onClick listener
Why?
I would call a method which needs some info about the card that has been clicked, and then redirect to a new activity which contains the info about the card that he clicked.
But i would need that onclick listener for each of these relative layouts, and i assume it would need to be initialized when the card is created since it create + 50 cards, but i have no idea of how to setup each listener.
Why do you create it like that?
a better solution to use RecyclerView.
and in the adapter, you can listen for the item click. write the code one time and when any item clicked. you will know the position of the clicked item.
see this tutorial
https://developer.android.com/guide/topics/ui/layout/recyclerview
https://www.androidhive.info/2016/01/android-working-with-recycler-view/

Add RadioGroup in dynamic LinearLayout

I dynamically generate radiobuttons for an app (ex: 3 radiobuttons) in a LinearLayout I call parentLinearLayout. Problem is, they don't go automatically in a group, so if I check a button and then another, both check instead of un-checking the first one. So, I thought I should do a RadioGroup.
The app itself is a questionnaire app, and every question has a different number of possible answers. I create from a radiobutton layout the number of answers as radiobuttons.
Problem is, I get an error saying that I should remove the old view before doing so, but if I do this I lose my generated linearlayout: The specified child already has a parent. You must call removeView() on the child's parent first.
Here is my code:
public void drawRAnswers(int pst){
int drawables = qmclist.get(pst).getAnswers().size();
RadioGroup l1 = new RadioGroup(this);
for (int i=0;i<drawables;i++){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView = inflater.inflate(R.layout.radiobutton, null);
// Add the new row before the add field button.
parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount());
rowView.setId(i);
RadioButton rd = (RadioButton) rowView.findViewById(R.id.radiobtn);
l1.addView(rd); <== HERE IS THE PROBLEM
rd.setText(current.getAnswers().get(i).getAns());
}
}
Any ideas how I could fix this? Thanks
You are creating a new layout during every iteration in loop.
By inflating a new view, you are losing the old views
Every time you are using the same id R.id.radiobtn for to find a view and add the same view again in the layout which is not possible hence the issue.
for (int i=0;i<drawables;i++){
// 1,2
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//
final View rowView = inflater.inflate(R.layout.radiobutton, null);
parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount());
rowView.setId(i);
RadioButton rd = (RadioButton) rowView.findViewById(R.id.radiobtn);
l1.addView(rd); // same view with same id R.id.radiobtn
rd.setText(current.getAnswers().get(i).getAns());
}
Solution :
public void drawRAnswers(int pst){
int drawables = qmclist.get(pst).getAnswers().size();
// create a radio group as container with direction
RadioGroup l1 = new RadioGroup(this);
l1.setOrientation(LinearLayout.VERTICAL);
for (int i=0;i<drawables;i++){
// create radio button, with id and text
RadioButton rd = new RadioButton(this);
rd.setId(i);
rd.setText(current.getAnswers().get(i).getAns());
// add radio button into group
l1.addView(rd);
}
// finally, add radio group with buttons into parent layout
parentLinearLayout.addView(l1, parentLinearLayout.getChildCount());
}
You are quite close I guess just change some of the lines and you are good to go.
public void drawRAnswers(int pst){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int drawables = qmclist.get(pst).getAnswers().size();
RadioGroup l1 = new RadioGroup(this);
for (int i=0;i<drawables;i++){
final View rowView = inflater.inflate(R.layout.radiobutton, null);
// Add the new row before the add field button.
RadioButton rd = (RadioButton) rowView.findViewById(R.id.radiobtn);
rd.setText(current.getAnswers().get(i).getAns());
rd.setId(i);
l1.addView(rd);
}
parentLinearLayout.addView(l1, parentLinearLayout.getChildCount());
//or
parentLinearLayout.addView(l1);
}
RadioGroups are glorified LinearLayouts behind the scenes, that means they can support any children, but will only treat RadioButtons in the same “group” if they are direct children of the Group. E.g.:
Imagine This hierarchy:
<RadioGroup> // THIS YOU HAVE IN XML
<RadioButton 1> // ALL THESE YOU CREATE PROGRAMMATICALLY
<RadioButton 2>
<RadioButton 3>
</RadioGroup>
So your XML looks like:
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/your_radio_button"
android:layout_width=“match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Radio Buttons will be programmatically added here -->
</RadioGroup>
So… you create everything programmatically, that’s fine. You have a “loop” like…
final RadioGroup group = //find your_radio_button in the layout.
// now iterate
for (Something something : listOfSomethings) {
final RadioButton rb = new RadioButton(context);
rb.setId(View.generateViewId());
rb.setText(something.giveMeTheText());
rb.setLayoutParams(layoutParams); // make these depending what your container for the RadioGroup is.
rb.setOnCheckedChangeListener(your OnCheckedChangeListener);
group.add(rb);
}
If you need to listen for changes, obviously add a common CompoundButton.OnCheckedChangeListener and override:
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// do what you need ;)
}
Bear in mind that the moment you do group.add(rb) if the Button has an onCheckedChangeListener, it will be fired… if you set it as checked (I think it also fires even if you don’t with a “false”), so you may want to delay the assignment of the listener until you’re done adding buttons to the RadioGroup and then iterate them and add them all at the same time (that doesn’t trigger the callback right there because the buttons are ALREADY in the hierarchy and haven’t changed).
If you need to insert something other than a RadioButton as the direct child of your RadioGroup that’s the topic for another question (it’s doable, not automatic and will require you to do some extra-work).

Android adding n text fields

I just started learning android programming and can't seem to work out how to permit the user to create a selected number (n) of EditText fields by clicking a button n times such that each would be uniquely identified, namely 1,2,3...,n as well as accessible programatically, from a different method (invoked by a different button click). I hope the question is clear enough as I don't really have that much code to provide.
Do something like this
// A list to keep reference to your created edit texts
List<EditText> mEditTexts = new ArrayList<EditText>();
// Get root view of your activity
ViewGroup viewGroup = (ViewGroup) ((ViewGroup)
findViewById(android.R.id.content)).getChildAt(0);
// Get the button and set a click listener to it
Button mButton = (Button) findViewById(R.id.button_id);
mButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
// Build edit text
EditText mEditText = new EditText(v.getContext());
// Pass two args (arg1/arg2); must be LayoutParams.MATCH_PARENT,
// LayoutParams.WRAP_CONTENT, or an integer pixel value.
mEditText.setLayoutParams(new LayoutParams(arg1, arg2));
// Add the edit text to your list
mEditTexts.add(mEditText);
// Add edit text to your root view
viewGroup.addView(mEditText);
}
}
To check your edit text fields you can then access them from the list
for(EditText editText : mEditTexts){
Log.d(TAG, editText.getEditableText().toString());
}
or explicitly
int specificPosition = (SOME_INT);
EditText specificEditText = mEditTexts.get(specificPosition);
Haven't been able to test it so it might need some modifying but it should be something along those lines. You can also use your layout directly if you don't want to use the viewGroup. Modify it to something like
LinearLayout mLayout = (LinearLayout) findViewById(R.id.layout_id);
....
mLayout.addView(mEditText);

Radio Buttons inside expandable list remain when expanding other child elements

I want to make an expandable list of radio groups in my android app. each element of the list should contain (when opened) several individual radio groups. So far I am testing with only one radiogroup per child and already I am encountering a problem I can't seem to solve by myself.
When I expand a parent of my expandable list, it seems to work properly. The radiobuttons of a radiogroup (which is the only child element of a parent right now) are displayed the way they should. However, when I expand another parent of my expandable list, the radio buttons are added to the already existing buttons of the other child group. Which means: Once I've expanded several child groups, each one of the expanded children contains tons of radio buttons, flooding the whole screen.
Simply put, when I expand parent 1 I get the choices
yes
no
maybe
When I expand the second parent, I get the radio choices
yes
no
maybe
yes
no
perhaps
probably
... which are also added to the radio button group thats inside parent 1. So now I have 2 large expanded list elements. When I expand another group, the choices get added to all the child views as well, and so on, and so on...
So, following simple logic it seems that all the radio buttons are not put into a new group (thats newly created every time I expand a child list), but instead they are added to the same, already existing group.
I have been able to pretty much isolate the problem to the getChildView function inside my ExpandableListAdapter class. This is the code which causes the output described above:
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view,
ViewGroup parent) {
ExpandListChild child = (ExpandListChild) getChild(groupPosition, childPosition);
if (view == null) {
LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = infalInflater.inflate(R.layout.child_layout, null);
}
ArrayList<HashMap<String,String>> inputDetailsList = child.getInputfields();
//RadioGroup rg = new RadioGroup(view.getContext());
RadioGroup rg = (RadioGroup) view.findViewById(R.id.radiogroup);
int has_radiogroup = 0;
for (int i = 0; i <inputDetailsList.size(); i++){
if (inputDetailsList.get(i).get("type").equals("radio")){
has_radiogroup = 1;
RadioButton rb = new RadioButton(rg.getContext());
rb.setText(inputDetailsList.get(i).get("textcontent"));
rg.addView(rb);
}
}
return view;
}
Here is the xml file that is used as child layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="55dip"
android:background="#color/ExpandChildBackground"
android:orientation="vertical" >
<TextView
android:id="#+id/tvChild"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#color/Black"
android:textSize="17dip" />
<RadioGroup
android:id="#+id/radiogroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
</RadioGroup>
</LinearLayout>
The line where I suspect my error could be this one:
RadioGroup rg = (RadioGroup) view.findViewById(R.id.radiogroup);
It looks for the radio group I created inside the inflated child layout (R.layout.child_layout). But it does not use a new one for each expanded child view and instead uses an existing one to apply the buttons to. In other words, it seems like the radio group never gets the sign that its "finished" and/or the child view never gets the sign that a new radioGroup has to be used instead of the old one.
What I have tried is creating a new RadioGroup for each child view using the following line (you can see it is the commented line in the code above), instead of using the radiogroup I defined in my layout.
Making a fresh radiogroup would look like this:
RadioGroup rg = new RadioGroup(view.getContext());
However, this does not work, it does not display any radio groups, let alone buttons at all. I have also tried removing the radiogroup element from the layout xml-file (because its not used anyway). Still no luck. Using simple unorganized textviews for each element seems to work properly, so this points to a problem with my radio group implementation as well.
Honestly, I am out of ideas right now. I might be getting the wrong context, but I have no clue what context to use. If anyone is able to point me the right direction, I would be extremely grateful. Thanks in advance.
If anyone is interested, I have been able to fix the problem myself. I have simply removed the if-condition [ if (view == null) ], so the new code looks like this:
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view,
ViewGroup parent) {
ExpandListChild child = (ExpandListChild) getChild(groupPosition, childPosition);
LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = infalInflater.inflate(R.layout.child_layout, null);
ArrayList<HashMap<String,String>> inputDetailsList = child.getInputfields();
RadioGroup rg = (RadioGroup) view.findViewById(R.id.radiogroup);
int has_radiogroup = 0;
for (int i = 0; i <inputDetailsList.size(); i++){
if (inputDetailsList.get(i).get("type").equals("radio")){
System.out.println("type: "+inputDetailsList.get(i).get("type"));
has_radiogroup = 1;
RadioButton rb = new RadioButton(rg.getContext());
rb.setText(inputDetailsList.get(i).get("textcontent"));
System.out.println("textcontent: "+inputDetailsList.get(i).get("textcontent"));
rb.setId(Integer.parseInt(inputDetailsList.get(i).get("value")));
if (has_radiogroup == 1){
rg.addView(rb);
}
}
}
return view;
}
Now it makes sense. The LayoutInflater is called everytime a new child view is generated, i.e. a group is expanded. Before this, it just used the existing view (view was not null) that was filled with radiobuttons, and added the new radiobuttons to that existing view, resulting in my list flooding the screen.
Thanks however to anyone trying to get their heads into the problem.
This is worked for me.
For RadioButtons and CheckBoxs
android:focusable="false"

Detect click on checkbox in custom ListView layout?

I know there's tons of other threads around about this same topic, but none of them seem to work with my scenario and I couldn't get my listview to work with their code. Basically, I'm using a SimpleCursorAdapter to populate a listview with items from the database. Each listview row uses a custom layout which consists of a checkbox and a line of simple text. How do I detect a click on the checkbox? I know I need to use OnItemClickListener, but I don't know how to incorporate that into my code. Here's my code:
remindersCursorAdapter = new SimpleCursorAdapter(this,
R.xml.view_reminders_item_layout,
remindersCursor, new String [] { RemindersDAO.NAME },
new int[] { R.id.view_reminders_item_text } );
viewRemindersListView.setAdapter(remindersCursorAdapter);
R.xml.view_reminders_item_layout is the custom listview layout file. How do I capture the checkbox from this file and set a click listener to it? Thanks for all your help!
If you want to check the checkbox when a item is clicked, you can do it by setting checked status of Checkbox in onItemClick method.
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
// now get the checkbox view. Then set the checked status.
CheckBox checkbox = (CheckBox) view.findViewById(R.id.check_box);
checkBox.setChecked(!checkbox.isChecked());
}
If you want to detect the click on only checkbox then set the focusable true in xml.
// in your custom list view item. It takes the current view focus.
<Checkbox>
android:focusable="true"
</Checkbox>

Categories