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"
我想在 GridView 中向用户展示设备上的所有缩略图,其中每个 "cell" 都是一个 ImageView。如果所有照片都是 横向 方向,这看起来不错:每个缩略图都是矩形并裁剪成相同大小(我假设这就是缩略图在设备上 generated/stored 的方式)。
但是,垂直 方向的照片(和缩略图)会导致问题。高缩略图拉伸了单元格,使 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"