【发布时间】:2015-11-26 22:34:06
【问题描述】:
我又遇到了一个奇怪的android框架问题:
我有一个显示对象详细信息的活动。它被设计成看起来像一个“浮动”活动,这意味着它覆盖了MainActivity,并且可以通过从用户那里简单地向下滑动来消除。
截图
它是怎么做的(错了?)
因为将窗口背景设置为@android:color/transparent 会导致丑陋的副作用,所以我使用自定义的ImageView 作为背景(我由Chris Banes https://github.com/chrisbanes/philm/blob/master/app/src/main/java/app/philm/in/view/BackdropImageView.java 修改了这个):
public class BackdropImageView extends ImageView {
private static final int MIN_SCRIM_ALPHA = 0x00;
private static final int MAX_SCRIM_ALPHA = 0xFF;
private static final int SCRIM_ALPHA_DIFF = MAX_SCRIM_ALPHA - MIN_SCRIM_ALPHA;
private float mScrimDarkness;
private float factor;
private int mScrimColor = Color.BLACK;
private int mScrollOffset;
private int mImageOffset;
private final Paint mScrimPaint;
public BackdropImageView(Context context) {
super(context);
mScrimPaint = new Paint();
factor = 2;
}
public BackdropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mScrimPaint = new Paint();
factor = 2;
}
private void setScrollOffset(int offset) {
if (offset != mScrollOffset) {
mScrollOffset = offset;
mImageOffset = (int) (-offset / factor);
offsetTopAndBottom(offset - getTop());
ViewCompat.postInvalidateOnAnimation(this);
}
}
public void setFactor(float factor) {
this.factor = factor;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mScrollOffset != 0) {
offsetTopAndBottom(mScrollOffset - getTop());
}
}
public void setScrimColor(int scrimColor) {
if (mScrimColor != scrimColor) {
mScrimColor = scrimColor;
ViewCompat.postInvalidateOnAnimation(this);
}
}
public void setProgress(int offset, float scrim) {
mScrimDarkness = ScrollUtils.getFloat(scrim, 0, 1);
setScrollOffset(offset);
}
@Override
protected void onDraw(@NonNull Canvas canvas) {
// Update the scrim paint
mScrimPaint.setColor(ColorUtils.setAlphaComponent(mScrimColor,
MIN_SCRIM_ALPHA + (int) (SCRIM_ALPHA_DIFF * mScrimDarkness)));
if (mImageOffset != 0) {
canvas.save();
canvas.translate(0f, mImageOffset);
canvas.clipRect(0f, 0f, canvas.getWidth(), canvas.getHeight() + mImageOffset + 1);
super.onDraw(canvas);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mScrimPaint);
canvas.restore();
} else {
super.onDraw(canvas);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mScrimPaint);
}
}
}
当我启动 Activity 时,我会创建当前 Activity 的快照,然后将其保存到缓存中,并通过 Intent.putExtra(String key, String value); 传递它的路径:
public static Intent createOverlayActivity(Activity activity) {
Intent startIntent = new Intent(activity, OverlayActivity.class);
View root = activity.findViewById(android.R.id.content);
Rect clipRect = new Rect();
activity.getWindow().getDecorView()
.getWindowVisibleDisplayFrame(clipRect);
Bitmap bitmap = Bitmap.createBitmap(
root.getWidth(),
root.getHeight(),
Bitmap.Config.ARGB_8888
);
Canvas canvas = new Canvas(bitmap);
canvas.drawRGB(0xEE, 0xEE, 0xEE);
// Quick fix for status bar appearing in Lollipop and above
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
canvas.translate(0, -clipRect.top / 2);
canvas.clipRect(clipRect);
}
root.draw(canvas);
try {
File file = new File(activity.getCacheDir(), "background.jpg");
FileOutputStream stream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
stream.flush();
stream.close();
bitmap.recycle();
startIntent.putExtra("bgBitmap", file.getPath());
Log.d(TAG, "Rendered background image.");
} catch (IOException e) {
e.printStackTrace();
}
return startIntent;
}
在OverlayActivity 的onCreate() 中,我收到缓存文件的路径并将位图加载到ImageView:
Bitmap screenshot = BitmapFactory.decodeFile(getIntent().getStringExtra("bgBitmap"));
if (screenshot == null) {
throw new IllegalArgumentException("You have to provide a valid bitmap!");
}
/* BackdropImageView is an ImageView subclass allowing
* me to darken the image with a scrim using the slide offset value */
backdropImageView = new BackdropImageView(this);
backdropImageView.setId(android.R.id.background);
backdropImageView.setFactor(1.125f);
backdropImageView.setScrimColor(Color.BLACK);
backdropImageView.setImageBitmap(screenshot);
backdropImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
问题
如您在上面的屏幕截图中所见,它在运行 API 23 的设备上运行得相当不错,但在下面的设备上不。
此处显示的是活动滑入时的图像,直到完全被覆盖,但是当我再次向下滑动时,图像消失了,ImageView 仅显示为纯灰色:
更新
我发现问题必须隐藏在 BackdropImageView 类中的某个地方,因为简单的 ImageView 可以工作。
关于什么可能导致这个奇怪问题的任何想法?
提前致谢!
【问题讨论】:
-
您是否尝试在 Activity 的 onStart() 事件中添加以下行:
backdropImageView.setFactor(1.125f); backdropImageView.setScrimColor(Color.BLACK); backdropImageView.setImageBitmap(screenshot); backdropImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);? -
是的,我试过了。还是不行:(
标签: android android-intent android-activity bitmap imageview