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.
Related
I am designing a scale where I have 100 boxes and their vertical space. Here is the code for that. The below code indicates one Block. Ther will be 100 blocks. in that scale. The height of this block from Imageview and view is 6.7dp. 6.7*100= 670dp.
<ImageView
android:id="#+id/img_2"
android:layout_width="6dp"
android:layout_height="6.5dp"
android:background="#color/boxcolor" />
<View
android:layout_width="6dp"
android:layout_height="0.2dp"
android:background="#android:color/transparent" />
But when I set the height of a graph-view 670 dp it does not match the height of the scale.
<charts.LineChart
android:id="#+id/graph"
android:layout_width="0dp"
android:layout_height="670dp"
android:layout_marginTop="11.7dp"
android:layout_marginStart="2dp"
android:background="#android:color/transparent"
Here are the pictures that explain what it looks like.
first_image,
I cannot directly the height of the scale because the boxes are in the inner views. so can't directly set the height that way.
Please check both pictures.
Here is the whole code file
XML file link
You can't count on math being consistent like that over dozens of objects of different size- eventually rounding will kill you. Devices aren't always exactly able to fill 1 dp, there might not be an even number of pixels in that size. For example, 330 dpi is a common screen size, that would have 2.0625 pixels per dp. That would likely round down to 2 for small numbers. Add a few of those together and now you're off by a few pixels of cumulative error. Where as the 600dp would still only be off by .0625 pixels, because it would calculate off the total.
If you want a view to go around other views, there's 2 ways to do it. One is to make it the parent. If so, put the other views inside it and make this view's height wrap_content. The other is to use a ConstraintLayout or RelativeLayout, make the height wrap_content, but constrain the top and bottom edges to the top of the first image and bottom of the last.
I have a layout (can be relative, linear or constraint)
with TextView aligned to parent left and then ImageView (fix width) aligned that start right to the textView.
I want the image to be rendered first and only then to render the text view.
Meaning I want the text view to be truncated according to the left space after the image was rendered.
<RelativeLayout
android:id="#+id/account_name_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginBottom="#dimen/account_menu_account_name_layout_bottom_margin">
<TextView
android:id="#+id/account_name"
style="#style/AccountDataAccountName"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:lines="1"
android:ellipsize="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
tools:text="emailisverylongaswellwewantittogettruncated#gmail.longdomain.com"/>
<ImageView
android:id="#+id/account_name_chevron"
android:layout_width="#dimen/account_menu_chevron_size"
android:minWidth="#dimen/account_menu_chevron_size"
android:layout_height="#dimen/account_menu_chevron_size"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/account_name"
android:layout_marginTop="#dimen/account_menu_chevron_top_margin"
android:layout_marginLeft="#dimen/account_menu_chevron_left_margin"/>
</RelativeLayout>
I have tried few options:
1) telling the text to be left to the image view
2) putting weight on the text view - made gap between the two elements.
3) setting minWidth to the image view - didn't help just made the imageView scale smaller.
Any idea how to render the image first and how to limit textView's width according to left width?
You can force the width on the imageView. That will prevent the textview from pushing it off the space. If you are saying you did this, please post the resulting image as that wouldn't make any sense.
Your above example has no constraints to each other, no enforcement to not overlay or push off. You need some constraints, such as "toTheLeftOf" or "Weight" or LinearLayout to enforce it as Weight only works in LinearLayout.
The easiest way is to just give the imageView a hard coded DP width and height, then set the text to 0 width with a weight of 1 inside a Linear Layout.
You can also use percentages if you want, use a LinearLayout then put a weight sum of like 100 for example (representing 100%). Then assign your image whatever percentage it needs like layout_weight=30 and give the textview 70.
Any of these options will work fine for you. If you try it, and it does not, then post your tried code as it will work unless you are doing something goofy that is not visible in your current example. As I do this all the time, every time you make a row, you typically have an image on the left fixed and text on the right to grow.
I have the following requirement in Android:
Given a horizontal LinearLayout, I have five buttons in it. All the buttons should have equal width and height. The height of each button is same as their parent LinearLayout and spacing between them should remain constant. The height of LinearLayout is not constant and depends on form factor and other layouts sizing. Therefore, I can not assign fixed with/height to each button.
While I can easily achieve that very easily in iOS with the help of constraints, I am not sure how to achieve this in Android at design time. Is there some way to achieve this or is it possible programatically only?
The height of each button is same as their parent LinearLayout
Set the height to match_parent
For your width, you'll have to calculate the screen size programmatically and set the widths accordingly. See this question.
Try this . As you have a horizontal LinearLayout with 5 buttons, for equal spacing of all buttons, you must first allocate the space to each button of of the total space available like this..
<LinearLayout
android:weightSum="5"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="allocate it programatically"
/>
This button shown above has to be for all 5 buttons u have. The idea allocating weight sum of 5 to LinearLayout and then dividing it as 1 to each button. Note the width here for the button should be 0dp.
Then dynamically change your button Height and Width per your requirement
Unfortunately no typical layout in Android seems to have the concept of this kind of layout constraint (square like elements).
It's the layout that ultimately determines the sizes of their children. Therefore if you want that you have to write your own layout implementing this constraint.
For this extend ViewGroup and in onLayout enforce that width of the children or a specific children equals height. You could even invent your own LayoutParams for this task. See the documentation of ViewGroupfor a general example. The exact implementation very much depends on which other requirements you have for your layout.
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 have custom row for data representation but in first text when text is long it is in two lines but second line is half cut by height (like text view doesn't wrap content)
<TextView
android:id="#+id/txtDate"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:singleLine="false"
android:maxLines="3"
style="#style/row"
android:layout_weight="1"/>
<TextView
android:id="#+id/txtTime"
android:layout_width="0dip"
android:layout_height="wrap_content"
style="#style/row"
android:layout_weight="1"/>
<Button
android:id="#+id/imbDetail"
android:layout_width="36dip"
android:layout_height="36dip"
android:background="#drawable/selector_detail_arrow" />
How to make that has height enough to show all content ?
your height is wrap content which means it'll wrap them to give the shortest view of text. Use fill_parent to display everything.
android:layout_height="fill_parent"
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.
check this answer: Here