I am learning Android development and I'm trying to make a simple calculator. I am having some problems with layout of the calculator. In my opinion, it would be too clunky to post the whole xml code, so I'm just going to post the snippets that matter in my opinion.
I made a vertical LinearLayout as the top-most parent, which then has 2 children, a horizontal LinearLayout, (which consists of a textView which shows your input and a button that tells to calculate) and a GridLayout, which would be 0-9 buttons and operators.
The problem is, the grid layout would be a 4x4 grid with buttons and when I want to set the First row of buttons, each button needs to get layout_height, which can't be left empty and if I set it's value to match_parent, then that button alone would fill up the whole screen.
So how can I solve this problem with layout_height, is there some workaround or would it be better to make multiple LinearLayouts for the grid? If you have any additional questions, feel free to ask so I can explain.
Here is the children LinearLayout and GridLayout xml code:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_weight="1"
android:background="#color/colorLight"
android:orientation="horizontal">
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="8"
android:background="#color/colorLight"
android:>
Sorry, I misunderstand your question.
If you use API 21 or newer, you can use columnCount to get it.
Please refer to that answer or that answer
The best way to sort this out for various screen sizes is to use the weight attribute. For GridLayout, there is none, according to the documentation.
Check out this answer for ideas, such as subbing nested LinearLayouts.
GridLayout (not GridView) how to stretch all children evenly
Related
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.
In my app I am calling API to get list of people with some informations (address, phone numbers etc.). Under every phone number, I am creating programatically 3 buttons (add to contacts, edit and call). Problem is, that last button is cut off (small screen). I am using Linear Layout horizontal.
Is there any way to control size of screen and if needed, put last button to second line? When I rotate screen to landscape, I have enough space, so buttons should stay in one line.
Now, I am using horizontalScrollView with visible scrollbar. It's working, but I am not very satisfied with it.
Thanks for help.
I'm not really sure if you can do that with LinearLayout. But you could do that using FlowLayout. Check this link: https://github.com/ultimate-deej/FlowLayout-for-Android.
This layout moves the buttons to the next line if there is no space for them on the screen.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weight="1" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weight="1" />
</LinearLayout>
the weight attribute will automatically adjust your button size
make sure you set width to match parent for all buttons.
Best to create a new variant of the listitem layout for smaller screenshots:
layout-w200dp/listitem.xml : layout with 3 buttons on one line
layout/listitem.xml : layout with buttons on separate lines
Android will then choose the multiline layout when the current available width is smaller than 200dp. (Note that you can still tweak the 200 to a different value)
Alternatively you can also use an alternatieve linearlayout which does the wrapping for you: Flowlayout
This is probably more complicated to achieve that you wan't it to be but the best shot is to use some adapter based solution:
GridView - this is the old solution, better go for the 2nd
RecyclerView with StaggeredLayoutManager setup to your needs
Simple solution is using android:layout_weight="1" and android:layout_width="0dp" as params for each button in your LinearLayout but then they will fit the whole screen and take the same percent of the width, and if the screen is too small buttons might get cut off.
I have a linearlayout and have to inflate variable number of buttons at runtime in this Linearlayout. Now my problem is that when I give Orientation for this linear layout. if I give it Horizontal or Vertical which create the problem. Will explain it with example:-
Eg1: Input is 3 buttons
Expected Output: Button1 Button2 Button3 ( If all 3 fits in one line completely)
All the 3 buttons should be displayed in this linear layout and in same line(just like horizontal) provided they fit completely.
Eg2: Input is 4 Buttons and they cannot fit in whole line
Expected output:-
Line1:- Button1 Button2 (Assuming Button3 is not fitting completely in this line)
Line2:- Button3 Button4
Currently if I set LinearLAyout's orientation as Horizontal then its forcing all the 4 buttons in one line and the UI is getting screwed up. Same is the case if I give orientation as vertical.
Can someone tell me how to handle this at run time so that only complete buttons are displayed in one line and it spreads over multiple lines. Some generic way to handle this case.
The layout can be considered something like this for static purpose:-
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<Button
android:id="#+id/button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="YYYYYYYYYYYOOOOOOOOOOOOO"
android:textSize="75sp"/>
<Button
android:id="#+id/button_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AAAAAAFFFFFFFFFFGGGGGGGGG"
android:textSize="75sp"/>
</LinearLayout>
LinearLayout doesn't work that way. It will layout items either vertically or horizontally(It doesn't wrap). You have a few options.
It sounds like your buttons will be different sizes(so you probably don't want to use gridview), you can either create Vertical LinearLayout that houses several HorizontalLinearLayouts(that in turn hold the Button).
Alternatively you can roll your own custom ViewGroup. Both methods are going to require you to write the calculation logic for determining what fits on a row. Your custom view group will likely be cleaner in the end but require more knowledge about the View.
what I understand is you need to load n number of views dynamically and you want your views to be auto carried over your parent view. I think what you need is just a gridview with a simple adapter. The "cell" of your gridview will be the buttons in your case. There is a lot of info out there about it. This is the simple guide provided from google.
http://developer.android.com/guide/topics/ui/layout/gridview.html
Hope I help you.
Regards.
I would like to place a layout on the bottom of a LinearLayout, but I can't seem to get it to work. I know that I can use RelativeLayout to do this, but I should be able to use LinearLayout, shouldn't I?
EDIT: Actually this is more confusing than I thought. The layout below is simplified. In reality, I'm using fragments on a pre-3.0 device, with the compatibility layer.
I used Hierarchy Viewer to examine what's going on, and found that an android.support.v4.app.NoSaveStateFrameLayout was added to my layout, and that layout has layout_height set to wrap_content. That seems to be what's causing my problem, but I haven't yet figured out how to fix it.
Specifically, why doesn't this work? Shouldn't the layout_gravity place it at the bottom?
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
... stuff here ...
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="horizontal">
... more stuff here ...
</LinearLayout>
</LinearLayout>
BTW, changing layout_height to fill_parent or setting layout_weight don't seem to work either. I just want to better understand what is going on, because clearly I'm missing something important. Thanks.
First of all nice question.
Android behaves we can say weird in the situation like this.
if you have selected your parent linear layout's orientation horizontal then you can set its child component at bottom by setting its layoug_gravity=bottom. suppose you have added 2 text views in that horizontal linear layout and second textview's layout_gravity is bottom then it will set to bottom but it work like it is set at bottom in other column then the first text view. NOTE : you can set textview's layout_gravity = "left" or "right" when its parent linearlayout is horizontal but you cant see its result.
Oppositely, if you have selected parent linearlayout's orientation vertical then you can set its child component at left or right by using layout_gravity. but the second textview will shown in you can say next row with left or right gravity as you have set. NOTE you can set textview's layout_gravity = "top" or "bottom" when its linear layout is vertical but you can not see its result.
Try to make sample xml design as i have stated above so you get better idea.
Strange but True!!! Try to understand this behavior. :)
Just add space between what you want at the bottom and all the rest:
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
So I resolved the problem. It's a two-part solution:
First, the way to do this without using LinearLayout is to provide weight to the element above so that it takes up all of the empty space. BTW, you can see this example in the API demos: http://developer.android.com/resources/samples/ApiDemos/res/layout/linear_layout_3.html
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
... stuff here ...
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weight="1"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
... more stuff here ...
</LinearLayout>
</LinearLayout>
This by itself didn't solve my problem, as I had a NoSaveStateFrameLayout with layout_width="wrap_content" as a parent view, and so I needed to get that fixed first. I'm using code based on the wonderful Google I/O App, and when I searched the code for NoSaveStateFrameLayout, I found this:
// For some reason, if we omit this, NoSaveStateFrameLayout thinks we are
// FILL_PARENT / WRAP_CONTENT, making the progress bar stick to the top of the activity.
mRootView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
Thanks for an awesome comment Google!!! I added this into my source and everything worked great!
The moral of the story: Hierarchy Viewer and comments are your friends.
LinearLayout will just stack things as they are placed in there. Since it is vertical, it will keep placing items one after the next in a vertical manner. Can you change the android:gravity of the linearLayout and not the layout_gravity of the nested one and see if that works.
RelativeLayout of course should be the first way but you stated you didnt want to do that. Is there reason for that?
It could be that, as per https://stackoverflow.com/a/13366783/513038, you need to set the parent LinearLayout to have android:baselineAligned="false". Worked in my case.
I have a LinearLayout with fixed view. I dynamically inject images in it (ImageViews) but I dunno in advance how many of them will be inserted. I'd like to have a layout where images wrap and go to a new line authomatically when they exceed the available width of the father (LinearLayout)
how do you recommend I should move?
thanks a lot
Define a Listview within the Linear Layout like below. Wrap your Linear Layout tags around it.
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:scrollbarAlwaysDrawVerticalTrack="true"
/>
Update this list view dynamically as you add images. This will solve your issues.
As I answered on a question asked a couple of hours before yours:
There is no layout manager in Android today that behaves like Swing's FlowLayout, where it wraps widgets onto multiple lines. It is theoretically possible for you to write one yourself, by looking at the open source code for LinearLayout, etc. and following the patterns they establish.
Sorry!