Reputation: 131
I am trying to create a custom dialog view for my application. When running the program, the result is far different from what I expect.
XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorPrimaryDark">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/colorAccent">
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary">
<Button
android:id="@+id/button10"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
</LinearLayout>
The Java class:
public class SinglePSettings extends AppCompatDialogFragment {
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_singlepsettings, null);
builder.setView(view)
.setTitle("Settings");
return builder.create();
}
public void onResume()
{
super.onResume();
Window window = getDialog().getWindow();
Point size = new Point();
Display display = window.getWindowManager().getDefaultDisplay();
display.getSize(size);
int width = (int)(size.x * 0.90);
int height = (int)(size.y * 0.90);
window.setLayout(width, height);
window.setGravity(Gravity.CENTER);
}
I do not fully understand why the main LinearLayout is 'invisible'. It also seems that the items inside do not depend on it. Is there a way to fill up the full-size of the dialog block with a layout?
(What of course later I can further customize.)
Upvotes: 0
Views: 155
Reputation: 1179
This is because the root layout of your dialogue is of height match_parent
and the total size of content is 200dp for the first child Linearlayout
+ ~24 dp for the second child Linearlayout
which is smaller than the total size of the dialog.
You should either change the height of the parent LinearLayout
to wrap_content
or add android:weight=1
to either of the child LinearLayouts.
Let me try to explain how linear layout works. Note that these are all from experience and you should read the official documentation for better understanding.
The dimension which is in line with the orientation
plays a crucial role for a linear layout's children. Thus, if the orientation is horizontal, then all the children will stack horizontally, and their width
attribute would be needed to be controlled.
Imagine a horizontal linear layout as a home. For the time being, assume that you always have to keep your crucial attribute as match_parent
in parent linear layout. Thus our Linear layout/ home has width=match_parent
. There can be three major ways by which the children could be added:
wrap_content
This means each child will take the amount of screen space equal to its own size.
if the number of items is less or the screen size is big enough, this approach works.
But if there are a lot of big items, then the total space required by them = sum of all of their individual widths. If this sum is greater than the screen size, then some of the items will go out of the screen.
In our home analogy, it is like we are stacking all the tables, chairs, beds, etc. in a straight line. If they take up less space than the space between two end walls, then it's great, but if they need more horizontal space, then we must break the wall to adjust them.
Thus it's not advisable to keep your all items as wrap content
match_parent
This is a very wrong approach. When you keep a child's width as match_parent
, you are basically telling the compiler to provide complete screen space to this single view.
And the compiler would definitely do so. Even if it's a button, it would stretch out on the complete screen and other views will not be visible, because they are virtually out of the screen.
When there are multiple views with width=match_parent
, it will simply allocate the whole screen space to the first view from the left.
In our home analogy, it's like as soon as you changed the width attribute of your chair to match_parent
, the room magically expanded it to take complete space, and thus your bed, table, etc. are now all squashed up at the side of room.
layout_weight=x
for one or more childrenThis is the best approach to be used in linear layout. I think of it as assigning a percentage of screen to a view.
If your child view has weight=x
, then it will not be affected by the value present in your view's crucial attribute
. That means you can have width= match_parent
or wrap_content
or even 1000000dp
, if it has weight=x
, it's going to render as full screen view. Note that I am only talking about a crucial attribute, i.e., width in this case.
It is also very interesting to know how a view with weight is going to affect other views.
width = match_parent
(and no weight attribute), that view is going to take the whole screen space, but this time our view WITH weight would not be squashed out. Instead, this gets the minimum space it should be getting (i.e., either wrap_content or the fixed value we passed for width=x
). It would be like we added weight
attribute to our chair and match_parent
attribute to our bed. The bed squashed out all the other items, but the chair still took the space it requires.Something similar goes when other items has wrap_content
as the values of their crucial attribute (but no weight attribute). This time, the view with weight is going to take all space, except the space required by other view (compare the below image with the first case, and notice how the circle is now taking all the remaining space without squashing the other views)
When every attribute has a weight, then this becomes a fun game of percentages. If we have two items, and every item has layout_weight=1
, then no matter whatever their width is, both will take 50% of the space. If one of them has layout_weight=2
, then distribution would be 2:1, i.e., 66%:33%. This makes the views responsive in different screen sizes and orientations.
Thus, the best way to use children views in a Linear layout is to have wrap_content
in their crucial dimension attribute and layout_weight=x
. This will make it much responsive and easier to control. Also I did not talk much about having fixed weights in the crucial dimension attribute, because they are always a mess to handle. I won't get into details (you can try for yourself), but they will always end up either getting squashed or squashing other views.
Upvotes: 2