How to add multiple TextViews programmatically to a RelativeLayout - android

How does one programmatically, via one button click at a time, add multiple TextViews to an existing RelativeLayout without the TextViews overlapping onto one another.
I am trying something like this -
The following code exists inside the onCreate() method:
TextView textViewToSeeFirst = (TextView) findViewById(R.id.textView1);
RelativeLayout rLayout1 = (RelativeLayout) findViewById(R.id.relativeLayout1);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams
(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TextView newTextView = new TextView(TheActivityYouAreUsingActivity.this);
newTextView.setText("text you want");
rLayout1.addView(newTextView, lparams);
}
The TextViews are being added to the RelativeLayout, but they are all on top of one another, how does one fix this?

The goal is to programmatically, via one button click at a time, add multiple TextViews to an existing RelativeLayout, and without the TextViews overlapping onto one another.
Here is what I finally came to, this works but I am unsure if it is the best way to go (or even a good way).
The following code exists inside the onCreate() method:
// Creates a variable to keep track of the amount of TextViews, the
// first TextView, an array, and then stores the TextView in the Array
int numberOfTextViews = 1;
TextView[] textViewArray = new TextView[20];
TextView textViewToSeeFirst = (TextView) findViewById(R.id.textView1);
textViewArray[numberOfTextViews - 1] = textViewToSeeFirst;
// Also need to reference the RelativeLayout we are putting TextViews in
RelativeLayout rLayout1 = (RelativeLayout) findViewById(R.id.relativeLayout1);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams
(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lparams.addRule(RelativeLayout.RIGHT_OF, textViewArray[numberOfTextViews - 1].getId());
lparams.addRule(RelativeLayout.ALIGN_TOP, textViewArray[numberOfTextViews - 1].getId());
TextView newTextView = new TextView(TheActivityYouAreUsingActivity.this);
newTextView.setText("text you want");
newTextView.setId(numberOfTextViews);
textViewArray[numberOfTextViews] = newTextView;
rLayout1.addView(textViewArray[numberOfTextViews], lparams);
numberOfTextViews = numberOfTextViews + 1;
}
Some things to keep in mind:
the parameters for RelativeLayout.LayoutParams are important, see developer material on these parameters. WRAP_CONTENT was chosen for my needs because it causes the TextViews to only take up the size of their text, rather than their entire parent... Overlapping was occurring before I changed this.
the id of each new TextView must be set if it is to be referenced later on for new layout parameters
the id must be a positive number, and zero is not positive
the RelativeLayout is holding the TextViews and handling them, the textViewArray is just so the ids of each TextView can be stored and referenced if need be
The corresponding XML has this going for it inside the main parent:
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight=".2" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/die_one" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/name_a_button" />
</RelativeLayout>
Notice that the first RelativeLayout, and the TextView both have an id, this is so the addRule() method in the activity can reference them.
This code allows a user to click a button and add new TextViews to a RelativeLayout without them overlapping.

Why dont you add all your text views in your xml file (as much as you want) before running you app. Just set the visibilities to the textviews which you dont want to show initially to "GONE" and then in button click listener just keep changing the visibility of textview to "View.Visible" .
If you want a new textview to appear each time you press a button then set a counter to a button and each time a counter increments you change the desire textview's visibility to View.Visible. If you understood what i am saying you will be able to make the code on your own.

You can use Linear Layout with orientation as vertical instead of Relative Layout. It will align all the textviews vertically one below the other.
I dont consider adding large number of textviews to the xml file a valid solution, as the number of times the user will click a button is unknown.

Related

How to add text in dynamically added EditTexts

I want to add text to my dynamically added EditTexts.
As for now its just adding a layout with two EditText in, its getting added to a LinearLayout on button click.
How do I set the text of these Editexts? Because now I can add as many as I like and every EditText has the same id as the have in the layout file.
My mainactivity.java with the inflation upon button clicklooks like this:
final LinearLayout mView = (LinearLayout) getLayoutInflater().inflate(R.layout.more_rest_main, null);
mView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
restLayout.addView(mView);
And here is my layout for more_rest_main.xml
<EditText
android:layout_width="150dp"
android:layout_height="wrap_content"
android:id="#+id/added_rest_from"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:hint="#string/time_from"
android:textSize="15dp"
android:focusable="false"/>
<EditText
android:layout_width="150dp"
android:layout_height="wrap_content"
android:id="#+id/added_rest_to"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:hint="#string/time_to"
android:textSize="15dp"
android:focusable="false" />
The thing to understand here is that you can look for a child view in any ViewGroup (LinearLayout is a ViewGroup).
You're probably familiar with retrieving a View in an Activity onCreate, where after calling setContentView, you have access to any View with findViewById.
So after inflating your ViewGroup, you can use the same approach you would use in an Activity onCreate, but you need to look for your ViewGroup's child views:
final LinearLayout mView = (LinearLayout) getLayoutInflater().inflate(R.layout.more_rest_main, null);
EditText txtAddedRestFrom = (EditText)mView.findViewById(R.id.added_rest_from);
restLayout.addView(mView);
Once you have your reference you can invoke any method on your EditText, such as setText.
You can create an EditText dynamically like following:
EditText editText = new EditText(myContext);
editText.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
//add the same logic as in the XML file
mView.addView(editText);
You can also set an ID dynamically. If you are using API 17 and above, do the following:
editText.setId(View.generateViewId())
Otherwise you can set a positive Integer of your choice as an ID, instead of using the:
View.generateViewId()
With the code above and since these will be added dynamically, you don't need the XML file as the EditTexts will be created dynamically.
If you want to keep the existing XML file, you can just call the
setTag()
to each one of the inflated EditTexts and set a unique value in the setTag method. That way you can distinguish the EditTexts. And since you can do that, you can add whatever text you need to each one of them.
To reply to your comment, on how to set an OnCLickListener:
editText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// here you can get either the Tag or the ID that
// you've set dynamically. And do whatever you like to do
view.getTag()
view.getId()
}
});

Adding a view dynamically to Layout

I'm having a hard time with Android as a pretty newbie in the platform, and as I learnt, many people too. I don't know how many hours I have lost so far - it's terrifying even to count them.
I want basically to add a new TextView (or any other View) to LinearLayout after clicking the button. Here's this part of the code:
public void btnClick(View view) {
final LinearLayout ll = (LinearLayout) findViewById(R.id.test_story_screen_layout);
//checking if child is being added - it is, this value is increase with every button click
android.util.Log.d("child: ", Integer.toString(ll.getChildCount()));
android.util.Log.d("height: ", Integer.toString(ll.getMeasuredHeight()));
ll.post(new Runnable() {
public void run() {
final TextView tv = new TextView(MainActivity.this);
tv.setText("new one " + (new Random()).nextInt());
tv.setTextColor(Color.YELLOW);
LayoutParams lp = new LayoutParams(200, 500);
tv.setLayoutParams(lp);
tv.setVisibility(View.VISIBLE);
ll.addView(tv, ll.getChildCount());
//checking if the run() is called - it is
ll.setBackgroundColor(Color.GREEN);
}
});
ll.requestLayout(); //invalidate() and postInvalidate() also not working
}
But the newly added View is not visible (but is added as a child to LinearLayout).
After hours of checking what's wrong, I only found out that when I replace this line:
ll.addView(tv, ll.getChildCount());
with this:
ll.addView(tv, ll.getChildCount() - 1);
Then new View is visible, but it replaces the previous one - which is not desired.
I already checked some solutions, like this: Refreshing a LinearLayout after adding a view
They didn't help me with the issue.
UPDATE:
Linear Layout looks just fine with predefined in XML two Views (as in the code below). Here's intersting part of the XML:
<LinearLayout
android:id="#+id/test_story_screen_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:layout_margin="16dp" >
<ImageView
android:id="#+id/imageView1"
android:src="#drawable/example"
android:layout_width="16dp"
android:layout_height="16dp" />
<TextView
android:id="#+id/textView1"
android:text="Hello World!"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Nothing unusual I think. So these two Views (Image and Text) are visible of course. Then any new TextView I add to this LinearLayout dynamically (via the btnClick() as in the code above) is not visible, but it is indeed added to Layout, as the ll.getChildCount() is increased every time when the child view is added (= button clicked).
In order to test this further, I added these two lines at the end of the btnClick() method:
android.util.Log.d("tv.getMeasuredWidth: ", Integer.toString(tv.getMeasuredWidth()));
android.util.Log.d("tv.getMeasuredHeight: ", Integer.toString(tv.getMeasuredHeight()));
I'm guessing the problem is the tv (TextView) rather than ll (LinearLayout), as tv gets width and height both 0.
Issue is you are initializing your linearlayout ll with what defined in your xml every time on button click and due to this your linearlayout is getting renewed. Move
final LinearLayout ll = (LinearLayout) findViewById(R.id.test_story_screen_layout);
in your onCreate if using Activity, onCreateView if using Fragment.
Your layout horizontal by default, When you add new view it set it up out from right border of screen. Just set orientation vertical in layout for you linear layout
The linearLayout orientation is horizontal by default set orientation to vertical.
if you want to add View as last element in Layout you can just do this:
ll.addView(tv);
There were number of things related in this Android issue, some of this were:
ll.post() made sense and appared to be required in my case
UI in Android should be updated in a special, not any, way, and it refers to e.g. Async Tasks
visibility of an item (item should be visible)
proper margins (when a screen e.g. is rotated to landscape, margin appeared to be too big)
Damn it. I find Android to be one of least thought-through platforms I've seen.

dynamically created Buttons overlapping

I have created a layout with a database call where a button will be created for each item inside the database. The buttons are created like I need and I also found out, how to set up the layout_width and layout_height but all buttons are placed in the same position and overlap each other so that only the last created button can be accessed. My code for creating the buttons looks like this:
Button bt = new Button(this);
bt.setText("Button Title");
bt.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
linerLayout.addView(bt);
The activity looks like that, after generating the buttons:
I looked at each method that can be used for the button but didn't find anything to define the position. I just thought about following method:
bt.layout(l, t, r, b);
but don't know exactly how to use it and thought there might be a simpler method to solve this problem. Anybody who knows a workaround?!
CHANGED CODE
I just tryied to set the layout parameters like explained from "Chen doron". I have a relative layout inside my xml file:
<RelativeLayout
android:id="#+id/llActOver"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="2" >
</RelativeLayout>
and formatted the generated buttons like this:
Button bt = new Button(context);
bt.setText(c.getString(iDef));
fontClass.setFont(bt);
//RelativeLayout placeholder = new RelativeLayout(context);
RelativeLayout.LayoutParams layoutParam =
new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
if(rowCount < 1){
layoutParam.addRule(RelativeLayout.ALIGN_PARENT_TOP);
rowCount++;
}else{
layoutParam.addRule(RelativeLayout.ALIGN_PARENT_TOP, lastButtonId);
}
lastButtonId = bt.getId();
//placeholder.addView(bt, layoutParam);
linearLayout.addView(bt, layoutParam);
I save the buttons id at the end of the loop so that the last buttons id can be accessed in the next round.
I also tryied to create a new relativ layout for each new button like the commented part of the code shows but even without the new layout nothing happens and i still just have all buttons overlapped.
I finally solved the problem, but just by trying each possible combination of layout types.
I found out, i have to define a LinearLayout inside the XML file and the attribute android:orientation="vertical" is affordable. all the other parameters that have been set before were unimportant.
So now i have a LinearLayout inside a ScrollView in my xml file:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="2" >
<LinearLayout
android:id="#+id/llActOver"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
and inside the java database i have following code to create a button for each row in the db, setting its Text and Font and add it to the loaded layout:
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
Button bt = new Button(context);
bt.setText(c.getString(iDef));
fontClass.setFont(bt);
linearLayout.addView(bt);
}
and here a screenshot of the result:
maybe somebody else who has the same problem won't need to worry as long as me with this description.
You could use a Relative Layout, and have the first Button align to the parent's top.
Then each button aligned to the previous button's bottom.
Use:
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
And then:
params.addRule(RelativeLayout.BELOW,ID-Of-Previous-Button);
Also check out:
http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html

Programmatically Position items in activity. NO XML

I have an Activity that has all the display elements added dynamically. Theres no xml for the acvtivity at all.
The Activity consists of the following controls:
RelativeLayout (Layout object that all the child views sit in)
TextView (Title for the page, sits at top of the RelativeLayout)
ScrollView (Scrollable area that holds all the data controls)
LinearLayout (Layout object to hold the activity buttons)
I want to know how it is possible to define that the ScrollView sits below the Title TextView and above the LinearLayout button holder where the LinearLayout is set to the Activity Page bottom
I have tried using RelativeLayout.LayoutParams to set up rules but cannot seem to understand the way to do it. Any help or links to tutorials would be apreciated
I have included my Code to see if someone can help
// declare the items for display
RelativeLayout baseLayout = new RelativeLayout(this);
// add the customer name and number field.
// NOTE: We will always require this widget regardless of dialog design fields
tvCustomerNameNumber = new TextView(this);
tvCustomerNameNumber.setTextSize(20);
tvCustomerNameNumber.setText("Customer Name & Number");
// build up the linear layout of controls
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
// Scroll view.
// NOTE: We will always need this widget to enable us to scroll the page
// if too many items are added for the display size
ScrollView sv = new ScrollView(this);
sv.addView(ll);
// buttons
LinearLayout buttons = new LinearLayout(this);
buttons.setOrientation(LinearLayout.HORIZONTAL);
// button edit
Button edit = new Button(this);
edit.setId(EDIT_BUTTON_ID);
// button save
Button save = new Button(this);
save.setId(SAVE_BUTTON_ID);
// button cancel
Button cancel = new Button(this);
cancel.setId(CANCEL_BUTTON_ID);
// add each button to the button layout
buttons.addView(edit);
buttons.addView(save);
buttons.addView(cancel);
// Scroll view Layout parameters
RelativeLayout.LayoutParams scrollParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
scrollParams.addRule(RelativeLayout.BELOW, tvCustomerNameNumber.getId());
scrollParams.addRule(RelativeLayout.ABOVE, buttons.getId());
// buttons Layout parameters
RelativeLayout.LayoutParams buttonParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
buttonParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
buttonParams.addRule(RelativeLayout.BELOW, sv.getId());
// add the customer name number field to the base layout
baseLayout.addView(tvCustomerNameNumber);
// add the scroll view to the base layout
baseLayout.addView(sv); //, scrollParams);
// add the buttons to the base layout
baseLayout.addView(buttons, buttonParams);
// set the content view
this.setContentView(baseLayout);
Deva has already answered your question, but it sounds to me like you could define an xml layout as you have described above, inflate it and populate it dynamically programmatically... perhaps the layout would initially contain an empty LinearLayout, and/or no text set for the TextView, maybe even set everything to android:visibility="gone" and show it when you have added/updated all your views?
See the links below which might help you achieve this :
Programmatically adding items to a relative layout
How to programmatically add multiple LinearLayouts into one view and then add to ViewFlipper?

Programmatically change a xml-created view

Is there a way to get the parameters from a XML view, modify some stuff on it and then use it as content view ?
Let's say I have a normal LinearLayout and I want to make that work:
LinearLayout layout = (LinearLayout) findViewById(R.layout.main);
setContentView(layout);
Instead of :
setContentView(R.layout.main);
Yes.
To be more specific, we need more specific info from you.
Edit
You can, for example, do the following.
Say you have in your xml specification a TextView:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/mytv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:textStyle="bold"/>
</RelativeLayout>
Now you want to center horizontal the TextView programmatically:
setContentView(R.id.main);
TextView myTV = (TextView) findViewById(R.id.mytv);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) myTV.getLayoutParams();
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
myTV.setLayoutParams(lp);
You just set the contentview at the start, and don't need to set it again when you change the variables.
You can do anyything you want to the layouts even after setContentView. When you do operations like add items to a layout or set a background, the views in the screen are redrawn.
onCreate method is where you can modify layouts as it it about to begin drawing on to a screen.

Categories

Resources