How to add several relativeLayout with 2 views inside programmatically? - android

I took a look on stackoverflow but I can't find the answer.
I would like to add several rows (RelativeLayout) into the parent (LinearLayout). The RelativeLayout would be composed of 2 views, a ImageView on the left and a TextView on its right, both into the same row, for each item:
LinearLayout userLayout = (LinearLayout) view.findViewById(R.id.participant_user);
RelativeLayout rL = new RelativeLayout(context);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_LEFT)
for (Participant participant : participants) {
TextView textView = setTextView(context, participant.getName());
rL.addView(textView, params);
ImageView imageView = new ImageView(context);
imageView.setImageResource(R.drawable.bz_ic_default_user);
rL.addView(imageView, params);
userLayout.addView(rL);
}
It doesn't work, the first element is only displayed or the app crashed...
Thank you for your help !

You should probably use a ListAdapater or RecylerView here
https://developer.android.com/training/material/lists-cards.html
http://developer.android.com/reference/android/widget/ListAdapter.html
You are trying to create a list of items with an unknown #. The way you are doing it, performance will be bad and you are inflating views into a linearlayout and not reusing views.

You are creating a RelativeLayout, filling it n times (one per participant) and trying to add it n times. At the very least you should create n different RelativeLayouts.
Anyway, as a rule of thumb, every time you have to crete a list ask yourself: will it contain 10 elements or 1000. If it's 10, then you can follow your approach (but I would advise to create every row inflating an xml instead od instantiating the views), if it's 1000 use a ListView (or some kind of RecyclerView), much simpler and efficient.

As the previous answers stated, using a ListAdapter would probably make things work. Here is an example.
If you really want to do it your way, you should share your error log (LogCat output).

As everyone here said, It's better to use the RecyclerView or the ListView. But if you want do it in this way for another reason, then I think that the best that you can do is:
LinearLayout mainLayout = new LinearLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
mainLayout.setLayoutParams(params);
LayoutInflater inflater = LayoutInflater.from(this);
for (Participant participant : participants) {
View rowView = inflater.inflate(R.layout.row, mainLayout, false);
((TextView) rowView.findViewById(R.id.name)).setText(participant.name);
((ImageView) rowView.findViewById(R.id.photo)).setImageResource(R.drawable.photo); //BTW You can set it in the xml and avoid this
mainLayout.addView(rowView);
}
setContentView(mainLayout);

Related

Place 2+ Textfields side-by-side in a LinearLayout (horizontal) programmatically

i know, there are a lot of questions like this. I read a lot on stackoverflow and google about this topic, but nothing help me :(
Ok, here is the problem. I have a small app. In this app i have a fragment. The layout.xml for this fragment includes a placeholder linearlayout like the following
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/placeholderLinLayout">
</LinearLayout>
The fragment has a button. If u click on it a DialogFragmentPopup opens and u can enter some data-stuff. After you enter the data you can click on another button on this dialog and the data will be transfere to the main-fragment. Here i call a method which should generate programmatically a layout to present the data. I use the following code
myRoot = (LinearLayout) view.findViewById(R.id.placeholderLinLayout);
innerLayout = new LinearLayout(view.getContext());
innerLayout.setOrientation(LinearLayout.VERTICAL);
innerLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
LinearLayout productHeaderLayout = new LinearLayout(getContext());
productHeaderLayout.setOrientation(LinearLayout.HORIZONTAL);
productHeaderLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
TextView product_header = new TextView(getContext());
product_header.setText("Produkt");
product_header.setLayoutParams(layoutParams);
TextView amount_header = new TextView(getContext());
amount_header.setText("Menge");
amount_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
amount_header.setLayoutParams(layoutParams);
TextView packaging_header = new TextView(getContext());
packaging_header.setText("Verpackung");
packaging_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
packaging_header.setLayoutParams(layoutParams);
TextView price_header = new TextView(getContext());
price_header.setText("Preis");
price_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
price_header.setLayoutParams(layoutParams);
TextView payment_header = new TextView(getContext());
payment_header.setText("Zahlart");
payment_header.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
payment_header.setLayoutParams(layoutParams);
productHeaderLayout.addView(product_header);
productHeaderLayout.addView(amount_header);
productHeaderLayout.addView(packaging_header);
productHeaderLayout.addView(price_header);
productHeaderLayout.addView(payment_header);
innerLayout.addView(productHeaderLayout);
The problem is, that the first textview push all other textviews out of the visible space, see the screenshot
What i want to do is, that these 5 textviews spread out automatically to the existing width. I googled a lot and the code i post here is the result of which i found many times on the internet.
So i hope someone can help find out the problem in my code :)
Greetings
Set all your TextView layout paramters to this:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f);
And remove .setWidth(ViewGroup.LayoutParams.MATCH_PARENT); from all the TextViews.
This will guarantee that all the views will have same weight set to them, and that weight gives all the views in LinearLayout same Width (or Height if orientation is set to vertical).
The issue is that your setting the TextView to MATCH_PARENT in its width. So one TextView takes the whole screen and the other starts just out of it. To solve this set the layoutparam width to WRAP_CONTENT.
Better yet, if you want to spread it, you can use the LinearLayout's weight property so they take as much space as they can:
textview.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f));
The third parameter 1f is the weight. A weight of one means it'll take all the available space without intruding on the other children, hence they will all spread evenly.
If you want to have your TextViews side by side, you must set the orientation of the LinearLayout to horizontal instead of vertical

How do I access a textview or progressbar in relative layout programatically when multiple?

I am creating multiple relative layouts in an activity, programmatically. Each is identical and has a textview as well as a ProgressBar spinner.
I want to programmatically change them when needed but not sure how to access the appropriate one. I believe I need to add a unique SetId() to each item (or maybe the relativelayout itself) but not sure the best way to do so.
I also am not sure if I use findViewById to access the views once created to make the changes (SetText, SetVisibility, etc).
Here is the code
RelativeLayout.LayoutParams tvpName = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
tvpName.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
RelativeLayout.LayoutParams pbpSpinner = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
pbpSpinner.addRule(RelativeLayout.CENTER_IN_PARENT);
pbpSpinner.addRule(RelativeLayout.ALIGN_PARENT_TOP);
for (int i = 0; i < 5; i++) {
RelativeLayout acctrl = new RelativeLayout(this);
TextView tvName = new TextView(this);
ProgressBar pbSpinner = new ProgressBar(this);
pbSpinner.setVisibility(View.GONE);
// Add items to Account Interal Layout
acctrl.addView(tvName, tvpName);
acctrl.addView(pbSpinner, pbpSpinner);
}
Any recommendations / suggestions?
When you create a View programatically, it's a good practice to setId(). Additionally, you can go ahead and setTag() also. By setting a Tag, you can know what each RelativeLayout or any other view. This way you can get a hold of the view that you are looking for.
If you are not going to access or modify the RelativeLayout then you need not set ID for it, but setting an id for it makes this easier, so that you can just send the ID of the RelativeLayout as a parameter to a method and it will perform all operations on the Views it holds, since you said all RelativeLayouts are identical.
If you are using setId(), then you can use the findViewById() to get the view.
If you are using setTag(), the you can refer this on how to use it to get the view: https://stackoverflow.com/a/5291891/4747587

Adding a custom view multiple times in a layout

I have a custom XML file. I want to repeat this in a layout (say Relative) n number of times, dynamically (obviously).
I have seen many posts, but none helped. I am not looking for a ListView or Adapters or so. It's as simple as - A RelativeLayout. Inside it, adding the custom XML one above another. Any number of times.
With a static LinearLayout (Vertical orientation), adding the view dynamically results in rendering it once, not one below another. Don't know why. Although a TextView or so do repeat one below the other in a loop inside a LinearLayout (Vertical).
Then I dynamically created the layout (Relative), and inflated the custom XML. Displayed one. When I tried for another below the first it told me to remove child's parent first (Exception). If I do that and add again, its as good as removing the first rendered view and adding it again.
So how can I get multiple views in same layout?
A rough presentation of what I've attempted:
mainLayout = (RelativeLayout)findViewById(R.id.mainlay); //Mainlayout containing some views already
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW,R.id.sideLayout); //sideLayout is an existing LinearLayout within the main layout.
View child = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
RelativeLayout r1 = new RelativeLayout(this);
r1.setLayoutParams(params);
r1.addView(child);
mainLayout.addView(r1);
mainLayout.setLayoutParams(params);
mainLayout.addView( child);
/* r2 = new RelativeLayout(this);
r2.setLayoutParams(params);
r2.addView(contentLayout); [Gives exception] */
This is how it worked out for me...
Before that, the issue with android is:
If you add dynamic views inside a LinearLayout (Horizontal), they will appear horizontally with new created instances, added to the view.
However, shockingly, it's not the same in case of LinearLayout (Vertical orientation). Hence the whole mess.
Solution:
The RelativeLayout layout file was binded with the variable, somewhat like this:
customLay = (RelativeLayout) mainLay.findViewById(R.id.dynamicCustomLayout);
Then, a Dynamic RelativeLayout was created within which the former variable is added/wrapped.
customLayout = new RelativeLayout(this);
customLayout.addView(customLay);
Every layout is assigned an id:
customLayout.setId(i);
And then a loop is run (2 if conditions for i=0 and i>0)
for i>0 (indicates the 2nd dynamic layout, to be added below the first), LayoutParameter is created:
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
And then for i>0, using the ids of dynamic views, they are added one below the other:
//Following code below used id to place these views below each other to attain list type arrangement of views//
// i==0 for first view on top//
if (i == 0) {
params.addRule(RelativeLayout.BELOW, R.id.sideLayout);
customLayout.setLayoutParams(params);
}
// i>0 for views that will follow the first top//
else {
params.addRule(RelativeLayout.BELOW, i - 1);
customLayout.setLayoutParams(params);
}
Then added to main root layout, where all these views or cards need to be displayed:
includeLayout.addView(customLayout);
Ofcourse, the code is not just this. I have written the essential points that helped me achieve the target and that may help others in future.
So the main essence was ---
using a Dynamic RelativeLayout, to
bind the static RelativeLayout, and
assigning ids to the Dynamic RelativeLayout wrappers, and
on basis of ids use RelativeLayoutParameters to place the following
ids below the previous ones.
You have to instanciate every child by itself
View child = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
r1.addView(child);
View child2 = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
r1.addView(child2);
//ok, i do a analog thing in obne of my apps. here is the code:
public class FlxForm extends LinearLayout {
public FlxForm(Context context) {
super(context);
inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.flxform, this);
this.setPadding(0, 0, 0, 0);
container = (LinearLayout) this.findViewById(R.id.flxform);
this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
//here is my funtion to calculate the items i want to add, its a little bit too complicated, but in the end it works like:
for(int i=0;i<10;i++){
View x = inflater.inflate(R.layout.dynamiccustomlayout,null);
container.addview(x);
}
}
}
XML for the Form
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/flxform"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:background="#android:color/transparent"
android:orientation="vertical" >
</LinearLayout>
Then you can instantiate a "Form" Objekt and add it into a ScrollView
For doing this You would have to nest your RelativeLayout inside a ScrollView and Manage all the Scrolling, items adding, memory management, etc manually.
So the simple solution for adding n Number of Custom Views is to use a RecyclerView, ListView, GridView, etc with a neat CustomAdapter and Your Custom View.
Here is a nice example of using RecyclerView with custom Adapter :
http://code.tutsplus.com/tutorials/getting-started-with-recyclerview-and-cardview-on-android--cms-23465
I hope this Helps.

How to display dynamic view in android

I have a title as processed with three textview and an images
and then another title with same three textview.
How to create this in dynamic layout? Since I need this to generate in dynamic in android.
I am new to this. please give me an idea.
Thanks
LinearLayout mContainer;
public void onCreate(Bundle) {
setContentView(R.layout.container);
mContainer = (LinearLayout) findViewByid(R.id.coainter);
View view = layoutInflater.inflate(R.id.inflaterView);
view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
mContainer.addView(view,1);
Info -
create the XML you need to add the Views inside.
create the view you need to Dyanmiclly add (inflate or create it)
set the LayoutParams according to the Conatiner.
add the View to the Conatiner the number 1 is the location inside the Container.
of crouse this is an Example i just followed your image.
you can use mConatiner.addView(view) this will insert them according to the Container Choice
Hope it Helps.

Create a RelativeLayout dynamically and positioning views inside

I would like to create a method which returns a RelativeLayout created dynamically. To be clear, let's use this simplified example:
private RelativeLayout createLayout() {
RelativeLayout layout = new RelativeLayout(activity);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
layout.setLayoutParams(params);
TextView tv1 = new TextView(activity);
tv1.setText("Text 1");
TextView tv2 = new TextView(activity);
tv2.setText("Text 2");
TextView tv3 = new TextView(activity);
tv3.setText("Text 3");
layout.addView(tv1);
layout.addView(tv2);
layout.addView(tv3);
return layout;
}
Now I want to position these TextViews relatively to each other. For that I have the idea to use a LayoutParams with the addRule method.
But this method requires an ID, e.g. addRule(RelativeLayout.BELOW, tv2Id). It means that I have to set an ID for each TextViews.
My problem is that the createLayout method will be called several times, so the question is:
Do I have to set different IDs for the TextViews each time the method is called in order to avoid conflicts ? If so, how can I do that ?
Most generally, Is there a better solution for doing it ?
EDIT
The idea behind this is to have a kind of ListView, where each item contains a Map (that can be shown or hidden).
Problem: the Map can't be scroll if it is inside a ListView (at least I did not manage to do that).
For that, I have decided to use a ScrollView and a LinearLayout to copy the behaviour of a ListView. This way the Map can be scrolled correctly and now, all I have to do is to create the items dynamically
ID's don't have to be unique. As you can see from this extract
setId (int id)
Sets the identifier for this view. The identifier does not have to be unique in this view's hierarchy. The identifier should be a positive number.
But like you said, if you want to avoid conflict then you have to find a way to generate unique identifiers for each view.
Frankly, IMO I don't think it matters much the value of the ID. You can use 10, 20, 30. Just make sure you can have access to them anytime you need it, possible using a static final variable.
You asked if there is a better solution, yes there is. The most preferred way is to inflate an xml layout.

Categories

Resources