I've tried layout_width attribute to match_parent as well as fill_parent on the root element of layout file, for a home screen widget. But when shown in App Widget, it's still being wrapped around the content.
App widget layout:
<StackView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/xxxxxxxxx"
android:layout_width="match_parent" <!-- always acts like wrap_content -->
android:layout_height="fill_parent"
android:gravity="center"
android:loopViews="true" />
Widget is assigned grid size of 4X2:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="250dp"
android:minHeight="110dp"
. . . . . />
But still after being added to a home screen, the widget's width doesn't take up 4 grids on home screen, it just wraps around the content. How can this be solved ?
Having a similar problem, it appears minHeight and minWidth factor into the max size as well, I bet if you increased the minWidth to (4 * 74) - 2 = 294dp it'd work. For your minHeight, the pixel height per the guide would be (2 * 74) - 2 = 146dp, just so you know.
Related
I have a complex xml layout with part of it being:
...
<FrameLayout
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_weight="1" >
<ImageView
android:id="#+id/flexible_imageview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#drawable/gradient"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingTop="8dp" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>
...
The height of the FrameLayout #+id/parent must be determined at runtime because it is displayed above many other views, and they must be shown in the layout. This way the FrameLayout fills the remaining space perfectly (using height="0dp" and weight="1" properties).
The ImageView #+id/flexible_imageview receives an image from the network, and it always shows with the correct aspect ratio. This part is already ok as well. This View is the largest and should determine the size of the FrameLayout #+id/parent.
The problem is that when the image is drawn, the width of the FrameLayout #+id/parent is not adjusted to wrap and be the ImageView #+id/flexible_imageview as it should be.
Any help is appreciated.
-- update --
I've updated the layout to clarify some of the missing parts, and to add the reasoning behind all of it.
What I want is to have an Image (ImageView #+id/flexible_imageview) with unknown dimensions to have, on top of it, a gradient and some text on top of the gradient. I can't set the FrameLayout #+id/parent dimensions to both wrap_content because there is more Views after this Image that must be shown. If there's not enough space in the layout, the Image (ImageView #+id/flexible_imageview) is reduced until it all fits in the layout, but it should maintain its aspect ratio, and the gradient/texts on top of it.
The #drawable/gradient is just:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<gradient
android:angle="270"
android:endColor="#aa000000"
android:startColor="#00000000" />
</shape>
-- update 2 --
I added two images below to demonstrate what's happening, and what should happen:
Bug:
Correct:
If would help if you explained more about what you are trying to accomplish in your layout (not the layout itself but what should the user see on the screen and what are the other elements in the layout).
A FrameLayout with multiple children is usually a "code smell". Usually, FrameLayouts should have only one child element. So this makes me wonder whether there is something wrong with your design.
-- Edit --
If I understand correctly, you are trying the framelayout to wrap the content of the image but at the same time match the space left from the other layout views before/after the frame layout.
What is the parent view/layout of the frame layout?
I see a couple of problems with this design or your explanation:
You have framelayout width set to match parent, but you want to wrap the content of the image.
You want the imageView to be reduced but you are not taking into account the text views in the linear layout. You have them set to wrap content. So when the fame layout is small, you will not see all the textviews. (Unless you are resizing them as well somehow).
Sorry if this isn't helpful enough but it's difficult to understand what you are trying to accomplish with this layout. A sample use-case would help in providing you a better recommendation.
When a dimension (width / height) is MeasureSpec.EXACTLY adjustViewBounds will not effect it.
In your case, having android:width="match_parent" ensures that the image view is the size of the parent, regardless of adjustViewBounds.
It works to begin with because the height is wrap_content - the height is adjusted when the image is scaled to fill the width.
When you override the height to fit everything on the screen (this may not be a great idea to begin with), the width is still matching the parent and doesn't get adjusted. However, because the scale type is ScaleType.FIT_CENTER the image is scaled and positioned so that the entirety of it fits in the bounds of the ImageView (and centred.. hence the name).
If you turn on the debug option for drawing layout bounds, or look at your app using hierarchyviewer, you'll see that the image view is still matching the width of its parent.
There are a couple of ways you could do what you want.
Since you're already manually calculating the height, setting the width shouldn't be that hard.
Drawable drawable = imageView.getDrawable();
if (drawable != null && drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
int height = // however you calculate it
int width = height / (getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth());
}
You might also get away with
<ImageView
android:id="#+id/flexible_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:minWidth="9999dp" />
Even if this works, you probably wouldn't be able to use it in a horizontal LinearLayout using weights any more (for example, if you wanted a landscape variant of the layout), or a number of other scenarios.
I'm developing an Android application and I want to design, in eclipse, a layout bigger than screen height.
I have a layout for a fragment and this fragment will be inside a ScrollView on FragmentActivity.
This is my fragment's layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/user_pro_main_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/text_state"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/layout_state"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
Do I have to change android:layout_height="match_parent" to make it bigger on eclipse's designer?
What do I have to do if I want to see the layout bigger on eclipse designer?
Answer is pretty simple: you can't view layout which is biggern then screen on Eclipse Editor.
Possible workarounds:
1. Comment part of top views (visible) to see bottom (which are invisible), then uncomment when ready to launch.
2. Change Device Preview to bigger resolution (Nexus 10), this will give you some extra space.
You can always explicitly set the exact dp value in layout_height, but of course most of the time I don't think you want a fixed value, so do it programatically.
LinearLayout yourLayout; // Get it by findViewById()
yourLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, your_calculated_height));
You would set android:layout_height="wrap_content" and as you add child elements beyond the physical screen it will continue to stretch the layout.
As for viewing this on Eclipse, I'm not sure. I personally would just run it on a device to view it.
just calculate device height and width and add int value to calculated height and width at runtime at layouts height and width.
public void deviceDisplay(){
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
}
With the below layout (a portion of a larger layout), the container layout's visibility is set to "gone" until a button is clicked. On the button click, if the container_ll is not visible, it's set to visible, and a custom view is added to the reminderViews_ll container.
The views are being added, and the container_ll view is visible on button click. What follows is the width and height of various views after the button is clicked.
container_ll width 420, height 96.
lineDivider_view width 420, height 2 (as expected)
reminder_img width 36, height 36 (as expected, hdpi phone)
reminderViews_ll width 0, height 96 (argh)
<LinearLayout
android:id="#+id/container_ll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
>
<View style="#style/lineDivider_view" />
<ImageView
android:id="#+id/reminder_img"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
/>
<!-- Stick the actual Reminder TVs + Del buttons in here dynamically -->
<LinearLayout
android:id="#+id/reminderViews_ll"
android:orientation="vertical"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
/>
</LinearLayout>
I'm at a bit of a loss as to where to go from here. I was thinking invalidate layout, to force it to draw again after making the view visible, but that's never worked for me (seemingly), and if the reminderViews_ll can get a height of 96, then it can't be an issue with when it's calculating the dimensions of the LinearLayout.
I hope you have enjoyed reading this question as much as I have writing it. Any pointers, as always, appreciated.
The numbers you show look correct to me.
The container is width 420. The other views that are set to fill_parent or wrap_content take up all of the space (actually more). The Linear layout then goes to carve up the remaining space to any weighted views. Since there is no space to allocate, you get zero.
container_ll width 420
lineDivider_view - 420
reminder_img - 36
= -36
so this makes sense
reminderViews_ll width 0
There simply is no room to give it.
Why are you using a horizontal line divider in your horizontal view?
Ah, very confused: layout_width="fill_parent" and layout_weight="1.0" doesn't work?
I mean, layout_width="0dp" is guaranteed to be width 0, regardless of what you put into it, so that one will never do what you want. If you are using fill_parent and its still not working I'd question if you are adding your custom View into the right LinearLayout, because that really should work correctly.
I see that you've set android:layout_width for reminderViews_ll to 0 dp, you have to change this parameter, possibly dynamically if you want to. I don't really understand why you set it to 0 dp and then ask why it has zero width.
I have a RelativeLayout which currently has a fixed size. Widths, heights, margins, font heights of child views are specified so everything looks just right.
I now want to scale the layout (to fit screen size). The layout should scale as if it was a flat image, so everything gets smaller in proportion (fonts, margins etc.)
I made a simplified example, below. Scaled to 0.5, this would display the text "ONE QUARTER" with margin left 200dip and margin top 120dip.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/RelativeLayout01"
android:layout_width="1600dip"
android:layout_height="960dip"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<TextView
android:text="ONE QUARTER"
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="400dip"
android:layout_marginTop="240dip"
></TextView>
</RelativeLayout>
Of course, I'm not asking anyone to help me hand code an algorithm to scale all these values: just wondering if there's some simple way to achieve this...
Thanks!
If you just want your app to look ok on another device then specifying things in dip and sp should do the trick.
If you actually want to shrink or expand the scale of your app on the same device then you would have to do it manually, perhaps using themes or styles.
In Android, when layout out widgets, what's the difference between fill_parent (match_parent in API Level 8 and higher) and wrap_content?
Is there any documentation where you can point to? I'm interested in understanding it very well.
Either attribute can be applied to View's (visual control) horizontal or vertical size. It's used to set a View or Layouts size based on either it's contents or the size of it's parent layout rather than explicitly specifying a dimension.
fill_parent (deprecated and renamed MATCH_PARENT in API Level 8 and higher)
Setting the layout of a widget to fill_parent will force it to expand to take up as much space as is available within the layout element it's been placed in. It's roughly equivalent of setting the dockstyle of a Windows Form Control to Fill.
Setting a top level layout or control to fill_parent will force it to take up the whole screen.
wrap_content
Setting a View's size to wrap_content will force it to expand only far enough to contain the values (or child controls) it contains. For controls -- like text boxes (TextView) or images (ImageView) -- this will wrap the text or image being shown. For layout elements it will resize the layout to fit the controls / layouts added as its children.
It's roughly the equivalent of setting a Windows Form Control's Autosize property to True.
Online Documentation
There's some details in the Android code documentation here.
fill_parent (deprecated) = match_parent
The border of the child view expands to match the border of the parent view.
wrap_content
The border of the child view wraps snugly around its own content.
Here are some images to make things more clear. The green and red are TextViews. The white is a LinearLayout showing through.
Every View (a TextView, an ImageView, a Button, etc.) needs to set the width and the height of the view. In the xml layout file, that might look like this:
android:layout_width="wrap_content"
android:layout_height="match_parent"
Besides setting the width and height to match_parent or wrap_content, you could also set them to some absolute value:
android:layout_width="100dp"
android:layout_height="200dp"
Generally that is not as good, though, because it is not as flexible for different sized devices. After you have understood wrap_content and match_parent, the next thing to learn is layout_weight.
See also
What does android:layout_weight mean?
Difference between a View's Padding and Margin
Gravity vs layout_gravity
XML for above images
Vertical LinearLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:textAppearance="?android:attr/textAppearanceMedium"
android:text="width=wrap height=wrap"
android:background="#c5e1b0"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="width=match height=wrap"
android:background="#f6c0c0"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="width=match height=match"
android:background="#c5e1b0"/>
</LinearLayout>
Horizontal LinearLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="WrapWrap"
android:background="#c5e1b0"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="WrapMatch"
android:background="#f6c0c0"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="MatchMatch"
android:background="#c5e1b0"/>
</LinearLayout>
Note
The explanation in this answer assumes there is no margin or padding. But even if there is, the basic concept is still the same. The view border/spacing is just adjusted by the value of the margin or padding.
fill_parent will make the width or height of the element to be as
large as the parent element, in other words, the container.
wrap_content will make the width or height be as large as needed to
contain the elements within it.
Click here for ANDROID DOC Reference
fill_parent :
A component is arranged layout for the fill_parent will be mandatory to expand to fill the layout unit members, as much as possible in the space. This is consistent with the dockstyle property of the Windows control. A top set layout or control to fill_parent will force it to take up the entire screen.
wrap_content
Set up a view of the size of wrap_content will be forced to view is expanded to show all the content. The TextView and ImageView controls, for example, is set to wrap_content will display its entire internal text and image. Layout elements will change the size according to the content. Set up a view of the size of Autosize attribute wrap_content roughly equivalent to set a Windows control for True.
For details Please Check out this link : http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html