- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在新版本的 gmail 上,有一个很酷的 imageView,可以在其中显示多个联系人图像(链接 here 例如)。
例如,如果有人给我发了一封电子邮件,我只能看到他的图片:
#######
# #
# A #
# #
#######
如果我回复了他,我可以在它旁边看到我的图像,但是我的图像和他的图像都减半并共享 imageView 的相同空间(我认为两者都有 scaleType 作为中心裁剪):
#######
# # #
# A# B#
# # #
#######
如果另一个人加入了对话,它可能看起来像这样:
#######
# # B#
# A####
# # C#
#######
如果另一个人加入了,它可能看起来像这样:
#######
# A# C#
#######
# B# D#
#######
我不确定项目的顺序(和规则,所以这里的一切都是我的猜测),以及当更多人加入时会发生什么。
重要的是我想知道如何实现这一目标。
有人知道解决这个问题的方法吗?他们是怎么做到的?使用了哪个 View ?
这肯定是一个自定义 View ,但最好的方法是什么?一种可能最有效且不使用大量内存的方法......
我什至可能想让最终图像变成圆形,因此处理位图而不是 imageView 可能更好...
我什至不确定如何调用这样的 View 。我想到了“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 在他们的应用中使用了什么?
编辑:我已经提出了一些可能的解决方案,对于每一个我都写了这个线程的答案。我不确定哪个最好,所以我把它们都贴出来了。我想每个人都有自己的优点和缺点。
我目前的解决方案都没有像我提供的那样处理位图,但它们非常直观......
我仍然希望就您认为应该如何完成这项工作提供一些建议。
最佳答案
我称之为解决方案:
它使用 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;
}
}
}
马赛克 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>
属性.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>
关于android - "Mosaic"(拆分)图像 - Gmail 的字母样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17315491/
只是出于好奇,我想知道gmail是如何做到的。查看页面源代码后,您看不到任何链接、onclick 方法和 javascript。我知道他们隐藏了 javascript,但页面仍然知道有点击。是否有一个
最近谷歌宣布,出于安全目的,Gmail 将使用代理加载外部图像。这导致我的应用程序在 Gmail 中显示图像时出现问题。 Gmail图片元素检查: https://ci5.googleusercont
我想将节点脚本作为 cronjob 运行,它使用 Gmail 的 API 来轮询我拥有的 gmail 帐户。 我关注 these quickstart instructions : 我被困在第一步。在
如果您在 Gmail 上处于非事件状态,则通过一段时间不移动鼠标,您的聊天状态会更改为橙色,这意味着空闲。但是当您再次开始移动鼠标时,它会变回绿色,表示处于事件状态。它如何知道您何时移动鼠标? 最佳答
您知道,当您加载 GMail 时,左侧会显示“撰写邮件”、“收件箱”、“已发送邮件”等吗?我在页面源代码中搜索了“撰写邮件”,但一无所获。 最佳答案 Gmail 界面使用 JavaScript 动态加
我正在创建一个函数,使用 Google 的 API 从一个人的 gmail 帐户导入联系人。但是我知道许多企业注册 Google 是为了拥有更专业的域名(例如 some_name@bislr.com)
我可以通过桌面应用程序使用 Gmail API 成功读取我的收件箱内容。但是,当我尝试阅读其他人的 gmail 收件箱时,我收到 Delegation denied 异常? 所以我的问题是,Gmail
我已经读到我可以使用 gmail atom 提要从谷歌创建的“内置”标签中获取邮件。 但是当我尝试从“已读”标签获取邮件时,使用 https://mail.google.com/mail/feed/a
通过 Gmail API 发送到 Gmail 地址的邮件在 Gmail 中被标记为“小心处理此邮件。它包含通常用于窃取个人信息的内容。” 该消息基本上只是说测试。并且通过 Gmail SMTP 发送的
编辑 :解决下面的第一条评论,为清楚起见,这不是代码问题。问题很简单: 我应该在新 Gmail UI 的 URI 查询字符串中输入什么来查看 Gmail API 创建的草稿邮件? 尽管这并不是一个真正
我是谷歌产品的新手。我打算开始在 gmail 中添加一些东西。使用类似于 Add on 的 Add on 或 chrome Gmail Extension 更好吗?如果是add-on,我们不能直接在s
使用标准查询格式时,Gmail api 和 Gmail Web ui 的结果有所不同,如下所述 - https://support.google.com/mail/answer/7190 . 该问题专
我正在尝试创建一个 PHP 应用程序,它将自动设置用户的电子邮件签名。这部分有效,我可以为用户设置签名。 我的问题是我在 SendAs 设置中找不到任何选项,该选项将禁用 GMail 中签名前插入的两
我的电子邮件标记通过了电子邮件标记测试器,我尝试了 JSON-LD 和微数据,但无论如何 - 我只是看不到标记在 Gmail (iOS) 客户端中的任何效果。 即使是 Google 自己文档中的基本示
我目前正在使用 Gmail 实验室功能 - canned responses.我有很多这样的预设回复并使用 their menu找到合适的,证明是耗时的。通过以下方式找到预设响应会更容易: 将预设回复
请问是否可以在我的 Gmail 状态中发布倒计时? 像“01:44:15:23”及其不断递减。 最佳答案 发现一个好 article to share : Google Talk 使用 XMPP 那么
我开发了一个上下文小工具并将其安装在我的域中。它在我的域中运行良好,但在我的域之外无法正常工作。如何在我的域外访问我的小工具? 最佳答案 您指的是您的 Google Apps 域吗?根据 Google
我在 this guide 之后配置了推送通知并在调用 watch 时端点我得到大约一周的到期时间。 在此期间,我希望收到有关我已配置的 Pub/Sub 主题的通知,而无需调用 watch。在到期日期
是否有可以在 gmail 中捕获的 API 或事件,以便我可以启动工作流甚至触发 python 脚本。 我正在尝试自动化一项工作,该工作将从已到达 gmail 的电子邮件中提取 csv 附件。然后它会
为什么网络版的 Gmail 会在不使用 = 标记中断位置的情况下对邮件内容进行换行,这使得电子邮件处理变得非常困难: 查看gmail发送的原始邮件内容: 这封由 Mac OS X Mail 发送的邮件
我是一名优秀的程序员,十分优秀!