GridView 中的横向和纵向图像(如何自动 crop/scale)

Landscape and Vertical images in GridView (how to auto crop/scale)

我想在 GridView 中向用户展示设备上的所有缩略图,其中每个 "cell" 都是一个 ImageView。如果所有照片都是 横向 方向,这看起来不错:每个缩略图都是矩形并裁剪成相同大小(我假设这就是缩略图在设备上 generated/stored 的方式)。

但是,垂直 方向的照片(和缩略图)会导致问题。高缩略图拉伸了单元格,使 UI 看起来很糟糕:

凌乱UI

整洁 UI

有什么好的方便的处理方法?也许我应该简单地在 ImageViews 上设置一些最大高度,手动裁剪(或缩放)垂直拇指?应该在 XML 或 Java 代码中完成这样的事情吗?

Update: Another odd thing, is device-dependency (as always). The images above are from an emulator (Nexus 7), while here's how the same app looks on my (physical) Sony Xperia Z1 compact. Note that all vertical thumbnails (and images) are automatically rotated, such that all thumbs have same, tall size...

相关文件如下:

layout/fragment_main.xml

<FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    tools:context=".MainActivity$PhotoFragment">

    <GridView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="4"
        android:id="@+id/listview_photo"
        style="@style/ForecastListStyle"
        />

</FrameLayout>

layout/grid_item_gallery.xml

<?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:minHeight="?android:attr/listPreferredItemHeight"
    android:padding="1dp"
    android:layout_height="match_parent">

    <ImageView
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:layout_width="fill_parent"
        android:id="@+id/grid_item_photo" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:textAppearanceSmall"
        android:fontFamily="sans-serif-light"
        android:id="@+id/grid_item_label" />

</LinearLayout>

PhotoFragment.java

public class PhotoFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private final static int LOADER_ID = 87;
    private PhotoAdapter mPhotoAdapter;
    private GridView mGridView;

    // these are the data we want from MediaStore
    private final static String[] THUMBNAIL_COLUMNS = {
            PhotoContract.ThumbEntry.COLUMN_THUMB_ID,
            PhotoContract.ThumbEntry.COLUMN_DATA,
            PhotoContract.ThumbEntry.COLUMN_IMAGE_ID
    };

    static final int COL_THUMB_ID = 0;
    static final int COL_THUMB_DATA = 1;
    static final int COL_THUMB_IMAGE_ID = 2;

    public PhotoFragment() {
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        getLoaderManager().initLoader(LOADER_ID, null, this);
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        mPhotoAdapter = new PhotoAdapter(getActivity(), null, 0);
        GridView gridView = (GridView) rootView.findViewById(R.id.listview_photo);
        gridView.setAdapter(mPhotoAdapter);

        mEmptyView = (TextView) rootView.findViewById(R.id.list_empty);
        mGridView = gridView;

        return rootView;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        Uri thumbs_uri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
        return new CursorLoader(getActivity(), thumbs_uri, THUMBNAIL_COLUMNS,
                null,null,  // read everything (all thumbnails)
                MediaStore.Images.Thumbnails._ID + " DESC");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        int antall = 0;
        if (cursor != null) 
            mPhotoAdapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {
        mPhotoAdapter.swapCursor(null);
    }

}

PhotoAdapter.java

public class PhotoAdapter extends CursorAdapter {

    public PhotoAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = LayoutInflater.from(context).inflate(R.layout.grid_item_gallery, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        view.setTag(viewHolder);
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ViewHolder viewHolder = (ViewHolder) view.getTag();

        long imgId = cursor.getLong(PhotoFragment.COL_THUMB_ID);

        String thumbData = cursor.getString(PhotoFragment.COL_THUMB_DATA);
        Bitmap thumbBitmap = BitmapFactory.decodeFile(thumbData);
        viewHolder.iconView.setImageBitmap(thumbBitmap);
        viewHolder.lbl.setText("Photo " + imgId);
    }

    public static class ViewHolder {
        public final ImageView iconView;
        public final TextView lbl;

        public ViewHolder(View view) {
            iconView = (ImageView) view.findViewById(R.id.grid_item_photo);
            lbl = (TextView) view.findViewById(R.id.grid_item_label);
        }
    }
}

我认为一个解决方案是在 xml 文件

的 ImageView 中设置 android:layout_height="sizeThatYouLike"