How can i set margin to a view in another class? - android

I do a constructer and set some view inside programmatically and add some rule. so When i call constructer i see default view.
Now i want to reach someof this view and change set margin.It is basic i know but i dosent work for me.
Can anybody help?
Part of my constructer:
_photoImgVw = new ImageView(getContext());
_photoImgVw.setImageResource(R.drawable.pic);
_photoImgVw.setAdjustViewBounds(true);
_photoImgVw.setMaxWidth(100);
_photoImgVw.setId(2);
lp2=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp2.setMargins(0,0,0,0);
addView(_photoImgVw,lp2);
LayoutParams lp3=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp3.addRule(RelativeLayout.RIGHT_OF,_photoImgVw.getId());
lp3.setMargins(0,0,0,0);
addView(_nameTxt,lp3);
Call in the activity for change:
facebookPersonView.lp2.setMargins(10,300,100,20);

Make sure that the layout params lp2 are an instance of the class RelativeLayout.LayoutParams instead of MarginLayoutParams, or any other subclass of it named LayoutParams (there are quite a few, see the top of the documentation).
If the params are an instance of the latter, they won't contain any rules for the RelativeLayout. Which means the parent layout doesn't know where to place the view¹ and therefore can't make any sense out of the margins.
It's best to declare that explicitly in a way like this:
RelativeLayout.LayoutParams lp2
= new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
lp2.setMargins(0,0,0,0);
addView(_photoImgVw,lp2);
¹ It will still make it visible in the top-left corner, but it's kind of an undefined state.

Related

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

Programmatically change View properies Android

In general, I'm trying to understand if it's possible in Android to arbitrarily change the properties of a view programmatically.
I understand that there are many properties that can be changed via methods (e.g. TextView.setBackgroundColor() among many others) but there aren't methods for every possible property.
Specifically, I'm interested in instantiating a custom View and then changing the layout_weight. I'm interested in learning how to do this, but in general I want to know how I'm supposed to create a custom View if I can't change it's properties programmatically. I understand I can change all its properties in xml (including custom xml properties) but I want to be able to instantiate the view at run-time.
layout_ attributes are actually slightly different than most other things as explained in this pro-tip: they're instructions to the parent ViewGroup and are stored in their LayoutParams.
For example, layout_weight in a LinearLayout would be found in LinearLayout.LayoutParams. This means you can change them by doing
LinearLayout.LayoutParams params =
(LinearLayout.LayoutParams) yourCustomView.getLayoutParams();
// Set the weight however you like
params.weight = 4.0f;
Creating the view allows you to do this as well:
LinearLayout parentLayout = ...;
YourCustomView yourCustomView = ...;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, // width
LayoutParams.WRAP_CONTENT, // height
1.0f); // weight
parentLayout.addView(yourCustomView, params);

How do I add FrameLayout and ImageViews within it Programmatically?

There are plenty of similar questions asked in SO, but then also, please take time to read my question.
I need to create a UI programmatically that would have multiple ImageView, all positioned at different location of the screen and having their associated click events (its a game app). I found that FrameLayout is appropriate choice, where I can set margins on my own and have it positioned at desired location.
Now, I'm confused whether to have FrameLayout for every single ImageView I create, or to keep single FrameLayout and add all ImageViews within it, but set each imageview at different position.
In either of the case, how can I add FrameLayout, and ImageView within it, programmatically and also set its margin such that it can be placed anywhere on the screen.
Note that my main canvas, which will carry all these ImageViews has background, and the canvas is a LinearLayout set via XML, so my onCreate() already has setContentView(R.layout.game_canvas);, and I'd be using addContentView() to add additional views, but this method too accepts LayoutParams object as it second parameter, so what exactly should I set for this, when I add my FrameLayouts using this method?
My question might be confusing itself, so please let me know if I need to elaborate.
FrameLayouts are designed to only hold one View, so this isn't really the appropriate choice.
Use a RelativeLayout to hold all of your ImageViews. You can position each ImageView by setting the margins in their LayoutParams.
E.g. The following code would place an ImageView at coordinates 50,50:
RelativeLayout imgLayout = new RelativeLayout(this);
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.an_image);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(50, 50, 0, 0);
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
imgLayout.addView(iv, lp);
You can then add this RelativeLayout to your main LinearLayout using its addView() method.

RelativeLayout add rule "RelativeLayout.LEFT_OF" not working

I have a relativeLayout like below:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:id="#+id/parent" >
<ListView
android:layout_width="360dp"
android:layout_height="600dp"
android:id="#+id/list"
android:inputType="text"
android:maxLines="1"
android:layout_margin="50dp"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
In the java code, I want to add a view to the left of the listview, but it didn't worked:
m_relativeLayout = (RelativeLayout)findViewById(R.id.parent);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.LEFT_OF, m_listView.getId());
Button button2 = new Button(this);
button2.setText("I am button 2");
m_relativeLayout.addView(button2, layoutParams);
only if I set the listview to alignParentRight, it will work. Is this an android bug or I'm missing something?
I always try addView(View child, int index, LayoutParams params), but it might only work in the linearlayout. So is there an normal solution to make the RelativeLayout.LEFT_OF work?
EDIT
I have tried RelativeLayout.BELOW and RelativeLayout.RIGHT_OF, and they worked perfectly, so it means I don't have enough place to get the button? I tried to give more space, but it still not work.
I use Toshiba AT100 (1280*800) and landscape, so the space is enough. Test below and right just same as the left. I think If i put an control A in the relativelayout, then I add control B and decalare it's on the left of the control A, the result should be the control B will push the control A to its right, right?
I think If i put an control A in the relativelayout, then i add control B and declare it's on the left of the control A, the result should be the control B will push the control A to its right, right?
Your assumption is incorrect, the control A will not be pushed to the right unless you specified this with a RelativeLayout.LayoutParams rule. RelativeLayout places its children one one top of each other starting at the top-left corner of the screen if you don't specify placement rules for them. When you add the View A to the RelativeLayout without any rules(like layout_alignParentRight) it will be placed starting from the top-left corner of the screen. Then, when you add the View B, the rule to_leftOf will apply to this View position but this rule doesn't mean anything for the View A who will maintain its position on the screen. This will make View B to be place to the left of View A but outside of the screen as View A bounds start from the left border of the screen.
The Button will be placed to the left of the ListView when you use layout_alignParentRight="true" because there is now space to actually see the Button(it's not outside anymore). addView(View child, int index, LayoutParams params) works in a LinearLayout because the LinearLayout arranges its children in a row or column(depending on orientation) so when you add a View at a specific position, it will push the other Views after it to the right or below(depending on orientation)(there is no relative positioning of the views in a LinearLayout, the only rule is that the children come one after the other).
Starting with the ListView without any rules set on it, here is an example on how to make the Button to appear on the left of the ListView:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
Button button2 = new Button(this);
button2.setText("I am button 2");
button2.setId(1000);
m_relativeLayout.addView(button2, layoutParams);
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) m_listView
.getLayoutParams();
rlp.addRule(RelativeLayout.RIGHT_OF, button2.getId());
The Button will be added as normal to the screen and it will appear starting from the top-left corner of the screen. Without the two lines from the code above the Button and ListView will overlap as this is the normal behavior of RelativeLayout for children without any rules on them. We then explicitly modify the position of the ListView to move it to the right(with the last two line from the code above).
If your variable names are indicative, it's because you are adding the widget to a LinearLayout, so tags for a RelativeLayout get ignored.
This line is the one I'm talking about:
m_linearLayout.addView(button2, layoutParams);
EDIT
You say alignParentRight works... the only difference there is that ot doesn't take an anchor parameter. Perhaps m_listView.getId() isn't returning the proper id. You could step through with the debugger and see if it's returning a proper value.
Maybe you could try calling the id specifically...
layoutParams.addRule(RelativeLayout.LEFT_OF, R.id.list);
To perform it, use predefined view ID or declare one. In values folder create ids.xml then add a Item like this:
<item name="imageViewID" type="id"/>
use this id in your code where you are creating new Instance of view like this:
RelativeLayout layout=new RelativeLayout(context);
ImageView imageView = new ImageView(context);
imageView.setId(R.id.imageViewID);
RelativeLayout.LayoutParams layoutParams = new LayoutParams(50, 50);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
layout.addView(imageView, layoutParams);
TextView textView = new TextView(context);
RelativeLayout.LayoutParams textViewParams= new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
textViewParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
textViewParams.addRule(RelativeLayout.BELOW, imageView.getId());
layout.addView(nameView, nameLayoutParams);
or we can directly use this function View.generateViewId() to perform the same. Like this:
imageView.setId(View.generateViewId());
I think you might have forgotten to add m_listView to the RelativeLayout or m_listView's visibility would be GONE.
Can you please check for that?
setId before align is called, especially for the new object view.
If you are using a custom id and not a regular generated Android id (eg. R.id.my_id), make sure that the id is not equal to 0 (or negative), otherwise the rule will be ignored.

How do I programmatically remove an existing rule that was defined in XML?

I have a linear layout that is contained inside a relative layout.
It is set in the XML file to be to the right of another linear layout (this works fine).
In some cases I want to change the relative position of the layout during the onCreate of the activity so I need to modify the "to the right of" param to relate to another layout.
I tryed this:
RelativeLayout.LayoutParams layoutParams;
layoutParams = (RelativeLayout.LayoutParams) linearLayoutToMove
.getLayoutParams();
layoutParams.addRule(RelativeLayout.RIGHT_OF,
R.id.new_ref_LinearLayout);
But it does not work :o(
Any clues ?
You can't remove a rule because all rules are always stored in a fixed-size java array. But you can set a rule to 0. For example
layoutParams.addRule(RelativeLayout.RIGHT_OF, 0);
layoutParams.addRule(RelativeLayout.BELOW, R.id.new_ref_LinearLayout);
EDIT (thanks to Roger Rapid):
As of API level 17, the class RelativeLayout.LayoutParams has the following method:
public void removeRule(int verb)
So you can remove a rule using the following line of code:
layoutParams.removeRule(RelativeLayout.RIGHT_OF);
And you will get exactly the same result as when 'adding' a zero-rule as:
layoutParams.addRule(RelativeLayout.RIGHT_OF, 0);
I think you need to call:
relativeLayout.updateViewLayout(linearLayoutToMove, layoutParams);
after changing the LayoutParams.
In reply to the edit, you can create new LayoutParameters using:
LinearLayout.LayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
and then add your new rules. Then, update the layout parameters using the previously mentioned updateViewLayout() method.
add the following code to your existing code
linearLayoutToMove.setLayoutParams(layoutParams)
I think this should do the job. In case if the above line dont work, try to call linearLayoutToMove.invalidate() after the above line.

Categories

Resources