在新版本的gmail上,有一个很酷的imageView,可以在其中显示多个联系人图片(例如链接here)。
例如,如果有人给我发了一封电子邮件,我只会看到他的图片:
#######
# #
# A #
# #
#######
如果我回复了他,我可以在旁边看到我的图像,但是我的图像和他的图像都减半并且共享imageView的相同空间(我认为两者都有scaleType作为中心裁剪):< / p>
#######
# # #
# A# B#
# # #
#######
如果其他人加入了对话,则可能如下所示:
#######
# # B#
# A####
# # C#
#######
如果另一个加入,它可能看起来像这样:
#######
# A# C#
#######
# B# D#
#######
我不确定项目的顺序(和规则,所以这里的所有内容都是我的猜测),以及当更多人加入时会发生什么。
重要的是我想知道如何实现这一点。
有没有人知道这方面的解决方案?他们是怎么做到的?使用了哪种观点?
这肯定是一种自定义视图,但最好的方法是什么?这种方式可能效率最高,并且不会占用大量内存......
我甚至可能想要将最终图像舍入,因此处理位图而不是图像视图可能会更好......
我甚至不确定如何称呼这样的观点。我想到了“CollageView”或“MosaicView”。
为了说清楚,我认为应该使用下一个API处理这样的问题:
public static Bitmap createMosaicOfBitmaps(int targetWidth,int targetHeight,ArrayList<Bitmap> imagesToShow)
或者,如果位图可能占用太多内存,我们可以使用类似:
public static Bitmap createMosaicOfBitmaps(int targetWidth,int targetHeight,ArrayList<LazyBitmap> imagesToShow)
/**interface for lazy loading of a bitmap, while downscaling the bitmap to the needed size*/
public interface LazyBitmap{
public getBitmap(int width,int height);
}
我提出了两个解决方案,每个都有自己的优点和缺点,但我仍然需要对最终结果执行特殊效果(特别是圆角,但也许其他的东西),这是我的东西不知道该怎么做。
任何人都可以帮忙吗?你认为谷歌在他们的应用上使用了什么?
我目前的解决方案都没有像我提供的那样处理位图,但它们非常直观......
我仍然希望就你应该如何做到这一点提出一些建议。
答案 0 :(得分:4)
这是我称之为的解决方案:
它使用XML来设置mosaicView的外观。仍然没有按照我的计划,但它可能会帮助一些需要这样的东西并能够按照他们想要的方式改变它的人。
我添加的是添加自定义分隔符的功能(为此使用来自actionBarSherlock的IcsLinearLayout)。当然,你可以添加你想要的任何东西......
这是代码:
public class MosaicView extends FrameLayout {
public static final int SHOW_DIVIDER_NONE = 0;
public static final int SHOW_DIVIDER_OUTER = 0x01;
public static final int SHOW_DIVIDER_INNER = 0x02;
private ImageView mTopLeftImageView, mTopRightImageView, mBottomRightImageView, mBottomLeftImageView;
private IcsLinearLayout mLeftContainer, mRightContainer, mMainContainer;
private int mShowDivider;
private Drawable mHorizontalDividerDrawable;
private Drawable mVerticalDividerDrawable;
public MosaicView(final Context context) {
super(context);
init(context, null, 0);
}
public MosaicView(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public MosaicView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(final Context context, final AttributeSet attrs, final int defStyle) {
removeAllViews();
final LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.mosaic_view, this, true);
mTopLeftImageView = (ImageView) findViewById(R.id.mosaicView__topLeftImageView);
mTopRightImageView = (ImageView) findViewById(R.id.mosaicView__topRightImageView);
mBottomLeftImageView = (ImageView) findViewById(R.id.mosaicView__bottomLeftImageView);
mBottomRightImageView = (ImageView) findViewById(R.id.mosaicView__bottomRightImageView);
mLeftContainer = (IcsLinearLayout) findViewById(R.id.mosaicView__leftContainer);
mRightContainer = (IcsLinearLayout) findViewById(R.id.mosaicView__rightContainer);
mMainContainer = (IcsLinearLayout) findViewById(R.id.mosaicView__mainContainer);
//
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MosaicView, defStyle, 0);
final int attributeCount = a.getIndexCount();
for (int i = 0; i < attributeCount; i++) {
final int curAttr = a.getIndex(i);
switch (curAttr) {
case R.styleable.MosaicView_mosaicVerticalDividerDrawable:
setVerticalDividerDrawable(a.getDrawable(curAttr));
break;
case R.styleable.MosaicView_mosaicHorizontalDividerDrawable:
setHorizontalDividerDrawable(a.getDrawable(curAttr));
break;
case R.styleable.MosaicView_mosaicShowDividers:
setShowDivider(a.getInt(curAttr, SHOW_DIVIDER_NONE));
break;
}
}
a.recycle();
//
if (!isInEditMode())
resetAllImageViews();
else {
final ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>();
for (int i = 0; i < 4; ++i)
bitmaps.add(BitmapFactory.decodeResource(getResources(), android.R.drawable.sym_def_app_icon));
setImages(bitmaps);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void setVerticalDividerDrawable(final Drawable drawable) {
mVerticalDividerDrawable = drawable;
mMainContainer.setDividerDrawable(drawable);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void setHorizontalDividerDrawable(final Drawable drawable) {
mHorizontalDividerDrawable = drawable;
mLeftContainer.setDividerDrawable(drawable);
mRightContainer.setDividerDrawable(drawable);
}
public Drawable getVerticalDividerDrawable() {
return this.mVerticalDividerDrawable;
}
public Drawable getHorizontalDividerDrawable() {
return this.mHorizontalDividerDrawable;
}
public int getShowDivider() {
return this.mShowDivider;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void setShowDivider(final int dividers) {
mShowDivider = dividers;
int containersDividers = IcsLinearLayout.SHOW_DIVIDER_NONE;
if ((dividers & SHOW_DIVIDER_INNER) != 0)
containersDividers |= IcsLinearLayout.SHOW_DIVIDER_MIDDLE;
if ((dividers & SHOW_DIVIDER_OUTER) != 0)
containersDividers |= IcsLinearLayout.SHOW_DIVIDER_END | IcsLinearLayout.SHOW_DIVIDER_BEGINNING;
mLeftContainer.setShowDividers(containersDividers);
mRightContainer.setShowDividers(containersDividers);
mMainContainer.setShowDividers(containersDividers);
}
private void resetAllImageViews() {
mTopLeftImageView.setImageResource(0);
mTopRightImageView.setImageResource(0);
mBottomLeftImageView.setImageResource(0);
mBottomRightImageView.setImageResource(0);
mTopLeftImageView.setVisibility(View.GONE);
mTopRightImageView.setVisibility(View.GONE);
mBottomLeftImageView.setVisibility(View.GONE);
mBottomRightImageView.setVisibility(View.GONE);
mLeftContainer.setVisibility(View.GONE);
mRightContainer.setVisibility(View.GONE);
}
public void setImages(final ArrayList<Bitmap> images) {
resetAllImageViews();
if (images == null || images.size() == 0)
return;
switch (images.size()) {
case 1:
mTopLeftImageView.setImageBitmap(images.get(0));
mTopLeftImageView.setVisibility(View.VISIBLE);
mLeftContainer.setVisibility(View.VISIBLE);
break;
case 2:
mTopLeftImageView.setImageBitmap(images.get(0));
mTopRightImageView.setImageBitmap(images.get(1));
mTopLeftImageView.setVisibility(View.VISIBLE);
mTopRightImageView.setVisibility(View.VISIBLE);
mLeftContainer.setVisibility(View.VISIBLE);
mRightContainer.setVisibility(View.VISIBLE);
break;
case 3:
mTopLeftImageView.setImageBitmap(images.get(0));
mTopRightImageView.setImageBitmap(images.get(1));
mBottomRightImageView.setImageBitmap(images.get(2));
mBottomRightImageView.setVisibility(View.VISIBLE);
mTopLeftImageView.setVisibility(View.VISIBLE);
mTopRightImageView.setVisibility(View.VISIBLE);
mLeftContainer.setVisibility(View.VISIBLE);
mRightContainer.setVisibility(View.VISIBLE);
break;
default:
// TODO handle case of more than 4 images
case 4:
mTopLeftImageView.setImageBitmap(images.get(0));
mTopRightImageView.setImageBitmap(images.get(1));
mBottomRightImageView.setImageBitmap(images.get(2));
mBottomLeftImageView.setImageBitmap(images.get(3));
mBottomLeftImageView.setVisibility(View.VISIBLE);
mBottomRightImageView.setVisibility(View.VISIBLE);
mTopLeftImageView.setVisibility(View.VISIBLE);
mTopRightImageView.setVisibility(View.VISIBLE);
mLeftContainer.setVisibility(View.VISIBLE);
mRightContainer.setVisibility(View.VISIBLE);
break;
}
}
}
mosaic_view.xml:
<com.actionbarsherlock.internal.widget.IcsLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mosaicView__mainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity" >
<com.actionbarsherlock.internal.widget.IcsLinearLayout
android:id="@+id/mosaicView__leftContainer"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
<ImageView
android:id="@+id/mosaicView__topLeftImageView"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@android:drawable/sym_def_app_icon" />
<ImageView
android:id="@+id/mosaicView__bottomLeftImageView"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@android:drawable/sym_def_app_icon" />
</com.actionbarsherlock.internal.widget.IcsLinearLayout>
<com.actionbarsherlock.internal.widget.IcsLinearLayout
android:id="@+id/mosaicView__rightContainer"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
<ImageView
android:id="@+id/mosaicView__topRightImageView"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@android:drawable/sym_def_app_icon" />
<ImageView
android:id="@+id/mosaicView__bottomRightImageView"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@android:drawable/sym_def_app_icon" />
</com.actionbarsherlock.internal.widget.IcsLinearLayout>
</com.actionbarsherlock.internal.widget.IcsLinearLayout>
attr.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<declare-styleable name="MosaicView">
<attr name="mosaicVerticalDividerDrawable" format="reference" />
<attr name="mosaicHorizontalDividerDrawable" format="reference" />
<attr name="mosaicShowDividers">
<flag name="none" value="0x00" />
<flag name="outer" value="0x01" />
<flag name="inner" value="0x02" />
</attr>
</declare-styleable>
</resources>
答案 1 :(得分:3)
这是我想要致电的解决方案
遗憾的是,它使用了多个imageView,并且没有最终的位图。
请,如果有人知道显示图像的好方法,请发布。
这是代码:
public class MosaicView extends ViewGroup {
private ArrayList<Bitmap> mImages;
private ImageView[] mImageViews;
public MosaicView(final Context context) {
super(context);
}
public MosaicView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public MosaicView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
public void setImages(final ArrayList<Bitmap> images) {
this.mImages = images;
removeAllViews();
mImageViews = new ImageView[Math.min(4, mImages.size())];
for (int i = 0; i < mImageViews.length; ++i) {
ImageView imageView;
imageView = mImageViews[i] = new ImageView(getContext());
imageView.setImageBitmap(mImages.get(i));
imageView.setScaleType(ScaleType.CENTER_CROP);
addView(mImageViews[i]);
}
invalidate();
}
@Override
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
if (!changed)
return;
final int width = r - l;
final int height = b - t;
if (mImageViews != null)
switch (mImageViews.length) {
case 0:
break;
case 1:
// all area
mImageViews[0].layout(0, 0, width, height);
break;
case 2:
// left
mImageViews[0].layout(0, 0, width / 2, height);
// right
mImageViews[1].layout(width / 2, 0, width, height);
break;
case 3:
// left
mImageViews[0].layout(0, 0, width / 2, height);
// right top
mImageViews[1].layout(width / 2, 0, width, height / 2);
// right bottom
mImageViews[2].layout(width / 2, height / 2, width, height);
break;
default:
// TODO think what should be done when more than 4 items should be shown
case 4:
// left top
mImageViews[0].layout(0, 0, width / 2, height / 2);
// right top
mImageViews[1].layout(width / 2, 0, width, height / 2);
// right bottom
mImageViews[2].layout(width / 2, height / 2, width, height);
// left bottom
mImageViews[3].layout(0, height / 2, width / 2, height);
break;
}
}
}
答案 2 :(得分:2)
我建议你延长ViewGroup
,让你的孩子像你想要的那样安排在街区。通过这样做我实现了类似的东西。您可以指定参数,这些参数将根据每个块中的图像数量确定布局。您的父母将指定您孩子的大小和位置。因此,例如,如果您要在父级中显示2个项目,则父级将看到该项并测量一个子项的块宽度的一半而另一个子项的另一半用于另一个子项,然后父项将定位子项以便它们显示正确。
对于您的孩子,您可以扩展ImageView
并使用抽样位图填充它。这将减少内存使用量,您将可以在父级中使用多个图像块。如果您的图片已下载,我建议您创建AsyncTask
,为您完成所有工作,然后在完成抽样后更新ImageView
Bitmap
。在ImageView
中使用回收时,您还可以使用此任务将图片加载到ListView
。当在父母中执行onMeasure
时,您孩子的大小显然将由父母确定。
然后,您可以使用您创建的自定义视图并在ListView中实现它以获得所需的效果
-----编辑-----
Here是我实施的控件的屏幕截图。这不完全相同,但它具有相同的方法和原则。在这个控件中,我的父(全屏)是包含图像的小块,我的孩子是(彩色块)是你的图像。现在,在您的孩子中,您可以做任何事情来达到预期的效果。您可以对每个孩子实施onTouch
个事件,为每个孩子添加动画等。如果正确实现父子结构,可能性是无穷无尽的。
这就是我在上面的示例屏幕截图中ViewGroup
父母中安排孩子的方式
@Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
int childCount = getChildCount();
final int childWidth = _viewWidth;
final int childHeight = _viewHeight;
final int hPadding = (int) _paddingW; //set horizontal padding
final int vPadding = (int) _paddingH; //set vertical padding
if (childCount > 0) {
int rowTop = 0;
int rowBottom = 1;
int columnCount = 1;
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
int childLeft = (columnCount != 1) ? (hPadding * columnCount) + (childWidth * (columnCount-1)) : hPadding;
int childRight = (columnCount != 1) ? (hPadding * columnCount) + childWidth * columnCount : hPadding + childWidth;
int childTop = (rowTop == 0) ? vPadding : vPadding + ((childHeight + vPadding) * rowTop);
int childBottom = (rowBottom == 1) ? vPadding + childHeight : (childHeight + vPadding) * rowBottom;
child.layout(childLeft, childTop, childRight, childBottom);
if (columnCount < BLOCK_COUNT) {
columnCount++;
} else {
rowTop++;
rowBottom++;
columnCount = 1;
}
}
}
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
int maxHeight = 0;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(desiredWidth, widthSize);
} else {
width = desiredWidth;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(desiredHeight, heightSize);
} else {
height = desiredHeight;
}
setMeasuredItemDimentions(width, height);
final int childWidth = _viewWidth;
final int childHeight = _viewHeight;
final int vPadding = (int) _paddingH; //set vertical padding
final int count = getChildCount();
int columnCount = 1;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
child.measure(childWidth, childHeight);
if (columnCount < BLOCK_COUNT) {
columnCount++;
} else {
maxHeight += childHeight + vPadding;
columnCount = 1;
}
}
if (count % BLOCK_COUNT != 0) maxHeight += childHeight + vPadding;
maxHeight += vPadding;
setMeasuredDimension(width, maxHeight);
}
此布局仅显示2列但行数无限,因此它不会像您希望的那样百分之百地工作,但您可以使用类似的方法。
这是我孩子的一个例子
public class Block extends ViewGroup {
private static final String TAG = Block.class.getSimpleName();
private String _text;
private State _state;
private Context _context;
private int _viewWidth;
private int _viewHeight;
private int _textSize;
public enum State {
GOOD, NEAR, PASSED;
}
public Block(Context context) {
super(context);
_context = context;
_textSize = 15;
TextView tx = new TextView(context);
tx.setTextColor(context.getResources().getColor(R.color.terminal_text_color));
tx.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tx.setGravity(Gravity.CENTER);
tx.setTypeface(null, Typeface.BOLD);
addView(tx);
TextView stateText = new TextView(context);
stateText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
stateText.setTextSize(18);
stateText.setGravity(Gravity.CENTER);
stateText.setTextColor(context.getResources().getColor(R.color.terminal_text_color));
stateText.setGravity(Gravity.CENTER);
addView(stateText);
}
@Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
int childCount = getChildCount();
final int childWidth = _viewWidth;
final int childHeight = _viewHeight;
if (childCount > 0) {
TextView child = (TextView) getChildAt(0);
int padding = (int) (childWidth * 0.05);
int childLeft = padding;
int childRight = childWidth - padding;
int childTop = padding;
int childBottom = (int) (childHeight * 0.5);
if (child != null) {
child.layout(childLeft, childTop, childRight, childBottom);
child.setText(_text);
child.setTextSize(_textSize);
}
TextView stateText = (TextView) getChildAt(1);
if (stateText != null) {
stateText.layout(padding, ((int) (childHeight * 0.75)), childWidth - padding, ((int) (childHeight * 0.95)));
if (stateText != null)
switch (_state) {
case GOOD:
stateText.setBackgroundColor(_context.getResources().getColor(R.color.google_green));
stateText.setText(_context.getResources().getString(R.string.bottom_bar_legend_good));
break;
case NEAR:
stateText.setBackgroundColor(_context.getResources().getColor(R.color.google_yellow));
stateText.setText(_context.getResources().getString(R.string.bottom_bar_legend_mild));
break;
case PASSED:
stateText.setBackgroundColor(_context.getResources().getColor(R.color.google_red));
stateText.setText(_context.getResources().getString(R.string.bottom_bar_legend_passed));
break;
}
}
}
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
_viewWidth = widthMeasureSpec;
_viewHeight = heightMeasureSpec;
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
int padding = (int) (widthMeasureSpec * 0.05);
TextView child = (TextView) getChildAt(0);
if (child != null) child.measure(widthMeasureSpec - ((int)(widthMeasureSpec * 0.1)), heightMeasureSpec - ((int)(widthMeasureSpec * 0.5)) - padding);
TextView childLayout = (TextView) getChildAt(1);
if (childLayout != null) childLayout.measure(widthMeasureSpec - ((int)(widthMeasureSpec * 0.1)), heightMeasureSpec);
}
}
我为我的孩子使用ViewGroup
,因为我的要求与您的要求不同,但您可以使用简单的ImageView
,因为您只想显示操作的位图。您可以使用this方法(正如您在评论中提到的那样)在子项中为您的位图提供圆角。
希望这有帮助
答案 3 :(得分:2)
这是我称之为的解决方案:
它从ImageView扩展,并覆盖其onDraw方法。它工作正常,但它有一些缺点,如果有人可以提高我会很高兴:
代码在这里:
public class MosaicView extends ImageView {
private ArrayList<Bitmap> mImages;
private ArrayList<Rect> mImagesRects;
private final Paint mPaint = new Paint();
private Rect mTopLeftRect, mLeftRect, mWholeRect, mRightRect, mTopRightRect, mBottomLeftRect, mBottomRightRect;
private boolean mIsDirty = false;
private final Rect mCenterCropRect = new Rect();
public MosaicView(final Context context) {
super(context);
}
public MosaicView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public MosaicView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
public void setImages(final ArrayList<Bitmap> images) {
this.mImages = images;
if (mImages == null)
mImagesRects = null;
else {
mImagesRects = new ArrayList<Rect>(images.size());
for (final Bitmap bitmap : images)
mImagesRects.add(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
}
mIsDirty = true;
invalidate();
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
final int width = getWidth();
final int height = getHeight();
if (mIsDirty) {
mIsDirty = false;
mTopLeftRect = new Rect(0, 0, width / 2, height / 2);
mLeftRect = new Rect(0, 0, width / 2, height);
mWholeRect = new Rect(0, 0, width, height);
mRightRect = new Rect(width / 2, 0, width, height);
mTopRightRect = new Rect(width / 2, 0, width, height / 2);
mBottomLeftRect = new Rect(0, height / 2, width / 2, height);
mBottomRightRect = new Rect(width / 2, height / 2, width, height);
}
if (mImages == null)
return;
Bitmap b;
switch (mImages.size()) {
case 0:
break;
case 1:
b = mImages.get(0);
getCenterCropRect(mImagesRects.get(0), mWholeRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mWholeRect, mPaint);
break;
case 2:
b = mImages.get(0);
getCenterCropRect(mImagesRects.get(0), mLeftRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mLeftRect, mPaint);
b = mImages.get(1);
getCenterCropRect(mImagesRects.get(1), mRightRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mRightRect, mPaint);
break;
case 3:
b = mImages.get(0);
getCenterCropRect(mImagesRects.get(0), mLeftRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mLeftRect, mPaint);
b = mImages.get(1);
getCenterCropRect(mImagesRects.get(1), mTopRightRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mTopRightRect, mPaint);
b = mImages.get(2);
getCenterCropRect(mImagesRects.get(2), mBottomRightRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mBottomRightRect, mPaint);
break;
default:
case 4:
b = mImages.get(0);
getCenterCropRect(mImagesRects.get(0), mTopLeftRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mTopLeftRect, mPaint);
b = mImages.get(1);
getCenterCropRect(mImagesRects.get(1), mTopRightRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mTopRightRect, mPaint);
b = mImages.get(2);
getCenterCropRect(mImagesRects.get(2), mBottomRightRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mBottomRightRect, mPaint);
b = mImages.get(3);
getCenterCropRect(mImagesRects.get(3), mBottomLeftRect, mCenterCropRect);
canvas.drawBitmap(b, mCenterCropRect, mBottomLeftRect, mPaint);
break;
}
}
private void getCenterCropRect(final Rect srcRect, final Rect limitRect, final Rect dstRect) {
final float scaleX = (float) srcRect.width() / limitRect.width();
final float scaleY = (float) srcRect.height() / limitRect.height();
if (scaleX >= scaleY) {
// image will fit in height, and truncate from the width
dstRect.top = srcRect.top;
dstRect.bottom = srcRect.bottom;
final float newWidth = limitRect.width() * scaleY;
dstRect.left = (int) (srcRect.width() / 2 - newWidth / 2);
dstRect.right = (int) (srcRect.width() / 2 + newWidth / 2);
} else {
// image will fit in width, and truncate from the height
dstRect.left = srcRect.left;
dstRect.right = srcRect.right;
final float newHeight = limitRect.height() * scaleX;
dstRect.top = (int) (srcRect.height() / 2 - newHeight / 2);
dstRect.bottom = (int) (srcRect.height() / 2 + newHeight / 2);
}
}
}