Android Multiple Shape Drawables In LinearLayout - android

Okay, so all I am trying to do is set four circles up in a linear layout. The problem is the circles show up as ovals. I have tried not setting width and height in the circle.xml files, I have tried setting width of the circles in the view to 0dp, wrap_content and 50dp to match the height, still, ovals. I have tried not setting the weightSum in the layout with the same result, it's like it doesn't need to be there.
LinearLayout
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="200dp"
android:paddingRight="#dimen/xlarge_padding"
android:paddingLeft="#dimen/xlarge_padding"
android:orientation="horizontal"
android:weightSum="4">
circle_blue.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="50dp"
android:height="50dp" />
<solid android:color="#color/fc_blue"/>
I am calling the circles with Views that have the width set to 0dp and the height to 50dp, and the layout_weight to 1 with the background set to circle_xxx.xml.
Should I just ditch the weight settings and use padding to space them apart?
Here is a screenshot of how they look on device
https://www.dropbox.com/s/afh8d8m3jrbhrzf/Screenshot_2015-09-27-06-35-07.png?dl=0

That's the effect of using weights.
I guessed that, because you used the (useless) weightSum attribute in the LinearLayout.
Now, weights actually modify the children Views dimensions, which are no more 50dp in width, while they maintain 50dp in height.
This is why you get ovals, instead of circles.

Related

How to spread children that display an XML shape evenly in a GridLayout (with maximum possible size)?

Here is what i want:
I have a GridLayout inside of a ConstraintLayout, to which I add multiple rows and columns of custom ImageButtons (BoardCells) dynamically.
The ImageButtons display circles using a shape XML file (code below).
I want the BoardCells to have equal width and height so the shape really is a circle and not an oval.
I also want the BoardCells to take as much space as possible on the screen and spread evenly.
Here is what I tried:
I tried a fixed size (in dp) for the BoardCells and setting layout_width of the GridLayout to wrap_content, but that will only work on different screens that are rather similar and does not use the space optimal. Screenshot of the GridLayout with fixed size BoardCells.
When I dont't set size for the shape and BoardCell then nothing gets displayed at all, doen't matter if GridLayout has match_parent, wrap_content or 0dp.
So I tried to give all BoardCells the same weight inside of the GridLayout like this:
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f);
params.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f);
this.setLayoutParams(params);
this.setScaleType(ScaleType.CENTER);
But setting column- and rowSpec does not keep the ratio so I don't get circles (which makes sense).
Screenshot of the GridLayout with column- and rowSpec set to 1 for every BoardCell.
So I tried to only set columnSpec and setting the ScaleType to CENTER or CENTER_INSIDE, hoping this would keep the ratio but stretch as much as possible.
But this only stretches horizontally and takes the fixed size vertically.
Screenshot of the GridLayout with columnSpec set to 1 and ScaleType CENTER
Then I thought I would implement an onLayoutChangedListener for the GridLayout, but trying to add children to GridLayout inside of onLayoutChanged resultet in "requestLayout() improperly called" errors in my log.
My last idea is to first display an empty GridLayout and only when the user presses a button to start the game (the button exists anyways because you may play multiple rounds), and the view is already inflated and displayed, I receive the width and height of GridLayout and calculate the biggest possible size for the BoardCells.
But this approach does not seem to be best practise.
Now I don't know what would be the right thing to do.
Did I do something wrong or is there any solution that I didn't think of at all?
Should I experiment with a bunch of emulated devices and create XML shape files for different screen sizes?
Is the dynamic approach okay?
Here is the relevant Code:
XML layout file:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/wood"
android:padding="10dp"
tools:context=".MainActivity">
<androidx.gridlayout.widget.GridLayout
android:id="#+id/board_cells"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/guideline70"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline8"
android:layout_margin="10dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I fill this GridLayout with custom ImageButtons with the following Code:
gridLayoutBoard.setUseDefaultMargins(true);
gridLayoutBoard.setRowCount(10);
gridLayoutBoard.setColumnCount(6);
for (int i = gridLayoutBoard.getRowCount()-1; i >= 0; i--) {
for (int j = 0; j < gridLayoutBoard.getColumnCount(); j++) {
if (j == 0 || j == 5) {
Indikator text= new TextView;
gridLayoutBoard.addView(text);
} else {
BoardCell boardCell = new BoardCell(this);
gridLayoutBoard.addView(boardCell);
}
}
}
The ImageButtons (BoardCells) set their background to this selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item android:drawable="#drawable/cell_solid"/>
<item android:drawable="#drawable/cell_gradient"/>
</layer-list>
</item>
</selector>
which uses the following solid shape and a gradient with the same size and shape:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#color/grey_cell_dings" />
<size
android:width="30dp"
android:height="30dp"/>
</shape>

Android layout 50% 50% fill with image over it

I'm trying to get android layout with one half of screen in one solid color, and another half - with another solid color and over it in the center of screen will be an image.
Is it possible to do so?
I've tried to use one layout and set gradient to it:
<gradient
android:type="linear"
android:centerX="51%"
android:startColor="#FF59901d"
android:centerColor="#FF59901d"
android:endColor="#FF2b241f"
android:angle="270"/>
but it didn't work as I expected - it gave smooth color mix, not 2 colors separated each from another. I think here is needed another gradient control point.
Another option was use 2 linear layouts and fill them with different colors, it gave normal background as I want, but in this case how to position image over both layouts at the center of screen?
To elaborate on #323go comment, Inside a framelayout use two linearlayout. Give weight = 1 to both. and height = 0dp (asssuming you wish to split in upper and bottom halves).
Then use a Relativelayout which fills whole screen, but has transparent background. Inside it place an imageview with center Parent Vertical as true
Create a RelativeLayout with your ImageView aligned centerInParent and set the RelativeLayout with the following background-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:type="linear">
<gradient
android:angle="270"
android:startColor="#FF59901d"
android:centerColor="#android:color/white"
android:endColor="#FF2b241f"
/>
</shape>
Hope this helps !!

Margin/Padding Shrinks ImageView

I recently tried to position an imageview's x and y coordinates with no luck, it seems there is no way to do it in Gingerbread. I then decided to try out paddings and margins, but when I set them, it shrinks my imageview. I set a left padding of 250dp and image view became tiny. The layout_height and width are set to wrap_content. I'm not sure what's going on. Does anyone know why setting a padding/margin would shrink an imageview?
You're confusing margin and padding. Margin is the area outside of your view, while padding affects the content inside your margin.
If you set padding, then it is going to affect your available content area, and assuming you have a ScaleType set, it's going to shrink your image down to fit the available space.
Now, you say you've tried margins, but margins will do exactly what you're asking.
For example, if you wanted an ImageView placed 10dp from the top-left corner, you can do something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="#+id/my_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:src="#drawable/my_image_id"
/>
</RelativeLayout>
Keep in mind that this places it 10dp with respect to the parent boundaries. If your parent layout also has padding, then that will affect your content placement.
if by shrink you mean the picture's ratio is messed then you should use
android:scaleType="centerInside"
this will prevent the ratio from changing

GridView row height

I have a GridView that displays images, which are, unfortunately, of different sizes. They are shown in between two lines of text:
text1.1 text1.2
ImageView(IMAGE1) ImageView(IMAGE2)
text2.1 text2.2
text3.1
ImageView(IMAGE3)
text4.1
etc....
If IMAGE1 is the same height as IMAGE2, everything is fine, but if IMAGE1 is longer than IMAGE2, text2.1 will run into text3.1 (padding doesn't seem to help much, as there's too much of it when images are of the same height).
I know there's a way to stretch the images in the ImageView so they are the same height, but is it possible to keep images as is and set the row height somehow?
You are in control over your row heights, by virtue of what you put in them. Since your cells appear to have more than one widget, they are presumably wrapped in a LinearLayout or something. Set your LinearLayouts to be some specific height, and the rows will all be that height.
Personally, I think you should be resizing your images if you are going to have text above and below each image on a per-cell basis.
Use drawable as background on Layout that is your grid cell and define that drawable with:
<size android:height="<some height>" />
For example:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff"/>
<size android:height="60dip" />
</shape>
Here is an alternative solution that pre-measures items and sets the height of each cell to the max height in that row.
GridView rows overlapping: how to make row height fit the tallest item?

What's the difference between fill_parent and wrap_content?

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

Categories

Resources