How can I retain attributes of the children in a RelativeLayout when dynamically adding ImageViews?
I have a custom ImageView I want to add at runtime to an empty RelativeLayout (nothing inside in XML), I can add the first, then move, scale and rotate them, it works fine.
When I add another ImageView all previously added instances loose their position and their size, but when I touch them they get back just their size, not the position.
In my ImageView I'm overriding onDraw and onTouch, do I need to override something else?
Maybe I have to write my own RelativeLayout implementation? I wouldn't!
This is the pseudocode for adding new ImageView:
create new instance of ImageView
set bitmap
set scaletype
add imageview to the RelativeLayout container
I even tried to set a standard layout parameter for the brand new added ImageView with the same result.
I tried to get the margins for every children, based on its position, and the re set the layout with ImgeView.setLayout(l, t, r, b);
no success...
Here's the XML RelativeLayout container, pretty simple, maybe too much?
<RelativeLayout
android:id="#+id/face_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</RelativeLayout>
Do you need more details to help me? Please ask, I can post the code too, but I have to clean it up a bit before, I can do it tomorrow, in the meantime please give me some advice.
In a RelativeLayout all view positions are related to the others views. So, as you do in xml, you should provide for each view the relative parameters.
Before add imageView to the RelativeLayout call setLayoutParams(layoutParams):
// Create a new RelativeLayout.LayoutParams instance
RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
// add roules
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
layoutParams.addRule(.........
layoutParams.addRule(.........
//add params to view
imageView.setLayoutParams(layoutParams);
//add imageview to the RelativeLayout container
yourRelativeLayout.addView(imageView);
Look here for all rules.
Related
I must be missing something really stupid.
I have a LinearLayout in my view:
_editTextViews = (LinearLayout)findViewById(R.id.editDesAndLocViews);
I am trying to dynamically change the height of that view by setting the LayoutParams
I have two LinearLayout.LayoutParams
LinearLayout.LayoutParams collapsedParams;
LinearLayout.LayoutParams openParams;
that are set in the constructor like so:
collapsedParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,0);
openParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);
But as soon as i try to apply one of those params to my LinearLayout, like so:
_editTextViews.setLayoutParams(collapsedParams);
I get the following FATAL EXCEPTION:
At first i thought my project needed to be cleaned as it seems to think i am trying to force a relative layout to use linear layout params, but everything is LinearLayout. The LinearLayout in question does contain a couple RelativeLayouts. I don't know if / why that would be the problem.
please help
Change your LayoutParamss' type to either ViewGroup.LayoutParams or RelativeLayout.LayoutParams.
The LayoutParams you apply have to match the parent layout of the view. LayoutParams define how a View is layed out in its parent view (layout). Because each layout type takes different parametres for laying out a view (e.g. only LinearLayout has weight, only RelativeLayout can use anchors), they all have their own LayoutParams.
I have a custom view which will be jar'ed up and added into another project. In the view I want to give an option of a button.
Here is what I have in the CustomView class.
final CustomView currentView = (CustomView) findViewById(this.getId());
RelativeLayout.LayoutParams params = (new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT ));
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
closeButton.setLayoutParams(params);
currentView.addView(closeButton);
This is all wrapped in a RelativeLayout Tag as well as the other objects of the application
Everything compiles however in the CustomView the Button is aligning left instead of right.Any Ideas???
I would guess the problem is your CustomView. It probably doesn't take the entire width of the window, and is just wide enough to fill its children (which, in your case, is the close button). Make sure your CustomView has a fill_parent horizontal layout.
Since your CustomView extends WebView, which, in turn, extends AbsoluteLayout, you can't expect it to handle RelativeLayout's parameters. Instead, it's best you put your customview and your close button inside a RelativeLayout and position them properly.
When adding your closeButton to your currentView you need to supply the LayoutParams as an argument as well in order for them to take effect.
Basically, switch
currentView.addView(closeButton);
with
currentView.addView(closeButton, params);
Since the width of your button is set to wrap_content, you could also try setting its layout_gravity to right.
params.gravity = Gravity.RIGHT;
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.
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.
I have a custom view (an extension of a TextView) that I want to dynamically add to my Layout (don't want to include it in the main.xml file).
The book says to fetch the RelativeLayout using findViewById() in my java code then create a new instance of my custom view, then use addView on the RelativeLayout to add the new view.
I'm not getting any errors, but when I click my button to add the new view, nothing is happening (view isn't being added). Do I need to set additional properties on my custom view (layout width, layout height for example) in order for it to be shown?
EDIT: adding code
// changed to an imageview as I thought it might be easier to see an image
RelativeLayout rel = (RelativeLayout) findViewById(R.id.rellay);
MyCustomImageView mciv = new MyCustomImageView(null);
mciv.setId(5);
LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
mciv.setLayoutParams(p);
mciv.setImageResource(R.drawable.someImage);
rel.Addview(mciv);
Please post your code where you add the view.
But yes, you might be missing the params for width and height. Try something like
LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.FILL_PARENT);
txtView.setLayoutParams(p);
or what you would like the width and height to be. Also in xml layout, layout_width and layout_height are required attributes.