1

新しいバージョンの gmail には、複数の連絡先画像を表示するクールな imageView があります (link here for example) 。

たとえば、誰かが私に電子メールを送った場合、私は彼の画像しか見ることができません:

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

彼に返信した場合、その横に自分の画像が表示されますが、私の画像と彼の画像の両方が半分になり、imageView の同じスペースを共有します (両方とも scaleType が中央のトリミングになっていると思います):

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

別の人が会話に参加している場合、次のようになります。

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

別のものが参加している場合は、次のようになります。

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

項目の順序 (およびルール、したがってここにあるものはすべて私の推測です) と、より多くの人が参加するとどうなるかについてはわかりません。

重要なことは、これを達成する方法を知りたいということです。

誰もこれに対する解決策を知っていますか? 彼らはどうやってそれをしたのですか?どのビューが使用されましたか?

それは間違いなくカスタムビューですが、それを行う最良の方法は何ですか? おそらく最も効率的で、多くのメモリを使用しない方法...

最終的な画像を丸くしたいかもしれないので、imageViewの代わりにビットマップを処理する方が良いかもしれません...

そのようなビューを呼び出す方法さえわかりません。「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);
}

私は2つの解決策を思いつきました.それぞれに長所と短所がありますが、最終結果に特殊効果を適用する必要があります(特に角を丸くしますが、他のことも可能です)。する方法を知っています。

誰でも助けてもらえますか?Google はアプリで何を使用していると思いますか?


編集: このスレッドへの回答を書いたそれぞれについて、いくつかの可能な解決策を考え出しました。どれが一番いいかわからないので全部載せました。それぞれに長所と短所があると思います。

私の現在のソリューションは、私が提供したようにビットマップを処理しませんが、非常に直感的です...

あなたの意見でこれをどのように行うべきかについて、私はまだいくつかのアドバイスを望んでいます.

4

4 に答える 4

4

これが私が呼ぶ解決策です:

XML ソリューション

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

}

モザイク ビュー.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>
于 2013-06-27T19:42:14.913 に答える