Problems Adding TextView Programmatically Without Erasing Views in XML - Android - android

I'm trying to add a TextView programmatically, and it has proved immensely difficult. I have found code that works here (added to onCreate):
LinearLayout thisLayout = new LinearLayout(this);
setContentView(thisLayout);
TextView dynamicTextView = new TextView(this);
dynamicTextView.setText("Dynamically Added TextView");
thisLayout.addView(dynamicTextView);
The problem is that this erases all of the views I had created in the XML. There is a popular question with a highly upvoted answer HERE. Based on that, I created this:
LinearLayout myLayout = findViewById(R.layout.activity_main);
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
tv.setText("Trying Again");
myLayout.addView(tv);
But there is an error on this line:
LinearLayout myLayout = findViewById(R.layout.activity_main);
I try to cast it like this, which silences the error, but immediately crashes:
LinearLayout myLayout = (LinearLayout) findViewById(R.layout.activity_main);
I'm curious what I'm doing incorrectly. I realize that there are many similar questions out there, but none of them seem to work and many point to the answer I connected here. The problem I'm having is that the answer just doesn't work at all. Also, I'm in the process of familiarizing myself with the Android environment so if there's anything I'm doing that seems "off", please point it out.
Here's my XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="lowri.morepractice.app.MainActivity">
<EditText android:id="#+id/edit_message"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
android:onClick="sendMessage"/>
</LinearLayout>
For anyone else who comes here, I also had to change the layout params to this:
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));

You can't request the layout by id. It doesn't point to the LinearLayout.
To actually get the LinearLayout you have to add an id to it
<LinearLayout
android:id="#+id/edit_linearlayout"
....
and request that like:
LinearLayout myLayout = (LinearLayout) findViewById(R.id.edit_linearlayout);
To add the the TextView you have to set the LayoutParams like in the question you posted. Doesn't have to be FILL_PARENT of course:
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
tv.setText("Trying Again");
myLayout.addView(tv);

The error is because you are looking for an XML file in your resources.
Try this,
In your code:
LinearLayout myLayout = (LinearLayout) findViewById(R.id.layout_main);
In your XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout_main"
android:layout_width="match_parent"

You are using the xml and the LinearLayout wrong.
1- call this to set your xml as content view
setContentView(R.layout.activity_main);
2- give an id to your linear layout
android:id="#+id/myLinearLayout"
3- find your linear layout like this
LinearLayout myLayout = (LinearLayout) findViewById(R.id.myLinearLayout);
4- then add your view
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
tv.setText("Trying Again");
myLayout.addView(tv);
I didn't try but this should work.
The mistakes you're doing are
1- SetContentView method overrides all the views in the content view. so it'll remove everything when you call
LinearLayout thisLayout = new LinearLayout(this);
setContentView(thisLayout);
2- You need to use id of an item while trying to find it. Not the name of the layout file like you did here
// findViewById gets the id of the view that you want to find
LinearLayout myLayout = (LinearLayout) findViewById(R.layout.activity_main);

Related

How to apply layout inheritance to android views programmatically?

I have a TextView that is generated programmatically (and not in xml layout file).
TextView myTextView = new TextView(this);
How do I apply all the attributes of the parent of this TextView (that is NOT created programmatically and it's stored in xml ) to it via code? (How do I inherit programmatically?)
Suppose your Root xml is-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
You want to add view dynamically to this view. Then set layout params of the parent to the child and set all other properties you want. Lastly add the view to the root and enjoy. In your Activity/Fragment use code like this-
LinearLayout rootLayout = (LinearLayout) findViewById(R.id.root_layout);
TextView textView = new TextView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.CENTER;
textView.setLayoutParams(layoutParams);
textView.setGravity(Gravity.CENTER);
textView.setText("Hello");
rootLayout.addView(textView);
Note: If your root layout is a RelativeLayout then use RelativeLayout.LayoutParams and for others accordingly.

relativeLayout.rightOf not working properly

I have this code in which i am adding certain views dynamically into a relativeLayout. Problem is despite using the above mentioned feature in the code, all the views are overlapping each other.
date=(EditText)findViewById(R.id.Date);
save=(Button)findViewById(R.id.Save);
save.setText("Confirm Purchase");
container=(RelativeLayout)findViewById(R.id.container);
items[no]=new AutoCompleteTextView(this);
RelativeLayout.LayoutParams p1=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
p1.addRule(RelativeLayout.ALIGN_PARENT_START);
items[no].setId(id++);
container.addView(items[no],p1);
items[no].setHint("Enter Item");
quants[no]=new EditText(this);
RelativeLayout.LayoutParams p2=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
p2.addRule(RelativeLayout.RIGHT_OF, items[no].getId());
quants[no].setId(id++);
container.addView(quants[no],p2);
quants[no].setHint("Quantity");
rates[no]=new EditText(this);
RelativeLayout.LayoutParams p3=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
p3.addRule(RelativeLayout.RIGHT_OF, quants[no].getId());
rates[no].setId(id++);
container.addView(rates[no], p3);
rates[no].setHint("Rates");
totals[no]=new TextView(this);
RelativeLayout.LayoutParams p4=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
p4.addRule(RelativeLayout.RIGHT_OF, rates[no].getId());
container.addView(totals[no], p4);
totals[no].setText("Amount");
PlZ dont ask me to do it in XML. Its a piece of a long code.
XML:
<ScrollView android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="2">
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/container">
</RelativeLayout>
</ScrollView>
Instead of using RelativeLayout, you can try using LinearLayout instead with which you would relax and not think about relative positions of newly added items. with LinearLayout you have to just assign orientation property in order for your elements to be displayed in the orientation suitable for your project
1.Your need xml to define all "id" for your controllers. I've not try to use id in codes directly without ids.xml.
2.You might use LinearLayout instead of RelativLayout.

TextView write text vertically when setting its layoutparams to fill_parent

I am trying to add TextView into a view which extends LinearLayout. When I set its width of layoutparams to fill_parent or wrap_content, the text inside TextView will display vertically such like the following.
e.g.
T
E
X
T
However, when I set the width to some fixed number, it will display normally or as I expected.
e.g. TEXT
My question is why this happens and how to solve it, i.e. how I should set programmatically so that TextView can write text horizontally without setting a fixed width to it such as setting fill_parent or wrap_content?
Here is setting of XML code of the parent ilGallery which extends LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.illib.ilgallery.view.ILGallery
android:id="#+id/galleryLayout"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
</LinearLayout>
The following is the code how i initialize the children inside it:
ilViewPager = new ILViewPager(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
ilViewPager.setLayoutParams(params);
ilgallery = this;
//initialize default header and footer view
LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
headerView = new TextView(context);
headerView.setLayoutParams(params2);
((TextView)headerView).setTextSize(TypedValue.COMPLEX_UNIT_PX,40);
((TextView)headerView).setText("hello");
footerView = new TextView(context);
footerView.setLayoutParams(params2);
((TextView)footerView).setTextSize(TypedValue.COMPLEX_UNIT_PX,40);
((TextView)footerView).setText("hello2");
There appears to be only a single item inside your LinearLayout. Please set the orientation of the LinearLayout to "horizontal", like this:
android:orientation="horizontal"
Also, whenever possible instead of creating new LayoutParams objects from scratch, you should get the LayoutParams from the current layout and modify that, like this:
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)ilViewPager.getLayoutParams();
lp.<change-any-values>;
ilViewPager.setLayoutParams(lp);

The best way to inflate view programmatically

I found a simple SwipeSample that I changed to allow me to create new xml layouts and inflate the main layout to display them. What I wanted to do was also be able to programmatically add layouts for the swipe process.
I have the main.xml layout and a red.xml and yellow.xml which are a simple linearlayout with a textview set to a solid color.
The code below works but I don't think that it's correct or the best way to do what I'm trying to get.
If anyone can suggest a better way that would be greatly appreciated.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Create a layout with a solid blue background programmatically
TextView tv1 = new TextView(this);
tv1.setText("Blue");
tv1.setBackgroundColor(Color.BLUE);
tv1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
ll.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
ll.addView(tv1);
//Create a layout with a solid green background programmatically
TextView tv2 = new TextView(this);
tv2.setText("Green");
tv2.setBackgroundColor(Color.GREEN);
tv2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
LinearLayout ll2 = new LinearLayout(this);
ll2.setOrientation(LinearLayout.VERTICAL);
ll2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
ll2.addView(tv2);
//inflate the flipper view and add the yellow and red xml layouts and also the 2 programmatically created layouts
fSpace = (ViewFlipper)findViewById(R.id.flipper);
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.yellow, fSpace);
inflater.inflate(R.layout.red, fSpace);
fSpace.addView(ll);
fSpace.addView(ll2);
}
If you have a complex layout that you want to create programmatically, it might be easiest to have the layout premade in xml and then just inflate it and add it at runtime.
Create view in xml
Here is a sample premade xml layout that is in the layout folder. Yours could be anything, a single view or a whole complex layout.
layout/my_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/TextView1"
android:text="This is a TV"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/TextView2"
android:text="How are you today?"/>
</LinearLayout>
Make a container for your view
Have some place it put your view in your activity layout. You could have something like this.
<FrameLayout
android:id="#+id/flContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</FrameLayout>
Inflate the view
Use get a reference to the container, inflate your view from xml, and then add it to the container.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout container = (FrameLayout) findViewById(R.id.flContainer);
View inflatedLayout= getLayoutInflater().inflate(R.layout.my_view, null, false);
container.addView(inflatedLayout);
}
Doing it like this keeps your code a lot cleaner.
See also:
How to inflate one view with a layout
Add a View to a wrapper multiple times with inflate
The way you inflate R.layout.yellow and R.layout.red is indeed the right way to do so. You may be able to simplify your code by moving a lot of it over to xml. I assume tv1 is just a sample? if not, it could go into main.xml. You may even find a way to create yellow and red with a single inflation... depending on what you're doing.
Programmatically creating views is just, for the most part, slightly tedious.

Add view to already existing xml viewgroup in code

I would like to be able to add a view to an already existing xml layout in code:
LinearLayout ll = (LinearLayout) findViewById(R.layout.common_list);
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
tv.setText("sample text");
ll.addView(tv);
setContentView(ll);
When creating a new LinearLayout in code it works, but when using a Resource like in the code above it doesn’t.
common_list.xml:
<?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="fill_parent">
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Quick List"/>
</LinearLayout>
Try to use LayoutInflater
LinearLayout ll = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.common_list)
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
tv.setText("sample text");
ll.addView(tv);
setContentView(ll);
If this won't work, please add error from Logcat.
Also, you should change properties from android:layout_width="fill_parent" to android:layout_width="wrap_content" in yout LinearLayout in common_list.xml and also do the same thing to your TextView in common_list.xml
Why? Because your layout is horizontal-oriented and it fills whole screen space. Your TextEdit fills as much space as your layout does (so in this case it's whole screen space). Now, when you add another TextView it is adding properly - to right of your first TextEdit, so it's like out of screen. To understand exactly what happens:
-----------------
||-------------||---------------
||| TextViev1 ||||addedTextView|
||-------------||---------------
|| ||
|| ||
|| ||
|| ||
|| ||
||LinearLayout ||
||-------------||
| screen |
----------------
I also had this problem many times. Usually if you add View to layout and you don't see it (and you get no errors) problem is with width/heigth or position (ex. when you use RelativeLayout).

Categories

Resources