GridView row height - android

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?

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 !!

Android Multiple Shape Drawables In LinearLayout

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.

Android: aling background of setPageMarginDrawable to fit into margin

I have a ViewPager with a graphic in between:
mPager.setPageMarginDrawable(R.drawable.margin);
I have set the image to repeat in y direction.
margin:
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/image"
android:tileMode="repeat"
android:dither="true" />
The problem is that it does not align to margin space. It seems that its repeated independently of the size of the ViewPager. On one device I mangaged to get the size that it fits into because its a multiple of the screen width in landscape and portraint, but on other devices it wont work.
Is there a solution for my problem?
thanks
okay solved it my own.
I scale the margin drawable programatically so that the display width is a multiple of it.
not beautiful, but working. better solutins are welcome.

Custom EditText vertical alignment

I created a custom EditText (actually, I just set a background drawable). The problem is that its text is always top-aligned, and I want it to be vertical-center-aligned. I've already tried to set its gravity to CENTER_VERTICAL, but it doesn't work. This is the drawable I created:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:gravity="center_vertical">
<solid android:color="#FFFFFF"/>
<stroke android:width="1dp" android:color="#88BA52" />
<corners
android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
</shape>
And here's how I create it:
searchEditText = new EditText(getContext());
searchEditText.setTextSize(12);
searchEditText.setSingleLine();
searchEditText.setGravity(Gravity.CENTER_VERTICAL);
searchEditText.setHint(R.string.search_hint);
searchEditText.setBackgroundDrawable(
getResources().getDrawable(R.drawable.search_field));
addView(searchEditText);
searchEditText.setGravity(Gravity.CENTER | Gravity.LEFT);
This might help
Try reducing your font size. For whatever reasons, I have found if your font size is too large, even if it appears to you the EditText should be tall enough to hold the text, the text will appear to be higher than properly centered vertically.
Adjust your font size down, or specify a font size if you are using default value, until you find a font size value small enough for it to appear properly centered.
I'm seeing the same issue. Programmatically creating an EditText resulted in the gravity being vertically forced to TOP (while horizontal centering still works) ... until I commented out the calls that set the background! In this case, vertical and horizontal gravity are both honored.
Here is my code:
inputField.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
inputField.setLinksClickable(false);
inputField.setInputType(ie.getInputType());
inputField.setFadingEdgeLength(0);
inputField.setHorizontalFadingEdgeEnabled(false);
inputField.setPadding(borderWidth.left,borderWidth.top,borderWidth.right,borderWidth.bottom);
inputField.setOnEditorActionListener(this);
inputField.setHint(hint);
inputField.setCompoundDrawables(null, null, null, null);
// comment out the next two lines to see gravity working fine
inputField.setBackgroundDrawable(null);
inputField.setBackgroundColor(Color.WHITE);
inputField.setTextColor(Color.BLACK);
inputField.setTextSize(TypedValue.COMPLEX_UNIT_PX, 20);
inputField.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
Now, step tracing in the OS source code reveals that the computation for vertical centering strangely relies on the height reported by the background. Defaut in EditText is a NinePatchDrawable with a 64 pixels high default bitmap. If your EditText is this height, your text will be centered. Otherwise, it will be closer to top than it should. Setting a background color will internally use a ColorDrawable which reports an intrinsic height of zero, therefore only using the text height and vertically aligning it to TOP.
The way to fix this issue is to create your own Drawable subclass, set it as the background of the EditText instance, make sure you call setBounds() on the drawable so it has a height to report, and override the getIntrinsicHeight() method of the drawable to report the height that was set using setBounds().

Categories

Resources