i make dynamic radio button list inside each row in recyclerview but when i random scroll all radio button uncheked i use model to store radiobutton condition,notifyItemChanged,initialize first cheked,using layout instead radiogroup , and use selection condition to check spesific radiobutton, but i cant solve this problem
following the first picture all radio button is checked
but when scrolling down and back up all radiobutton is not checked
this my item layout inside recyclerview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayoutlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<LinearLayout
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/questionText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sumber Data" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:orientation="vertical">
<CheckBox
android:id="#+id/tidak_ada"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Tidak Ada" />
</LinearLayout>
</TableRow>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<RadioGroup
android:id="#+id/radiogroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"/>
<LinearLayout
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"></LinearLayout>
</LinearLayout>
</LinearLayout>
my code to create radiobutton inside adapter in onBindViewHolder
var rprms = InputFieldHolder.radiogroup?.layoutParams
if(rprms != null && question.pilihan_jawabans.count() > 0){
InputFieldHolder.radiogroup?.removeAllViews()
question.pilihan_jawabans.forEachIndexed {i,e->
val rdbtn = RadioButton(context)
rdbtn.id = question.pilihan_jawabans[i].id
rdbtn.text = question.pilihan_jawabans[i].isi.toString()
rprms = RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
InputFieldHolder.radiogroup?.addView(rdbtn, rprms)
val size = InputFieldHolder.radiogroup?.childCount?.minus(1)
if(question.pilihan_jawabans[i].checked){
for (x in 0..size!!) {
if((InputFieldHolder.radiogroup?.getChildAt(x) is RadioButton)){
if((InputFieldHolder.radiogroup?.getChildAt(x) as RadioButton).id != question.pilihan_jawabans[i].id){
(InputFieldHolder.radiogroup?.getChildAt(x) as RadioButton).setChecked(false)
}
}
}
}
rdbtn.setChecked(question.pilihan_jawabans[i].checked)
rdbtn.setTag(Integer(question.pilihan_jawabans[i].id))
rdbtn.setOnCheckedChangeListener({ group, checked ->
question.pilihan_jawabans.forEachIndexed {ii,ee->
if(checked){
question.pilihan_jawabans[ii].checked = false
}
}
question.pilihan_jawabans[i].checked = checked
notifyItemChanged(position)
})
}
}
my model to store radiobutton checked state
#Parcelize
class QuestionSelection(
var id : Int,
var isi : String,
var keterangan : String,
var checked : Boolean = false
) : Parcelable
NOTE : my radiobutton is dynamic so not just 2 option but more than it,depending on the data that I took from the API
after few hour to solve , i finally got what cause the problem.i always call InputFieldHolder.radiogroup?.removeAllViews() to destroy all radiobutton and make new with new satet but radio group always save state from previous radiobutton has been destroy so in last i just call InputFieldHolder.radiogroup?.clearCheck() after destroy radio button to clear all check state inside the radio group
Related
I have a form in my app which requires the user to enter his/her height and weight. There are two radio buttons of imperial and metric units. I want to show one height edittext (meters) when the user chooses imperial in the radiogroup and two edittexts (feet + inches) for metric. How can I implement this?
Use both edittexts (in meters) and (in feet-inches) with one have android:visibility="gone"
when user selects the metric hide the another one edittext and show edittexts (feet + inches) and when user selects the imperial then hide the other and show height edittext (meters)...
Try with the following code working fine.
//activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingHorizontal="15dp">
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/radioGroup1">
<RadioButton
android:id="#+id/imperial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Imperial" />
<RadioButton
android:id="#+id/metric"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Metric" />
</RadioGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:orientation="vertical">
<EditText
android:id="#+id/height_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:hint="Input height" />
<EditText
android:id="#+id/feet_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginTop="20dp"
android:hint="Input Feet" />
<EditText
android:id="#+id/inches_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginTop="10dp"
android:hint="Input Inches" />
</LinearLayout>
</LinearLayout>
//activity code
class TestActivity : AppCompatActivity() {
private lateinit var heightEdt: EditText
private lateinit var feetEdt: EditText
private lateinit var inchesEdt: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
heightEdt = findViewById(R.id.height_et)
feetEdt = findViewById(R.id.feet_et)
inchesEdt = findViewById(R.id.inches_et)
val rg = findViewById<View>(R.id.radioGroup1) as RadioGroup
rg.setOnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.imperial -> {
heightEdt.isVisible = true
feetEdt.isVisible = false
inchesEdt.isVisible = false
}
R.id.metric -> {
heightEdt.isVisible = false
feetEdt.isVisible = true
inchesEdt.isVisible = true
}
}
}
}
}
Using Listview, I deleted item if check box is checked.
Although it has been implemented through googling, it does not work when you press the checkbox and then press the delete button.
I wrote it like the source below, but nothing reacts. What should I fix?
<MainActivity.kt>
lv.choiceMode = ListView.CHOICE_MODE_MULTIPLE
val del = binding.delBtn
val lv = binding.lvMainMusic
del.setOnClickListener {
val count: Int = mainAdapter.count
if (count > 0) {
val checked: Int = lv.checkedItemPosition
if (checked > -1 && checked < count) {
playList.removeAt(checked)
mainAdapter.notifyDataSetChanged()
lv.clearChoices()
}
}
}
}
<Music_items.xml>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/album_img"
android:layout_width="75dp"
android:layout_height="75dp"
android:paddingLeft="10dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/song"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:text="title"
android:textSize="15dp" />
<TextView
android:id="#+id/singer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:text="singer" />
</LinearLayout>
<CheckBox
android:id="#+id/choose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingTop="10dp"
android:paddingRight="10dp" />
So what I understood from the question is that whenever the user checks an item and then clicks on delete, you want to remove that checked item from the list and update the UI accordingly in listView. Generally, when you want to remove that item you have to remove it from the mainAdapter's list. Something like
mainAdapter.remove(checked)
And in mainAdapter you have a method defined that removes the item at that position from its list like
fun remove(position: Int){
playList.remove(position)
notifyDataSetChanged()
notifyItemRangeChanged(0, playList.size)
}
Sorry if I misunderstood the question..
I got the following composition:
This layout is an Item of my RecyclerView.Adapter. The X button (holder.delete_button), when clicked, deletes himself and the EditText; basically it removes the row.
The ADD FIELD button add new rows (by inflater):
Here's the code to add new line:
holder.add_field_button.setOnClickListener {
holder.parent_layout.apply {
val inflater = LayoutInflater.from(context)
val rowView = inflater.inflate(R.layout.generated_layout, this, false)
holder.parent_layout.addView(rowView, holder.parent_layout.childCount!! - 0)
}
}
My problem here is that I just can delete the first row, because is the only button I can initialize in the ViewHolder by the id of delete_button. But for the next X buttons, I can't do no action, because the button it's in an external layout inflated, called generated_layout! I've tried to generate ids but then I don't know how to put them into an array. Here's the code to delete a row:
holder.delete_button.setOnClickListener{
holder.parent_layout.removeView(holder.delete_button.parent as View)
}
Here's the code of generated_layout, as well:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"
android:inputType="phone"/>
<Button
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_weight="0"
android:background="#android:drawable/ic_delete"/>
</LinearLayout>
Set the onClick listener like this
holder.add_field_button.setOnClickListener {
holder.parent_layout.apply {
val inflater = LayoutInflater.from(context)
val rowView = inflater.inflate(R.layout.generated_layout, this, false)
val rowViewDeleteButton=rowView.findViewById(R.id.deletebutton)
rowViewDeleteButton.setOnClickListener{
holder.parent_layout.removeView(it.parent as View)
}
holder.parent_layout.addView(rowView, holder.parent_layout.childCount!! - 0)
}
}
And give id to your delete button :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<EditText
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"
android:inputType="phone"/>
<Button
android:id="#+id/deletebutton"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_weight="0"
android:background="#android:drawable/ic_delete"/>
</LinearLayout>
I am working on an application where I have multiple linear layouts which are dynamically generated. Each linearlayout has an Id field, Name and a radioGroup containing two radio buttons for Yes and No.
I am also providing a button at bottom of the page so that once the button is clicked, All the YES radio buttons are selected.
How can i achive this as the layout is dynamically generated based on some data:
Here is my layout which is repeated dynamically:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:weightSum="10">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="10">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
android:id="#+id/RollNum"
android:textSize="20dp"
android:textColor="#color/black"
android:gravity="center"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="70dp"
android:layout_weight="6"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Amandeep Singh and some very very long name"
android:gravity="center"
android:id="#+id/Name"
android:textSize="20dp"
android:textColor="#color/black"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:gravity="center">
<RadioGroup
android:id="#+id/radioAttendance"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation='horizontal'
android:gravity="center">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="P"
android:id="#+id/PresentCheck"
android:textSize="10dp"
android:gravity="center"
android:textColor="#color/black"
/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
android:id="#+id/AbsentCheck"
android:textSize="15dp"
android:gravity="center"
android:textColor="#color/black"
/>
</RadioGroup>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.1">
<View
android:layout_width="fill_parent"
android:layout_height="0.1dp"
android:background="#ffffff" />
</LinearLayout>
</LinearLayout>
I tried following approach but didn't work:
//some code before it for button clicks and all other stuffs
LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout scrollViewLinearlayout = (LinearLayout)findViewById(R.id.parent); // The layout inside scroll view
//int count=50;
Studentlist = Arrays.copyOfRange(StudentlistInterim, 1, StudentlistInterim.length);
for(int i = 0; i < Studentlist.length; i++){
String data = Studentlist[i];
String RollNum = data.split("--")[0];
String Name = data.split("--")[1];
Log.d("Name is:", Name);
LinearLayout layout2 = new LinearLayout(context);
layout2.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
View item = inflater.inflate(R.layout.item_layout, null, false);
layout2.addView(item);
layout2.setId(i);
TextView trollnum = (TextView) item.findViewById(R.id.RollNum);
trollnum.setText(RollNum);
TextView tname = (TextView) item.findViewById(R.id.Name);
tname.setText(Name);
RadioButton rPresent = (RadioButton)item.findViewById(R.id.PresentCheck);
RadioButton rAbsent = (RadioButton)item.findViewById(R.id.AbsentCheck);
rPresent.setId(i); //tried to set a unique Id for all YES
rAbsent.setId(Studentlist.length+i); // to make the id unique for each YES and NO entry
scrollViewLinearlayout.addView(layout2);
Log.d("Id is: ", trollnum.getText().toString());
}
}
#Override
public void onClick(View v){
switch(v.getId()){
case R.id.bMarkAllPresent:
for (int i=0;i<Studentlist.length;i++){//iterate over the list for the radio buttons
RadioButton r1 = (RadioButton)findViewById(i);
RadioGroup rg = (RadioGroup)findViewById(R.id.radioAttendance);
rg.check(r1.getId()); /* get the id of radio button one by one and mark it checked*/
//Log.d("Button check id:", (r1.getId()));
}
break;
I got 'java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.RadioButton' error in the onClick() method
I am not sure if this approach will work or if this is the best approach.
Please help.
Edit-1:
After using the List way of doing it as per the answer.
RadioButton rPresent = (RadioButton)item.findViewById(R.id.PresentCheck);
RadioButton rAbsent = (RadioButton)item.findViewById(R.id.AbsentCheck);
//rPresent.setId(i);
//rAbsent.setId(Studentlist.length+i); // to make the id unique for each present and absent entry
presentRadioList.add(rPresent); //getting null pointer here
absentRadioList.add(rAbsent);
I am getting null pointer exception.
I suggest keeping two List<RadioButton>s, one for the "yes" selections and one for the "no" selections. Then you can just iterate through the appropriate list.
I am trying to map a List<List<Object>> to a RecyclerView in Android, but the result is totally messed up.
For example, I have a list of list like this (just for explaining, not my real case):
List<List<String>> list = {{a, b, c}, {d, e}, {f, g, h, i}};
the Recyclerview should display like (first row contains three subrows, second has two and the last on has four):
|----a-----|
|----b-----|
|----c-----|
|=======|
|----d-----|
|----e-----|
|=======|
|----f-----|
|----g-----|
|----h-----|
|----i-----|
but the result is not exactly like the above order. some element is duplicated and some disappears. for example:
|----d-----|
|----e-----|
|----c-----|
|=======|
|----d-----|
|----e-----|
|=======|
|----f-----|
|----a-----|
Here is a piece of my code:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
List<Event> list = eventList.get(position);
if (holder.rows < list.size()) {
holder.rowViewGroup.removeAllViews();
holder.rows = 0;
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
TextView startView = new TextView(context);
startView.setLayoutParams(layoutParams);
Event headEvent = list.get(0);
Calendar startCal = headEvent.getStartCal();
startView.setText(String.format("%tD", startCal));
holder.rowViewGroup.addView(startView);
for (final Event event : list) {
View element = LayoutInflater.from(context).inflate(R.layout.element, null);
//start time view
TextView startTimeView = (TextView)element.findViewById(R.id.eventStartTimeInElement);
Calendar startTimeCal = event.getStartCal();
startTimeView.setText(String.format("%tl:%tM %tp", startTimeCal, startTimeCal, startTimeCal));
//end date time view
TextView endView = (TextView)element.findViewById(R.id.eventEndTimeInElement);
Calendar endCal = event.getEndCal();
endView.setText(String.format("%tD %tl:%tM %tp", endCal, endCal, endCal, endCal));
//title view
TextView title = (TextView)element.findViewById(R.id.eventTitleInElement);
title.setText(event.getTitle());
//member name
Drawable divider = context.getResources().getDrawable(R.drawable.divider);
ImageView dividerView = new ImageView(context);
dividerView.setImageDrawable(divider);
holder.rowViewGroup.addView(dividerView);
holder.rowViewGroup.addView(element);
holder.rows++;
}
}
}
Here is my row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recycleViewRow">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="2sp"
card_view:cardUseCompatPadding="true"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/rowView"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/eventStartTimeInRow"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
and element.xml(which is contained by row.xml):
<?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="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/eventStartTimeInElement"
android:layout_weight="2" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/eventEndTimeInElement"
android:gravity="end"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/eventTitleInElement"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="2sp"
card_view:cardUseCompatPadding="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/memberNameInElement"
android:gravity="end"
/>
</android.support.v7.widget.CardView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
And I know this is not a really good idea to implement this, so could anybody please tell me a better way to implement this? Thanks...
I think your best bet is to flatten your list of lists into one list.
This is just for purposes of the ListView. Your adapter will act as though the lists have all been strung into one long list.
Start by creating a single-list index for all the items of your nested lists.
For example:
List<List<String>> listOfLists = ... // your original data
List<String> listForView = new ArrayList<String>();
for (List<String> innerList : listOfLists) {
for (String str : innerList) {
listForView.add(str);
}
listForView.add("---"); // e.g. marker value for divider
}
Now in your adapter's getItem() need only return listForView.get(position).
Anytime your nested list structure changes, you redo this flattening operation and call notifyDataSetChanged().
Things get a little trickier if — given the position — you have to figure out which list an item is in, but you could always index the inner lists in a similar fashion.