Programmatically change a xml-created view - android

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.

Related

How to automatically adjust the TextView height according to the size of the String?

I want to know how to automatically adjust the size of the TextView according to the length of the String. I am getting some data from another Intent as a String and storing it in a TextView. If I leave it small, the whole text won't fit and only half of it is displayed. If I leave a big space for the TextView it does not look nice on the screen.
The solution I found online was using extends TextView and using this method gives errors in my class and I have to change a lot of functions because of this
Use a multi-line TextView and set layout_height to wrap_content:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="false"/>
Note: If you set layout_width to wrap_content it won't work properly. If you don't want the TextView to take up the entire width of the parent view then either:
Set it to a fixed width in XML, or
Set the width programmatically, or
Set layout_alignLeft/layout_alignRight etc in a RelativeLayout
Set the layout_width to 0dp and use a layout_weight in a LinearLayout
If you are using xml file, just do this,
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="false"/>
And if you want to do dynamically do like this,
TextView textView= new TextView(activity);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
textView.setLayoutParams(param);

Programmatically set ImageButton layout_gravity

What I Tried To Do
I tried to set my ImageButton's layout_gravity via Java code, the way I want the ImageButton to be is presented like the way within the Orange frame in the image below:
The Blue frame is a vertical LinearLayout act as a "base" layout and this is the layout I tried to add child layouts to.
The Orange and Red are both horizontal LinearLayout.
The Orange layout is the way I want to put the ImageButton and the TextView, this one is set up via XML
The Red layout is the result I tried to mimic the Orange layout via Java code.
The Related Code
Here's the XML code that set up the Orange layout, this is the effect I want to achieve via Java code:
<!-- Begin the Orange Layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/info_left_padding"
android:layout_marginRight="#dimen/info_right_padding" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:minHeight="#dimen/detail_min_line_item_height"
android:text="TextView" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageButton
android:id="#+id/imageButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:adjustViewBounds="true"
android:maxHeight="#dimen/abs__action_bar_default_height"
android:scaleType="fitCenter"
android:src="#drawable/navigation_cancel" />
</FrameLayout>
</LinearLayout>
Here's the Java code that set up the Red layout
int textHeight = (int)getResources().getDimension(R.dimen.detail_min_line_item_height);
int imgHeight = (int)getResources().getDimension(R.dimen.abs__action_bar_default_height);
TextView mTextView = new TextView(this);
ImageButton mDeleteButton = new ImageButton(this);
// Set Delete Button Padding
// mDeleteButton.setPadding(buttonPadding, buttonPadding, buttonPadding, buttonPadding);
// Set Imagebutton Scale type as fitCentre
mDeleteButton.setScaleType(ScaleType.FIT_CENTER);
// Set AdjustViewBounds
mDeleteButton.setAdjustViewBounds(true);
// Set max height of the image
mDeleteButton.setMaxHeight(imgHeight);
// Set the text appearance to be "large"
mTextView.setTextAppearance(this, android.R.style.TextAppearance_Large);
mTextView.setText(text);
// Set the minimum height of this textview
mTextView.setMinHeight(textHeight);
// Set the content of the textview to be centred
mTextView.setGravity(Gravity.CENTER_VERTICAL);
// Set the ImageButton's background image
mDeleteButton.setImageResource(R.drawable.navigation_cancel);
LinearLayout.LayoutParams hParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
LinearLayout hLayout = new LinearLayout(this);
// Set Margins
hParams.leftMargin = (int) getResources().getDimension(R.dimen.info_left_padding);
hParams.rightMargin = (int) getResources().getDimension(R.dimen.info_right_padding);
hParams.bottomMargin = (int) getResources().getDimension(R.dimen.text_layout_margin);
hLayout.setLayoutParams(hParams);
// Set orientation to horizontal
hLayout.setOrientation(LinearLayout.HORIZONTAL);
// The settings below is actually setting up some of the button's parameters
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
buttonParams.gravity = Gravity.RIGHT;
mDeleteButton.setLayoutParams(buttonParams);
hLayout.addView(mTextView);
hLayout.addView(mDeleteButton);
layout_blue.addView(hLayout);
What I've Tried So Far
According to some SO post like this: Java method for android:layout_gravity I initially tried to first put my ImageButton into a FrameLayout then set the params of this FrameLayout, like this:
FrameLayout buttonFrame = new FrameLayout(this);
FrameLayout.LayoutParams buttonParams = new FrameLayout.LayoutParams(android.widget.FrameLayout.LayoutParams.WRAP_CONTENT,
android.widget.FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.RIGHT | Gravity.CENTER_VERTICAL);
buttonFrame.setLayoutParams(buttonParams);
buttonFrame.addView(mDeleteButton);
But I had the same result as the image presented above. Later I also tried to change the LayoutParams width to MATCH_PARENTonly to find theImageButton` was stretched horizontally (Yes it's stretched)
Then I tried the method posted in these two SO posts:
How to set layout_gravity programmatically?
How to set a button's parameters programatically
Their method is to set up a LinearLayout.Params first, then apply this params to the button (The Code I posted in The Related Code section applies this method). In short it is:
// The settings below is actually setting up some of the button's parameters
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
buttonParams.gravity = Gravity.RIGHT;
mDeleteButton.setLayoutParams(buttonParams);
However, the result was still the same as the image presented above.
Question
Since I need to programmatically add more child views to the Blue layout later, I wonder if there's a way to set up each child layout like the Orange one in the image?
At Last
I found a solution which is quite similar to #Permita 's answer.
Here's my solution:
LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT);
textParams.weight = 1.0f;
mTextView.setLayoutParams(textParams);
Add the below code, it will assign all the available space to the texView, shifting the button to right side of the layout to make it appear like the orangeLayout.
mTextView.setLayoutParams(LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT, 1.0f));
Try layout_width = "0dp" layout_weight="1" for the TextView. This tells TextView to occupy the whole available width, so that FrameLayout with ImageView will align to the right border.
<TextView
android:id="#+id/textView1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:minHeight="#dimen/detail_min_line_item_height"
android:text="TextView" />
Instead of using the standard LinearLayout, why not try to use the more complex RelativeLayout? With it, you can adjust the locations of each individual view relative to others. You can set the ImageButton in the orange layout to android:layout_alignParentRight="true", which will set the button attached to the right side of the parent layout, the RelativeLayout in my case, but the LinearLayout in yours. Here is the link to the API Guides for Relative Layouts on the Android developers website.

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

Adding EditText to custom LinearLayout

I recently updated a custom view so I could potentially add an EditText to the center of my canvas (so to speak).
After adding my onDraw code to dispatchDraw my custom LinearLayout works in the same way as my previous custom view did.
Now, how can I add an EditText smack in the middle of the layout?
So far I am trying this:
EditText edit = new EditText(getContext());
edit.setText("My EditText");
edit.setTextSize((int)Math.ceil(thickness/2));
edit.setWidth((int)(diameter*0.07f));
edit.setX(centerX);
edit.setY(centerY);
addView(edit);
Forgive some of the variables, they are not too important but I'm trying to add the EditText using the X and Y coordinates.
Thanks for any help.
UPDATE:
I have updated my LinearLayout constructor to inflate the comment_edit.xml file to see if I could get it to work this way.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_comment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/edittext_comment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:imeOptions="actionDone" />
</LinearLayout>
The LinearLayout constructor extract is as follows:
LayoutInflater inflater = LayoutInflater.from(context);
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.comment_edit, this, false);
EditText edit = (EditText) view.findViewById(R.id.edittext_comment);
edit.setText("Add Comment");
edit.setX(112);
edit.setY(117);
addView(view);
I have also tried:
LayoutInflater inflater = LayoutInflater.from(context);
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.comment_edit, this, false);
EditText edit = (EditText) view.findViewById(R.id.edittext_comment);
edit.setText("Add Comment");
view.setX(112);
view.setY(117);
addView(view);
The EditText still does not appear
In case the answer is not found yet. Every dynamically created view should have layout parameters (WRAP_CONTENT, FILL_PARENT, etc) that is why is not shown. For more information please edit your question accordingly.
An example might be:
editText.setLayoutParams(new LayoutParams(WRAP_CONTENT,WRAP_CONTENT));
EDIT:
Now your problem is that the edit text is not centered. Ok, I can give you an overview but I believe you must research from now on because there are a lot of things to do. First of all the LinearLayout is what it says, is a layout that it stacks the views vertically or horizontally. The position of the text shouldn't be given with the actual pixels of the screen but with some other specific layout parameters. Take Gravity for example, it aligns the inner view of a layout to the center, left, etc. Add gravity property of the LinearLayout.
I hope it helped

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.

Categories

Resources