Recyclerview add radiobutons programmatically - android

I am creating an Android app with Java which displays a question and 3 or 4 options for it (MCQ app). I have used a RecyclerView with a TextView in the XML to hold the question.
However, I am confused on how to create the radio button/checkbox for the option part since those are dynamic. Meaning, a question might have any number of options as radio button from 1 to 6 depending on the entries in the database. Also, few of the question might have checkbox rather than radio button again depending on the DB entries.
Since these are decided at runtime, there is no way I can keep these radiobuttons/checkboxes in the XML file. Initially I tried creating them inside onBindViewHolder method but doing that significantly slows down the scrolling since this method gets called even while scrolling. Since this is a very common use case, I would like to believe the framework must have readily available solution for this which I am yet to discover.
I do not want to add all the possible radiobuttons/checkboxes and play with the visibility of those in runtime.

You can create your xml file as -
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Question Text " />
<RadioGroup
android:id="#+id/radioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp" />
</LinearLayout>
In Your adapter let you have arraylist of Questions say
ArrayList<Question> queList;
Instance of Question contain
class Question{
String question;
int nubOfOptions;
String[] options;
int selectedOption = 0;
}
now First take the id of radioGroup in ViewHOlder as -
RadioGroup radioGroup = (RadioGroup)view.findViewById(R.id.radioGroup);
Now in onBindViewHolder you can do as -
onBindViewHolder(int position, ....){
Question que = queList.get(position);
radioGroup.removeAllViews();
for(int count=0; count<radioBtnCount;count++){
RadioButton btn= new RadioButton(context);
btn.setText("you option");
if(selectedOption==count+1){
btn.setCheck(true);
}
radioGroup.addView(btn);
}
}
you have to remove all views otherwise you will face problem while scroll.

Related

Giving id's to dynamically created views

I'm a beginner in coding, and I would love some help. I want to make an alarm application. On my main page fragment, I added a button that will add an alarm into a LinearLayout inside a ScrollView. The alarm will have three TextViews in it, and a button for activation/deactivation.
Here is how I would like my alarm to look like (this is currently not being used anywhere in my coding; I created it just to have a visual aid of what I'm aiming to make):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:id="#+id/alarm_fl"
android:background="#mipmap/white_box">
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="9.5dp"
android:id="#+id/alarm_activation_button"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="70dp"
android:layout_marginTop="5dp"
android:textSize="10pt"
android:id="#+id/alarm_time"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="165dp"
android:layout_marginTop="11.5dp"
android:textSize="7pt"
android:id="#+id/alarm_ampm"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="70dp"
android:layout_marginTop="30dp"
android:textSize="5pt"
android:id="#+id/alarm_day"/>
</FrameLayout>
This is how I'm currently testing my alarms in the fragment:
addAlarm.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
LayoutInflater alarm_inflater = (LayoutInflater) getContext().getSystemService(LAYOUT_INFLATER_SERVICE);
ViewGroup parent = (ViewGroup) getActivity().findViewById(R.id.alarm_ll);
View alarm_view = alarm_inflater.inflate(R.layout.alarm_layout, parent);
TextView alarm_time = (TextView) alarm_view.findViewById(R.id.alarm_time);
alarm_time.setText("9시 45분");
TextView alarm_ampm = (TextView) alarm_view.findViewById(R.id.alarm_ampm);
alarm_ampm.setText("오후");
TextView alarm_day = (TextView) alarm_view.findViewById(R.id.alarm_day);
alarm_day.setText("월,화,수,목,금");
Button activation_button = (Button) alarm_view.findViewById(R.id.alarm_activation_button);
activation_button.setBackgroundResource(R.mipmap.checkbox_deactivated);
}
});
where alarm_ll is the LinearLayout that I want to populate with newly created alarms.
And it appeared to me that I need unique id's for each of the Buttons and TextViews to manipulate them separately.
Now here are my questions:
Is this the right approach if I want to add views programmatically whenever the button is clicked? Or is there a better, simpler way?
My alarms would eventually need to be objects. Would it be possible for a non-activity class like User, or in this case Alarm, to have a layout for it's own?
How do I give unique id's to each view when creating via a button click?
When I test-run my application now, the layouts I add into alarm_ll won't be saved, so if I shift to another activity and come back, alarm_ll will be reset. How do I save these in a fragment, when they are not in primitive data types?
I'm sorry to ask so many questions at once, but I would really love some answers or suggestions. Thank you.
I assume that you want to have the ability to set multiple alarms. This is a perfect use of ListView or RecyclerView which allows you to inflate several copies of the same view and display a list based on some underlying data.
I suggest that you learn about creating "model" which are objects that store the data. These "model" objects should be separate from the view objects which display the data. There are several design patterns which are commonly used for this kind of separation: Model-View-Controller, Model-View-Presenter, and Model-View-ModelView.
android:id in XML is typically used to be able to get an object for the view in the Java code. When you create a view dynamically, either the way you showed in your question or by inflating XML, you already have this object, so I do not see a need for assigning an ID to these dynamically created views.
When using one of the design patterns which I suggested in #2, you will also create a way to store the data. Android provides an API to store information in a database. This can easily be displayed in a ListView or RecyclerView by using an "adapter".

how to create a multiple row activity

how do i create a multiple row app with the same data for each row. This is how all the rows are to look like. it contains three text views and two spinners. this app is to help calculate the gpa of a student for one semester.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.mbedobe.android.samplegpacalculator.app.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C1"
android:id="#+id/course_textView"/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spinner"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/course_textView"
android:layout_toEndOf="#+id/course_textView"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp" />
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spinner2"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/spinner"
android:layout_toEndOf="#+id/spinner"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/spinner2"
android:layout_toEndOf="#+id/spinner2"
android:id="#+id/gradePoints"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/gradePoints"
android:layout_toEndOf="#+id/gradePoints"
android:id="#+id/gradeValue"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp"/>
</RelativeLayout>
You should think about using a ListView with BaseAdapter.
The best solution is to use RecycleView
Use a RecyclerView with a custom adapter. The layout above will be the row layout for each row in this case.
Use the links above to understand how you can create your own Custom RecyclerView Adapters with Custom Layouts.
EDIT:
Ok, I'll give you the basics here. There are three major things you need for a custom RecyclerView.
They are:
List of Objects (your data)
A custom layout for each row
An Adapter that will transform your data onto the above layout.
Now, let's take an example and try and explain this.
You must have seen popular apps like Gmail, WhatsApp, etc.
When you open these apps, you see a list of Emails/Chats etc.
One thing to notice is that the layout for each row is same, even though the content inside them is different.
This tells us 2 things: first that the data must be a list of the same kind of objects, and secondly that the layout of each row is the same. So, to create such a listView or RecyclerView, we shouldn't need to create as many layouts as there are rows. One layout can be reused for each row.
So, two of our three needs are understood. The final item required is the Adapter. The adapter is what takes your List and converts each item from the list into a row on your RecyclerView. These rows are automatically created by the Adapter as the user scrolls through the list, and removed when the user can no longer see those rows.
If you want code for this, let me know. I'll upload code explaining this. But I would recommend you try it out on your own. It's not that hard.
Either use ListView, recyclerView or dynamically add the items in scrollview.
Use of ListView or RecyclerView will be the best approach for you.
I'll give you the last option that should be worked from java only if you are with good knowledged in java. ( only the steps not complete code)
1) your xml file should contain scroll view.
2) for each item to be added (3 textview 2 spinner), add a layout and provide layout params for it i.e width/height/orientation/background etc.
3)add this layout to the scrollview you created in xml by
findViewById(R.id.scrollviewId).add(layout)
4)create your textviews/spinners in and give them layout params.{ this process is much logical in a pattern of your design so must be very careful}
5)add all these textviews/spinners in the layout you created in step 3.
Note: according to your design requirements you might need to add other layouts in between the layout created in step 2/3 and other items created in step 4.
Here is the code you liked:
LinearLayout myLayout = (LinearLayout)findViewById(R.id.layout_in_xml);
for(int i = 0; i < required_fields.length; i++){
LinearLayout lr = new RelativeLayout(DisplaySadip.this);
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lr.serLayoutParams(layoutParams);
lr.setOrientation(LinearLayout.HORIZONTAL);
//add linear layout to your layout in xml
myLayout.add(lr);
//add textview, spinner to this layout now
TextView tv1 = new TextView(YourActivity.this)
tv1.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv1.setText("......"+i);
lr1.add(tv1)
Spinner spinner1 = new Spinner(YourActivity.this)
spinner.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
Spinner spinner2 = new Spinner(YourActivity.this)
spinner.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
lr.add(spinner1);
lr.add(spinner2);
TextView tv2 = new TextView(YourActivity.this)
tv2.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv2.setText("......"+i);
lr.add(tv2)
TextView tv3 = new TextView(YourActivity.this)
tv3.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv3.setText("......"+i);
lr1.add(tv3)
}
it shall add add many no of views you want in your layout.

Android how to create textview one over another

I am developing an Android application with a textview updated by one event and at the same place where the textview is present, I want 1 more textview so that other event can update this new textview. How do i achieve in having 1 textview on other
I'm assuming that you're asking how you could have two TextView components overlaying each other. There are a few way you could do this.
Frame Layout
Use a Frame Layout to determine the area in which the TextViews will occupy. Like this...
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/tv1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/tv2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</FrameLayout>
Credit goes to https://stackoverflow.com/a/2634059/3769032
Create a Compound View
This is fairly in-depth for the type of question you are asking. CompoundViews are a collection of typical views, such as a TextView, that you can create if you plan on re-using the view frequently.
If you plan on overlaying the TextViews often, I recommend this. So check out this tutorial.
Use only one TextView
Having two overlayed textviews can become messy really quickly. If you have two pieces of text overlayed is becomes impossible to read. So since the content of your textview is based on an event. Use the same event listener in your java code to determine the content of your TextViews.
For example, in your on click listener you might have...
TextView tv1 = (TextView) findViewByID(R.id.tv1);
public void onClick(View view){
if (first_event_happened){
tv1.setText("One event happened");
} else if(second_event_happened){
tv1.setText("A different event happened");
}
}
These conditions might mean checking the type of view that was clicked, or checking its id (what I usually do). Please comment if things aren't clear. Some clarification on your question would be helpful too.
use relative layout and also you can set text on exiting textView like when event one triggered textView.setText(your text) and same when event two triggered textView.setText(your text)
There is no trick to this. Just put two TextViews in a RelativeLayout at the same position and they will draw overtop of one another. Like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="first textview"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="second textview"/>
</RelativeLayout>
You can make each one visible or invisible by using TextView.setVisibility(...) or you can set their text with TextView.setText(...).

Android: what is the best way to show a TextView in case if no item in a ListView?

I need to show a list of items, the items are read from a database, and it is possible there is no item, in this case, I just want to show a TextView saying "there is no item", I think I could implement this by using relative layout, both list and text are in center of parent, they are displayed alternatively, but is there any way better than this?
Thanks!
Adding to Aleadam , Bill Mote
You may call at any time AdapterView.setEmptyView(View v) on an AdapterView object to attach a view you would like to use as the empty view.
The snippet is as follows:
empty = (TextView)findViewById(R.id.empty1);
list = (ListView)findViewById(R.id.list1);
list.setEmptyView(empty);
Make sure you keep the ListView and TextView inside the same parent.
For detailed description please refer this
If you're using a ListActivity, that is the default behavior. If not, then you can set the ListView visibility to GONE and a TextView visibility to VISIBLE.
Aleadam is right. Here's an example XML in support of his answer:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
<ListView
android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<TextView
android:id="#id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="#drawable/red"
android:gravity="center_vertical|center_horizontal"
android:textStyle="bold"
android:text="#string/error_no_groups"
/>
</LinearLayout>
The first tutorial on the Android developer website explains how to do this:
http://developer.android.com/resources/tutorials/notepad/notepad-ex1.html
(Look under Step 4)
Snippet:
The ListView and TextView can be thought as two alternative views, only one of which will be displayed at once. ListView will be used when there are notes to be shown, while the TextView (which has a default value of "No Notes Yet!" defined as a string resource in res/values/strings.xml) will be displayed if there aren't any notes to display.
The View with the empty id is used automatically when the ListAdapter has no data for the ListView. The ListAdapter knows to look for this name by default. Alternatively, you could change the default empty view by using setEmptyView(View) on the ListView.

Set, get text and value in listitem view in Android

I have listview collection that show id and name in Android. I following example from this resource site.
But actually that example only display name. I wish similar like checkboxlist in ASP.NET that contain property text and value. So the text to show name and value store id. When user select one item, I could retrieve id by viewtext.
My question is how do I set id and name in same viewtext item? I wish could pass the id to another layout.
I know that possible using multi viewtext then set invisible of viewtext using map. How that could be waste memory.
i would suggest a custom listview. you can google for "custom listview" and will find a bunch of tutorials on that. simply said, it is a listview that has a custom row that you can specify in a xml file.
here is a quite useful tutorial to start with.
here is what i coded, maybe it will help you. note that this is a bit different, because i am not defining a listactivity but a listview widget. but concerning the custom row item, it won't matter.
this will create a listview and specify an adapter for that listview.
CustomListView listview = (CustomListView) findViewById(R.id.list);
ArrayAdapter<String> arrayadapter = new ArrayAdapter<String(getApplicationContext(), R.layout.rowoflistview, R.id.label);
listview.setAdapter(arrayadapter);
my rowoflistview.xml looks like the following. it adds an image and a text to each row of the list. you can of course change it to (mostly) whatever you want.
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/rowselector"
>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/musicicon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:src="#drawable/musicicon"
android:paddingLeft="3px"
/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="26px"
android:layout_marginLeft="3px"
android:singleLine="true"
android:ellipsize="end"
android:focusable="false"
/>
</LinearLayout>
as i wanted the listview as a widget in my main activity and not as a fullscreen activity, i had to do it other than you when it comes to event listening and click listening. if you want it a bit easier, be sure to extend the listactivity in your custom listview-activity and override the default methods.
hope that was understandable to get a grip on the topic ;)
Views have an associated tag Object map, which could contain your id http://developer.android.com/reference/android/view/View.html#getTag%28int%29

Categories

Resources