Create RecyclerView UI dynamically - Android - android

I am working on an e-commerce App . Here I am working on Products Filtering .
Here filters are dynamic, It means once filter page will display BRANDS and PRICE then next time it can display BRANDS , PRICE , STYLES ..etc .
There may be many cases to filter products .
Application is receiving filters dynamically from Webservice .
So here I am creating filters dynamically using data received from the webservice . For this I am using RecyclerView to display dynamic filters
.
Here is the code of RecyclerView where I am creating filters dynamically .
onCreateViewHolder() :
#Override
public FilterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LinearLayout topLayout = new LinearLayout(mContext);
topLayout.setOrientation(LinearLayout.VERTICAL);
if (filterItems != null) {
for (int filterItemsCount = 0; filterItemsCount < filterItems.size(); filterItemsCount++) {
LinearLayout ll = new LinearLayout(mContext);
ll.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(10, 10, 10, 10);
AFileterItem filterItem = filterItems.get(filterItemsCount);
TextView textView = new TextView(mContext);
textView.setText(filterItem.getFiletrLabel());
ll.addView(textView);
for (int i = 0; i < filterItem.getList().size(); i++) {
VlauesItem item1 = filterItem.getList().get(i);
CheckBox cb = new CheckBox(mContext);
cb.setId(i);
cb.setText(item1.getValueItemLabel());
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Toast.makeText(mContext, String.valueOf(isChecked), Toast.LENGTH_SHORT).show();
}
});
ll.addView(cb);
}
topLayout.addView(ll);
}
}else{
topLayout.addView(null);
}
FilterViewHolder viewHolder = new FilterViewHolder(topLayout);
return viewHolder;
}
Now , the problem is :
When I create filters dynamically then RecyclerView creates same filter more than once .
I want to know how should I manage above code so that I can eliminate this problem .

You need to understand what ViewHolders are. ViewHolder of a concrete type has single layout. If it is possible consider creating different viewholder types, or one with predefined layout, which will be customized in onBind callback. What you see is happening, because RecyclerView reuses view, and calls onCreateViewHolder only to fill the screen with items, then they are reused.

Related

Save dynamically created tablelayout on screen rotation

I am working on an app that uses 5 tabs and each tab has a different fragment. In all of these fragments I have from 1 up to 10 dynamically created tablelayouts and each one of them can have as many rows as the user wants. Each row may have up to 16 columns of EditText, Spinner, Checkbox. My problem is that when I rotate my phone I lose all the data inside these tablelayouts. My ViewPagerAdapter that hosts these fragments extends FragmentStatePagerAdapter. I am not losing any data outside the tables. I understand that when I rotate the phone they are recreated but I want to keep my data. I do not want to create a database because when I finish adding data in my app I want to save everything to a .txt file. This is code for one of my tables
table18 = (TableLayout) view.findViewById(R.id.blg_parameter18_table);
TableRow.LayoutParams tlparams18 = new TableRow.LayoutParams(
TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
//Create header
TableRow table18HeaderRow = new TableRow(view.getContext());
table18HeaderRow.setLayoutParams(tlparams18);
TextView table18HeaderColumn0 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn0, R.string.blg_parameter18_0, tlparams18);
TextView table18HeaderColumn1 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn1, R.string.blg_parameter18_1, tlparams18);
TextView table18HeaderColumn2 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn2, R.string.blg_parameter18_2, tlparams18);
TextView table18HeaderColumn3 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn3, R.string.blg_parameter18_3, tlparams18);
TextView table18HeaderColumn4 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn4, R.string.blg_parameter18_4, tlparams18);
TextView table18HeaderColumn5 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn5, R.string.blg_parameter18_5, tlparams18);
TextView table18HeaderColumn6 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn6, R.string.blg_parameter18_6, tlparams18);
TextView table18HeaderColumn7 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn7, R.string.blg_parameter18_7, tlparams18);
TextView table18HeaderColumn8 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn8, R.string.blg_parameter18_8, tlparams18);
TextView table18HeaderColumn9 = new TextView(view.getContext());
setTableHeaderView(table18HeaderRow, table18HeaderColumn9, R.string.blg_parameter18_9, tlparams18);
table18.addView(table18HeaderRow);
createRowTable18(table18, table18NumOfRows, tlparams18);
public void createRowTable18(TableLayout table18, int numOfRows, TableRow.LayoutParams tlparams18) {
TableRow table18Row = new TableRow(table18.getContext());
table18Row.setLayoutParams(tlparams18);
table18Row.setId(numOfRows);
CheckBox table18RowColumn1 = new CheckBox(getContext());
CheckBox table18RowColumn2 = new CheckBox(getContext());
CheckBox table18RowColumn3 = new CheckBox(getContext());
CheckBox table18RowColumn4 = new CheckBox(getContext());
CheckBox table18RowColumn5 = new CheckBox(getContext());
CheckBox table18RowColumn6 = new CheckBox(getContext());
EditText table18RowColumn7 = new EditText(getContext());
final TextView table18RowColumn8 = new TextView(getContext());
EditText table18RowColumn9 = new EditText(getContext());
Spinner spinner18 = new Spinner(getContext());
ArrayAdapter<CharSequence> adapter18 = ArrayAdapter.createFromResource(getContext(),
R.array.blg_parameter18_1_array, android.R.layout.simple_spinner_item);
adapter18.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner18.setAdapter(adapter18);
table18Row.addView(spinner18);
spinner18.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selection = (String) parent.getItemAtPosition(position);
if (!TextUtils.isEmpty(selection)) {
if (selection.equals(getString(R.string.blg_parameter_18_1_0))) {
table18RowColumn8.setText(null);
} else if (selection.equals(getString(R.string.blg_parameter_18_1_a))) {
table18RowColumn8.setText("kWh");
} else if (selection.equals(getString(R.string.blg_parameter_18_1_b))) {
table18RowColumn8.setText("lt");
} else if (selection.equals(getString(R.string.blg_parameter_18_1_c))) {
table18RowColumn8.setText("lt");
} else if (selection.equals(getString(R.string.blg_parameter_18_1_d))) {
table18RowColumn8.setText("Nm^3");
} else if (selection.equals(getString(R.string.blg_parameter_18_1_e))) {
table18RowColumn8.setText("Nm^3");
} else if (selection.equals(getString(R.string.blg_parameter_18_1_f))) {
table18RowColumn8.setText("kg");
} else if (selection.equals(getString(R.string.blg_parameter_18_1_g))) {
table18RowColumn8.setText("kWh");
}
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
setTableRowCheckBox(table18Row, table18RowColumn1);
setTableRowCheckBox(table18Row, table18RowColumn2);
setTableRowCheckBox(table18Row, table18RowColumn3);
setTableRowCheckBox(table18Row, table18RowColumn4);
setTableRowCheckBox(table18Row, table18RowColumn5);
setTableRowCheckBox(table18Row, table18RowColumn6);
table18RowColumn7.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
setTableRowEditView(table18Row, table18RowColumn7, tlparams18);
setTableRowTextView(table18Row, table18RowColumn8, tlparams18);
table18RowColumn7.setInputType(InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_NORMAL);
setTableRowEditView(table18Row, table18RowColumn9, tlparams18);
table18.addView(table18Row);
}
public void addRow18() {
createRowTable18(table18, table18NumOfRows, tlparams);
table18NumOfRows++;
}
public void removeRow18() {
if (table18NumOfRows > 0) {
table18.removeViewAt(table18NumOfRows);
table18NumOfRows--;
} else {
Toast.makeText(getContext(), "Δεν υπάρχουν γραμμές στον πίνακα", Toast.LENGTH_SHORT).show();
}
}
When I complete inserting data they are too many to save and recall them one by one everytime i rotate the phone. Any ideas?
When your orientation changes, Android destroys your current activity and creates a new activity again, so you must manage your state.
You can use onSaveInstanceState to save the state and then get the same it in onCreate, for example:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("MyObject", myObject);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
final MyDataType myData = savedInstanceState.getString("MyObject"));
// fill your layout...
}
}
You can manage the state of your fragments too, please check here. Fragments can be "retain his instance" please read this or this.
Here another great post.
In some projects where I worked, when the application was not prepared for screen rotation, we had to disable this configuration.
I hope this will be useful for you.
Android will automatically save and restore your tables and the associated text views, but you need to do a couple of things.
Make sure each view you want to save has an id. Only views will an id will be saved. See generateViewId and setId.
Note: In order for the Android system to restore the state of the views in your activity, each view must have a unique ID, supplied by the android:id attribute.
Even with an id set, Android will not by default save the value of a TextView presumably because TextViews tend to be static. You can force a save/restore of a TextView by using freezesText.
android:freezesText
If set, the text view will include its current complete text inside of its frozen icicle in addition to meta-data such as the current cursor position. By default this is disabled; it can be useful when the contents of a text view is not stored in a persistent place such as a content provider. For EditText it is always enabled, regardless of the value of the attribute.
There may be some odds and ends to tend to, but that should be the bulk of the changes needed.

RecycleView Select multiples

How I can select multiples rows in a recycleview correctly ?
I see this example : https://github.com/kiddBubu/RecyclerViewDemo but is so bat because when move up or down screen value disappear or change or assing position to other row, so bad.
I try show more content of the row.
Example :
Row 1 (uncollapsed)
Row 2 (uncollapsed) - > click - > (collapsed) add + padding or margin
Row 3 (uncollapsed)
.
.
Row x (uncollapsed)
But when I try move list up or down the value selected is randomly and others views change automatically, I don't know why, ListView, RecycleView are equals...
I know how do with listviews normals with "tags" (but also is bad)
I don't want "expandablelistview".
Any help ?
Update
I want this efect : http://i.stack.imgur.com/fuFFl.png
I have not found anything, not a complete example in google
Code :
I tried 4 or 5 methods, this is the first
boolean [] check; check = new Boolean[Fragment2.recyclerView.size()];
Arrays.fill(array, Boolean.FALSE);
.
.
.
public class ViewHolder extends RecyclerView.ViewHolder {
// l1
public TextView text1,text2,text3,text4;
LinearLayout imgLayout,l1;
// l2
public TextView text5,text6,text7;
LinearLayout l2;
public ViewHolder(final View itemView) {
super(itemView);
l1 = (LinearLayout) itemView.findViewById(R.id.l1);
imgLayout = (LinearLayout) itemView.findViewById(R.id.imgLayout);
text1 = (TextView) itemView.findViewById(R.id.text1);
text2 = (TextView) itemView.findViewById(R.id.text2);
text3 = (TextView) itemView.findViewById(R.id.text3);
text4 = (TextView) itemView.findViewById(R.id.text4);
l2 = (LinearLayout) itemView.findViewById(R.id.l2);
text5 = (TextView) itemView.findViewById(R.id.text5);
text6 = (TextView) itemView.findViewById(R.id.text6);
text7 = (TextView) itemView.findViewById(R.id.text7);
int itemPosition = Fragment2.recyclerView.getChildPosition(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!check[itemPosition]) {
l1.setVisibility(View.VISIBLE);
l1.setEnabled(true);
check[itemPosition] = true;
l2.setVisibility(View.GONE);
l2.setEnabled(false);
} else {
l1.setVisibility(View.GONE);
l1.setEnabled(false);
check[itemPosition] = false;
l2.setVisibility(View.VISIBLE);
l2.setEnabled(true);
}
}
The RecyclerView connects a data structure like an ArrayList via Adapter. Upon an update of the ArrayList, your RecyclerView's View objects should change state.
If I were to update multiple rows in a RecyclerView, I'd update the value inside the ArrayList and call mAdapter.notifyDataSetChanged(). So when I scroll, the element has been updated properly.

Android dynamically drawing more than 1000 text view is causing full application to not responding

This is my function which will fetch some 1300 record from SQLite database and draw a series of text view inside the table layout. But when this function starts executing full application is not responding for some time. Table layout is again inside a Scroll View.
Basically I want it to load in back ground.so that remaining application is still responsive
public void LoadAlarmNotifications() {
int SerNo = 0 ;
TextView SerNoTxtVw;
TextView AlarmTxtVw;
TextView TimeOccuredTxtVw;
TextView UploadTxtTxtVw;
Notificationtablelayout.setGravity(Gravity.CENTER);
pastEvent_tbleList = oDatabaseHandler.FetchPastEventDetails(sDiagnosisID);
if(pastEvent_tbleList != null)
{
for(Pastevents_tble PEvents_tble: pastEvent_tbleList)
{
final TableRow row = new TableRow(this.getApplicationContext());
nAlarmType = PEvents_tble.GetAlarmID();
nRowID = PEvents_tble.GetEventNo();
SerNo = PEvents_tble.GetEventNo();
SetAlarmType(nAlarmType); // Set Alarm
tAlarmTime = PEvents_tble.GetStrtTime();
sUploadStatus = PEvents_tble.GetUploadStatus();
row.setId(nRowID);
SerNoTxtVw =new TextView(this.getApplicationContext());
AlarmTxtVw =new TextView(this.getApplicationContext());
TimeOccuredTxtVw=new TextView(this.getApplicationContext());
UploadTxtTxtVw =new TextView(this.getApplicationContext());
SerNoTxtVw.setText(Integer.toString(SerNo));
SerNoTxtVw.setWidth(80);
SerNoTxtVw.setHeight(40);
SerNoTxtVw.setGravity(Gravity.CENTER);
SerNoTxtVw.setPadding(2, 2,2,2);
SerNoTxtVw.setTextColor(Color.parseColor("#FFAADDFF"));
row.addView(SerNoTxtVw);
AlarmTxtVw.setText(sAlarmName);
AlarmTxtVw.setWidth(100);
AlarmTxtVw.setHeight(40);
AlarmTxtVw.setGravity(Gravity.LEFT);
AlarmTxtVw.setPadding(2,2,2,2);
// AlarmTxtVw.setBackgroundColor(Color.LTGRAY);
row.addView(AlarmTxtVw);
TimeOccuredTxtVw.setText(tAlarmTime);
TimeOccuredTxtVw.setWidth(140);
TimeOccuredTxtVw.setHeight(40);
TimeOccuredTxtVw.setGravity(Gravity.CENTER);
TimeOccuredTxtVw.setPadding(2,2,2,2);
// TimeOccuredTxtVw.setBackgroundColor(Color.LTGRAY);
row.addView(TimeOccuredTxtVw);
UploadTxtTxtVw.setText(sUploadStatus);
if(sUploadStatus.equals("Y")){
UploadTxtTxtVw.setText("✔");
UploadTxtTxtVw.setTextColor(Color.parseColor("#FF00FF00"));
}
else if(sUploadStatus.equals("N")){
UploadTxtTxtVw.setText("X");
UploadTxtTxtVw.setTextColor(Color.parseColor("#FFFF0000"));
}else
{
UploadTxtTxtVw.setText("✔");
UploadTxtTxtVw.setTextColor(Color.parseColor("#FFAADDFF"));
}
UploadTxtTxtVw.setWidth(100);
UploadTxtTxtVw.setHeight(40);
UploadTxtTxtVw.setGravity(Gravity.CENTER);
UploadTxtTxtVw.setPadding(2,2,2,2);
// UploadTxtTxtVw.setBackgroundColor(Color.LTGRAY);
row.addView(UploadTxtTxtVw);
Notificationtablelayout.addView(row);
nProgressCounter++;
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View SelectedRowVw) {
if(!bSwitchPopOpen)
{
}
});
}
LoadingTxtView.setVisibility(View.GONE);
bEpisodeLoad = true;
} else
{
bEpisodeLoad = true;
LoadingTxtView.setText("No Snapshot available...");
}
}
pastEvent_tbleList size is 1335. Any idea how to optimize this. Instead of text view is there any other light control?
You should use the Loader pattern to do this so that you only load content that the user will actually see, and you should also reuse the text views on the screen. This is what ListView / CursorLoader were created to solve, so you really ought to reuse these components if at all possible.
You should use listview, because it loads visible area so application will not stop doing calculations and you can scroll up and down and see your texviews

Find out which view is touching in multiple layouts in linearlayout in android?

I have to create layout dynamically using Java.
I have created 9 linear layouts dynamically as below:
for (int i=0;i<10;i++)
{
Element e = (Element) nl.item(i);
cpName = parser.getValue(e,"coverpage");
System.out.println("coverpage name :" + cpName);
LinearLayout lbottomLayoutu1=new LinearLayout(getApplicationContext());
lbottomLayoutu1.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams layoutParams1u1= new LinearLayout.LayoutParams(width,height/4);
layoutParams1u1.weight=1.0f;
lbottomLayoutu1.setLayoutParams(layoutParams1u1);
lbottomLayoutu1.setBackgroundColor(Color.RED);
lbottomLayoutu1.setBackgroundResource(R.drawable.image);
linearLayout.addView(lbottomLayoutu1);
ImageView iv1=new ImageView(getApplicationContext());
LinearLayout.LayoutParams layoutParams= new LinearLayout.LayoutParams(width/4,height/4);
iv1.setLayoutParams(layoutParams);
iv1.setImageResource(R.drawable.coverpage3);
lbottomLayoutu1.addView(iv1);
lbottomLayoutu1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Calling coverpage");
String Url = WebUrl+cpName;
System.out.println("web Url: " + Url);
Intent in = new Intent(getApplicationContext(),CurlActivity.class);
Bundle bundle = new Bundle();
bundle.putString("Image Url",Url);
in.putExtras(bundle);
startActivity(in);
}
});
setContentView(linearLayout);
}
I put a touch event for every layout. But if I touch any layout how can I know which layout is touching?
I think it's better to use custom listView (like here http://www.codeproject.com/Articles/507651/Customized-Android-ListView-with-Image-and-Text)
You need to set the ids of each layout as
obj.setId(i)
so that in your touch event you can identify it with
int id=obj.getId()
and work accordingly!
If you implement the OnClickListener for the view, like you did...
lbottomLayoutu1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// ...
}
}
... the parameter View v tells you which layout has been touched. You can then cast it to your expected layout, like:
LinearLayout clickedLayout = (LinearLayout) v;
This will be the layout that has been clicked.
If you want, however, know the index that you used in the loop, you have to overwrite your LinearLayout and give it a member that holds the index. Then you can cast it to your custom LinearLayout class and get the index. (If you need more help on this, let me know in the comments).

dynamically name textview after inflating android

I m inflating 4 linear layouts multiple times in a scroll view. Each layout has a title in its header. The code snippet is given below.
for(int j=0;j<qType.length;j++)
{
LinearLayout.LayoutParams siz = new LinearLayout.LayoutParams(width, height);;
if(qType[j]==0)
{
view1 = getLayoutInflater().inflate(R.layout.layout1, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/3);
}
else if(qType[j]==1)
{
view1 = getLayoutInflater().inflate(R.layout.layout3, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/3);
}
else if(qType[j]==2)
{
view1 = getLayoutInflater().inflate(R.layout.layout4, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/3);
}
else if(qType[j]==3)
{
view1 = getLayoutInflater().inflate(R.layout.layout5, main_layout,false);
siz = new LinearLayout.LayoutParams(width, height/2);
}
siz.topMargin = 25;
main_layout.addView(view1, siz);
}
scroll_layout.addView(main_layout);
scroll_layout.setBackgroundResource(R.drawable.options_background);
setContentView(scroll_layout);
Now there is textview in each layout and i want to change the text of it. If i access them by findviewbyid and give settext, only the first instance is being changed, i want to change the textview on all occasions.
for(int k=0;k<NumberQuestions.length;k++)
{
TextView number_title = (TextView)main_layout.findViewById(R.id.number_title);
TextView mcq_title = (TextView)main_layout.findViewById(R.id.mcq_title);
TextView comment_title = (TextView)main_layout.findViewById(R.id.comment_title);
TextView cam_title = (TextView)main_layout.findViewById(R.id.cam_title);
if(qType[k]==0)
{
number_title.setTypeface(myriadpro_bold);
number_title.setText(NumberQuestions[k]);
}
if(qType[k]==1)
{
comment_title.setTypeface(myriadpro_bold);
comment_title.setText(NumberQuestions[k]);
}
else if(qType[k]==2)
{
mcq_title.setTypeface(myriadpro_bold);
mcq_title.setText(NumberQuestions[k]);
}
else if(qType[k]==3)
{
cam_title.setTypeface(myriadpro_bold);
cam_title.setText(NumberQuestions[k]);
}
Please help.
probably the TextView android: id in all layouts are the same, thus explaining the behavior of the method findViewById always returns the first occurrence
Disclaimer: I feel like you are trying to work against the Android Framework, as opposed to working with it. My suggestion is a tad bit of an overhaul, but I do feel like it is the correct way to go about things.
I would recommend using a ListView, since you are repeating the same format many times. A listview will typically have a container of objects of objects, and an adapter responsible for mapping an object to a particular row within the listview. When you change the data in the underlying container, you will call the callback notifyDataSetChanged() for your adapter to notify it that you changed the underlying data and alert it to update your listview.
2 great resources/tutorials from the android developer site:
ListView: http://developer.android.com/guide/topics/ui/layout/listview.html
Adapters: http://developer.android.com/guide/topics/ui/declaring-layout.html#AdapterViews
If i am right main_layout is a name view in your xml file.So You should use like this
view1 = getLayoutInflater().inflate(R.layout.layout1, main_layout,false);
TextView tv = (TextView)main_layout.findViewById(R.id.tv1);
where tv is texview in layout1.xml

Categories

Resources