“马赛克"(拆分的)图像 - Gmail 的字母样式 [英] "Mosaic" (splitted) images - Gmail's letters style

查看:46
本文介绍了“马赛克"(拆分的)图像 - Gmail 的字母样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在新版本的 gmail 中,有一个很酷的 imageView,其中显示了多个联系人图像(链接 这里 例如).

On the new versions of gmail, there is a cool imageView that shows multiple contacts images in it (link here for example) .

例如,如果有人给我发了一封电子邮件,我只会看到他的图片:

for example, if someone has sent me an email, i only see his image:

#######
#     #
#  A  #
#     #
#######

如果我回复了他,我可以在旁边看到我的图像,但我的图像和他的图像都减半并共享 imageView 的相同空间(我认为两者都有 scaleType 作为中心裁剪):

if i've replied to him, i can see my image next to it, but both my image and his are halved and share the same space of the imageView (and i think both have scaleType to be center crop) :

#######
#  #  #
# A# B#
#  #  #
#######

如果另一个人加入了对话,它可能如下所示:

if another person has joined the conversation, it could look like this:

#######
#  # B#
# A####
#  # C#
#######

如果另一个人加入了,它可能看起来像这样:

and if another one has joined, it could look like this:

#######
# A# C#
#######
# B# D#
#######

我不确定项目的顺序(和规则,所以这里的一切都是我的猜测),以及当更多人加入时会发生什么.

i'm not sure about the order of the items (and the rules, so everything here is my guess) , and what happens when more people are joining.

重要的是我想知道如何做到这一点.

the important thing is that i want to know how to achieve this .

有人知道这个的解决方案吗?他们是怎么做到的?使用了哪个视图?

does anyone know of a solution for this? how they did it? which view was used?

这当然是一个自定义视图,但最好的方法是什么?一种可能是最有效且不占用大量内存的方式...

it's most certainly a custom view, but what's the best way to do it? a way that is probably most efficient and doesn't use a lot of memory ...

我什至可能想让最终的图像变圆,所以处理位图而不是 imageView 可能会更好...

i might even want to make the final image to be rounded, so it might be better to handle bitmaps instead of an imageView...

我什至不确定如何调用这样的视图.我想到了拼贴视图"或马赛克视图".

i'm not even sure how to call such a view. i've thought of a "CollageView" or a "MosaicView" .

为了清楚起见,我认为应该使用下一个 API 来处理这样的问题:

just to make it clear, i think that such a problem should be handled using the next API :

public static Bitmap createMosaicOfBitmaps(int targetWidth,int targetHeight,ArrayList<Bitmap> imagesToShow)

或者,如果位图可能占用太多内存,我们可以使用类似的东西:

or, if the bitmaps might take too much memory , we could use something like:

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);
}

我提出了 2 个解决方案,每个都有自己的优点和缺点,但我仍然需要对最终结果执行特殊效果(尤其是圆角,但也许还有其他东西),这是我不知道该怎么做.

i've come up with 2 solutions, each has its own advantages and disadvantages, but i still need to perform special effects on the final result (especially rounded corners, but maybe other things too ), and this is something that i don't know how to do.

有人可以帮忙吗?你认为谷歌在他们的应用上使用了什么?

can anyone please help? what do you think google has used on their app ?

我想出了一些可能的解决方案,对于每一个我都写了这个线程的答案.我不确定哪个是最好的,所以我把它们都贴出来了.我想每个人都有自己的优点和缺点.

i've come up with a few possible solutions, for each i've written an answer to this thread. i'm not sure which is the best so i've posted them all . i guess each has its own advantages and disadvantages.

我目前的解决方案都没有像我提供的那样处理位图,但它们非常直观......

none of my current solutions handles a bitmap as i've offered, but they are quite intuitive...

我仍然希望就您认为应该如何做到这一点提供一些建议.

i would still wish for some advice as to how this should be done in your opinion.

推荐答案

我称之为解决方案:

它使用 XML 来设置镶嵌视图的外观.仍然不像我计划的那样,但它可能会帮助一些需要这样的东西并能够按照他们想要的方式改变它的人.

it uses XML to set how the mosaicView would look like. still not as i've planned, but it might help some people who need such a thing and be able to change it the way they want.

我添加的是添加自定义分隔线的功能(为此使用 actionBarSherlock 中的 IcsLinearLayout).当然,你可以添加任何你想要的......

what i've added is the ability to add custom dividers (uses IcsLinearLayout from actionBarSherlock for this) . of course, you can add whatever you wish...

代码如下:

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:

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>

这篇关于“马赛克"(拆分的)图像 - Gmail 的字母样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆