When I use a linear layout I am unable to graphically move any elements around in the WYSIWYG editor. If I set them to relative I can, but I the reasoning doesn't make sense to me. After reading up I am under the impression linear is somewhat like absolute positioning. Shouldn't dragging objects be possible?
<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:background="#400080"
tools:context="com.x.EntranceActivity" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/mobile_full_logo" />
</LinearLayout>
Yes you can't visually move elements inside LinearLayout.
LinearLayout can hold all elements in vertical orientation or horizontal orientation, so there is no need for dragging elements somewhere else.
But you can set android:layout_gravity and android:gravity attribures for elements to position them in right way as you want.
From the docs:
A Layout that arranges its children in a single column or a single row. The direction of the row can be set by calling setOrientation().
You can tweak things like gravity, padding, and weight, but there is no way to set absolute positions. As such, dragging them around in the WYSIWYG editor is disabled.
Related
So I have a UI element (a single line of text) that I want horizontally centered with respect to the overall device -- unless/until it collides with other UI elements in the given view group / layout. At that point I'd like it to be either centered in the space remaining or pegged as close to being centered overall as possible without colliding. [When there's finally not enough space, then I want to use ellipses.]
Is there any way to achieve this using just standard Android layouts?
I'm currently achieving this via code that adjusts layout constraints when the view group's width changes, the text changes, or related UI elements become visible/invisible. It works fine, but I can't help thinking that some layout should just do this for me.
You can use a weighted horizontal LinearLayout like this:
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:gravity="center_horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="i am centered"
android:ellipsize="end"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="another widget"/>
.
.
.
</LinearLayout>
The TextView with width 0dp and weight 1 will use the remaining horizontal space.
You can add additional widgets to the LinearLayout, and the TextView will always take the remaining space.
For example, if you change the Visibility of the Button to GONE, you'll see the TextView will expand to use the whole width. Similarly, if you programmatically add new widgets to the LinearLayout, the available space for the TextView will adjust.
You can further add ellipsize options to control what happens when the text does not fit in the TextView size.
Related question. Answer: RelativeLayout can't do it. I'm asking how to do it anyway, with not just RL, or with something else.
General story: you have a complex layout that would be difficult to adjust, and along comes a request for something to be added, aligning with a nested view.
What is the best approach? A popup with a custom style? (not familiar with those yet)? Spending days changing the whole hierarchy to a single RelativeLayout? A custom Layout class as wrapper?
AbsoluteLayout (deprecated) or FrameLayout with programmatically changed LayoutParams or margins? (this I'd rather avoid, I prefer not to touch onMeasure, etc)
Simplified example (no relation to pic above):
LinearLayout defines relative heights of the elements. I don't know to do it with RelativeLayout.
anExpandableView is something to be animated as sliding from under someBar (here; full-width, but perhaps it may need to align its width, as well as vertical position).
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/topStuff"
layout="#layout/incl_topstuff"
android:layout_width="match_parent"
android:layout_weight="7"
android:layout_height="0dip" />
<include
android:id="#+id/someBar"
layout="#layout/incl_filters_and_stuff"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="#+id/bottomStuff"
layout="#layout/incl_bottomstuff"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="10" />
</LinearLayout>
<include
android:id="#+id/anExpandableView"
layout="#layout/incl_filters"
android:visibility="gone"
android:layout_below="#id/someBar"/>
</RelativeLayout>
I know SO has an aversion to general questions, but I don't want an ad-hoc solution. I am asking what to do in cases which would be solved if only a wrapping RelativeLayout would allow alignment to a view that is not a direct sibling.
Putting it simply, RelativeLayout can only measure and layout it's direct children based on each other, but I guess you already knew that.
The only general solution would be to implement your own custom Layout class, which I wouldn't recommend. If I had to guess why RelativeLayout does not traverse the entire layout hierarchy at it's level and below, it's probably for performance reasons.
Unfortunately if you're using RelativeLayouts and LinearLayouts and you want views to be dependent on each other you have to pick one approach and stick to it, either the flat hierarchy of RelativeLayout, or the nested one of LinearLayout.
Based on your example, as far as I know, there is no way to implement weighted views with a RelativeLayout, so you're stuck with using a LinearLayout.
The easiest way to do what you want is to inflate your expandableView in code, align it with the bottom of the RelativeLayout, set it's height and position based on bottomStuff, and animate from there.
If you really want to do it in xml, I can think of one somewhat hacky, ad-hoc approach, but which can can be generalized to mirroring the measurement and layout of any hierarchy with a bit of work.
Create a parallel but invisible LinearLayout that is a sibling of the first one. Give it an empty view with weight 7 on top, an invisible copy of someBar in the middle, then your expandable view under that with weight 10. To have it slide up, either animate the height of the invisible someBar and the weight of the empty view on top towards 0, or remove them/set them to gone and set animateLayoutChanges on your LinearLayout.
I have many activities with a scrollview inside a tablelayout. However, it is necessary a small design change, so I have to put a black transparent view over the whole screen from the top to the bottom. Is it possible to do it in the tablelayout or the scrollview?
RelativeLayout allows for easy overlapping of views. You'll have to adjust the existing views in your app because it doesn't do anything automatically.
EDIT:
A quick way to do this would be to take your existing view (the ScrollView) that is already organized and put it in a top-level RelativeLayout. Then, all you have to do is add new view inside the RelativeLayout with the width and height both set to MATCH_PARENT. The result should be the black transparent view will be visible over the ScrollView.
I normally use FrameLayout to achieve any kind of 'layering' of views.
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
//your existing layout
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#33000000" />
</FrameLayout>
As DeeV said, you can probably use RelativeLayout in a similar way, but you might have to set additional attributes on its children to achieve this.
I need to implement the layout as in the picture. Parent and Sibling are in a vertical LinearLayout. So I need to make a child view to overlap it's parent. Can I do that in android?
If:
sibling is a sibling of parent
parent is a ViewGroup
and you really want child to be a child of parent
then maybe you could consider using android:clipChildren set to false on parent.
I was actually just looking at an example of a FrameLayout that had a TextView overlaid on top of an ImageView. So, there are obviously multiple ways to get it done. Your next question might be which one is best ... to that I have no idea, but here's a guy that might:
http://www.curious-creature.org/2009/03/01/android-layout-tricks-3-optimize-part-1/
Just contain them all within a RelativeLayout, and remember the draw order is top to bottom, so put the top most view on the bottom of the XML definition.
If you use a RelativeLayout you should have no problem achieving this effect. By default it will stack all of its children on top of each other in the top left corner if you don't supply them with android:layout parameters. So it will definitely support overlapping children. You'd just have to figure out what the best way to tell it where the child should go on the screen relative to something else.
There are at least two layouts that can do that. AbsoluteLayout and RelativeLayout. I suggest that you put your views in a RelativeLayout and add them with LayoutParams that specify their offset form the top and left of the parent:
RelativeLayout.LayoutParams rlp;
label = new TextView(ctx);
label.setBackgroundColor(0x00000000);
label.setTextColor(0xFF7ea6cf);
label.setTextSize(13);
label.setGravity(Gravity.LEFT);
label.setText("Examples:\n- Fentanyl\n- Dilaudid 2 mg PO q 4 hours prn moderate pain");
rlp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,100);
rlp.topMargin=189;
rlp.leftMargin=30;
rlp.rightMargin=30;
rlParent.addView(label,rlp);
In my case, I have to set android:clipCildren to be false on the parent of parent.
i.e.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:id="#+id/parent1">
<FrameLayout
android:id="#+id/parent2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="64dp"
android:background="#android:color/holo_blue_bright">
<View
android:id="#+id/This_is_the_view_I_want_to_overlap_parent2"
android:layout_width="160dp"
android:layout_height="80dp"
android:layout_gravity="top|start"
android:layout_marginTop="-40dp"
android:background="#000000" />
</FrameLayout>
</FrameLayout>
Sorry for the extremely bad title, I have no other idea what to call this question. What I'm trying to do is this: have a RelativeLayout which has two children:
one with layout_centerInParent="true"
one with layout_alignParentBottom="true"
However, when the device is in landscape mode, element (1) appears slightly over or under element (2). But, element (1) has enough space above it to appear above element (2). How could I make the layout so that if the screen is too small to center element (1) and make both elements not overlap, then align element (1) above (as in layout_above) element (2)?
This should work to give you a layout where the text1 item fills the available space above text2, and is centered vertically and horizontally in that space; and text2 is on the bottom, centered horizontally.
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<TextView
android:id="#android:id/text1"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Centered"
android:gravity="center_vertical|center_horizontal"
/>
<TextView
android:id="#android:id/text2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Bottom"
android:gravity="center_horizontal"
/>
</LinearLayout>
The important parts are android:layout_weight, combined with android:gravity.
Alright here's a leftfield suggestion that might work if your element (1) isn't too resource intensive.
Have two versions of element (1), the first with layout_centerInParent="true" and the second with layout_above="#id\element2". Default them both to android:visibility="invisible". In your onCreate Post a Runnable that inspects the Y dimension of both elements, and sets View.VISIBLE on the element with the smallest value.
New idea:
This is another idea that's sort of a workaround in that it's not very elegant, but it's very simple. Put element (1) in its own < LinearLayout > configured like so:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" // More on this line below
android:layout_alignParentTop="true"
android:layout_above="#id/element2"
android:gravity="center">
That linear layout will always span from the top of screen to just above element (2), and since its gravity is "center", element (1) will always be in the middle of whatever space is available for it. Note: The line android:layout_height="..." is required, but doesn't seem to actually do anything. Whether it's fill_parent or wrap_content, its height is overridden by the lines anchoring its top to the ParentTop and its bottom to element(2). However, not having the line makes it crash with a Runtime exception.
Original, not very good idea:
Another less-than-ideal solution is to use two layout files. Put the portrait layout xml in your layout folder and the landscape layout in a new folder called layout-land. Android then automatically selects the right one based on the orientation of the phone. I think you could use layout-port, but putting the portrait one in just layout makes sure it knows which one to use by default.