24

I am using a GridView. Four items in a column. Each element is composed of the following layout:

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="vertical">

  <ImageView
    android:layout_width="32dip"
    android:layout_height="32dip"/>

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="11dip"
    android:paddingTop="2dip" />
</LinearLayout>

So each element is a small image with a bit of text below it. The layout works great on the first pass. However, if an item's text is long, it wraps to two lines. This works ok, until you scroll it in and out of view. By default, all the images in a row are top-aligned. When you scroll a row off-screen, then back on screen, you'll see that the row somehow gets bottom-aligned. It looks like:

First layout:

[image]   [image]   [image]  
[text]    [text]    [text
                     wrap]

so even though the third element has 2 lines of text, the tops are aligned which is perfect. If I scroll this row off screen, then back on, it looks like this:

                    [image]
[image]   [image]   [text
[text]    [text]     wrap]

so the row gets bottom-aligned here. I'm not sure if this is a bug in GridView, or if there's some way to control the layout to always top-align rows. I've tried setting the gravity of the element layout to "top", no good. There also doesn't appear to be any setting unique to GridView to control this. Any ideas?

Thanks

user291701
  • 38,411
  • 72
  • 187
  • 285
  • All I can think of to do for now is to add whitespace to all strings to equal the length of the longest string in my dataset. Since the font is monospaced (i think) then everything should top-align again correctly. This is madness! – user291701 Nov 05 '10 at 13:38
  • please share the ans if you already found. – PiyushMishra Dec 13 '12 at 09:20
  • @user291701 did you ever find an answer to this, I'm struggling with it myself – Russ Wheeler Dec 04 '13 at 11:48

4 Answers4

14

The height of the items in the GridView must be the same. You have 2 or 3 options.

  1. Give a height to the TextView
  2. Make the TextView single line with android:singleLine="true"
  3. If you must have 2 lines in some of the items, make all the items have 2 lines. You can do that android:minLines="2"
tasomaniac
  • 10,234
  • 6
  • 52
  • 84
  • @RogerGarzonNieto what did you end up doing off this answer? I'm really loathed to force my textview to have 2 lines every time. I'm sure it should be pretty simple to make every child item in the gridview align to top – Russ Wheeler Dec 04 '13 at 11:49
  • 1
    You may also simply do ``android:lines="2"``. This prevents possible issues if one of the items exceeds 2 lines (which will be truncated, but that's a different issue!). – SMBiggs Jan 20 '16 at 22:35
  • minLines = 2 is not working. I understand what u say, but it is not working – M. Usman Khan Apr 11 '16 at 12:00
  • even fixed height misaligns for 2 rows. – M. Usman Khan Apr 11 '16 at 12:03
  • Min lines should be available only on TextView 's. Are you using TextView 's? – tasomaniac Apr 11 '16 at 12:10
0

Some devices doesnt work good with style.

    grid.setColumnWidth(90);
    grid.setNumColumns(GridView.AUTO_FIT);
    grid.setVerticalSpacing(10);
    grid.setHorizontalSpacing(10);
    grid.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
    grid.setGravity(Gravity.CENTER);
    grid.setOnItemClickListener(this);

<style name="GridViewStyle" parent="@android:style/Widget.GridView">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:columnWidth">90dp</item>
        <item name="android:numColumns">auto_fit</item>
        <item name="android:verticalSpacing">10dp</item>
        <item name="android:horizontalSpacing">10dp</item>
        <item name="android:stretchMode">columnWidth</item>
        <item name="android:gravity">center</item>
    </style>

// look how my adapter return textview
// I have som troubles with order you just have to refresh adapter (onResume or orientation change)

public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView!=null) return convertView;

        Intent intent = (Intent) getItem(position);
        TextView tv = new TextView(mContext);
        tv.setGravity(Gravity.CENTER_HORIZONTAL);
        tv.setText(intent.getStringExtra("text"));

        try {
            tv.setCompoundDrawablesWithIntrinsicBounds(null, mContext.getPackageManager().getActivityIcon(intent), null, null);
        } catch (NameNotFoundException e) {
            tv.setCompoundDrawablesWithIntrinsicBounds(0, android.R.drawable.ic_secure, 0, 0);
        }

        return tv;
    }
Mertuarez
  • 901
  • 7
  • 24
0

If you are using a getview method, you can set its height/width dynamically, you do not need to take all the elements of same size. It will automatically crop the image from its center dynamically.

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView = new ImageView(mContext);
        imageView.setImageResource(mThumbIds[position]);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); //it will crop the image from center
        imageView.setLayoutParams(new GridView.LayoutParams(70, 70));
        return imageView;
    }

Also set the number of colums you want in your xml

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/grid_view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="2"          // set the number of coloums
    android:columnWidth="90dp"
    android:horizontalSpacing="10dp"
    android:verticalSpacing="10dp"
    android:gravity="center"
    android:stretchMode="columnWidth" >  
</GridView>
BenC
  • 8,729
  • 3
  • 49
  • 68
Anshul
  • 147
  • 2
  • 13
0

Try android:layout_gravity="top" in your LinearLayout.

Also, if you are manually inflating your layouts for the cells, be sure to use the inflate() version that takes the GridView as the 2nd parameter and use false for the third parameter.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Argh no luck with either method. Still bottom-aligns the row when scrolling back into view. – user291701 Nov 05 '10 at 15:09
  • Another thing is that when scrolling up and down, the scrollbar calculation goes haywire - the gridview will all of a sudden let you scroll infinitely, so you end up looking at a blank canvas. Trying to scroll back fails at that point. It's really bizarre behavior, I think it's a bug within GridView. – user291701 Nov 05 '10 at 15:10
  • @user291701: If you think it is a bug, create a sample project that demonstrates the behavior, and post it with an explanation to http://b.android.com. If you think of it, add a link here to the issue. – CommonsWare Nov 05 '10 at 15:18
  • 4
    Ok will-do. For now I just set the textview::lines=2. This gives each element the same height and seems to work. – user291701 Nov 05 '10 at 16:14
  • I have also experienced the issue you mentioned about the screen going blank as you scroll up/down. I fixed it by adding a view holder to the grid adapter. – omega Feb 03 '12 at 12:08
  • i think it occurs each time a gridView's view has x lines in its textView while the one on the right has x-1 lines of text in its textview . the reason it worked is that you've set the exact number of lines. – android developer Sep 08 '12 at 18:04