我正在尝试将照片设为Activity
的背景。我希望背景为a full screen image (no borders)。
因为我希望图像能够在没有拉伸/挤压的情况下填充整个活动的背景(即X和Y的不成比例的缩放),我不介意是否必须裁剪照片,我正在使用{{1} } RelativeLayout
(ImageView
),其余部分由android:scaleType="centerCrop"
及其子项组成。
ScrollView
问题是布局的其余部分有一些<!-- Tried this with a FrameLayout as well... -->
<RelativeLayout>
<!-- Background -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<!-- Form -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView>
<LinearLayout>
...
<EditText/>
</LinearLayout>
</ScrollView>
</LinearLayout>
</RelativeLayout>
视图,当软键盘出现时,ImageView会重新调整大小。无论软键盘是否可见,我都希望背景保持不变。
我已经看到plenty of questions关于ImageViews重新调整大小但是(imo)没有令人满意的答案。其中大多数只是设置EditText
- 这并不总是实用的,特别是如果您希望用户能够滚动活动 - 或者使用不会裁剪图像的android:windowSoftInputMode="adjustPan"
。
我设法对ImageView进行子类化并覆盖其getWindow().setBackgroundDrawable()
(请参阅我的答案:ImageView resizes when keyboard open),以便它可以强制固定高度&amp; width - 等于设备的屏幕尺寸 - 根据标志,但我想知道是否有更好的方法来实现我想要的结果。
所以,总而言之,我的问题是:如何将活动的背景设置为全屏照片
,缩放类型=“centerCrop”,以便照片均匀缩放(保持其宽高比),因此两个尺寸(宽度和高度)将等于或大于相应的尺寸观点;
不会调整大小;
解答:
我最后关注了@pskink的建议,并将onMeasure()
隐藏了(请参阅下面的回答)。我必须做一些调整,以确保BitmapDrawable
始终按照填充屏幕的方式进行缩放和裁剪。
这是我的最后一堂课,改编自他的答案:
BackgroundBitmapDrawable
然后只需创建一个public class BackgroundBitmapDrawable extends BitmapDrawable {
private Matrix mMatrix = new Matrix();
private int moldHeight;
boolean simpleMapping = false;
public BackgroundBitmapDrawable(Resources res, Bitmap bitmap) {
super(res, bitmap);
}
@Override
protected void onBoundsChange(Rect bounds) {
if (bounds.height() > moldHeight) {
moldHeight = bounds.height();
Bitmap b = getBitmap();
RectF src = new RectF(0, 0, b.getWidth(), b.getHeight());
RectF dst;
if (simpleMapping) {
dst = new RectF(bounds);
mMatrix.setRectToRect(src, dst, ScaleToFit.CENTER);
} else {
// Full Screen Image -> Always scale and center-crop in order to fill the screen
float dwidth = src.width();
float dheight = src.height();
float vwidth = bounds.width();
float vheight = bounds.height();
float scale;
float dx = 0, dy = 0;
if (dwidth * vheight > vwidth * dheight) {
scale = (float) vheight / (float) dheight;
dx = (vwidth - dwidth * scale) * 0.5f;
} else {
scale = (float) vwidth / (float) dwidth;
dy = (vheight - dheight * scale) * 0.5f;
}
mMatrix.setScale(scale, scale);
mMatrix.postTranslate(dx, dy);
}
}
}
@Override
public void draw(Canvas canvas) {
canvas.drawColor(0xaa00ff00);
canvas.drawBitmap(getBitmap(), mMatrix, null);
}
}
并将其设置为根视图的背景。
答案 0 :(得分:7)
试试这个LayerDrawable(res / drawable / backlayer.xml):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
>
<item>
<shape>
<solid android:color="#f00" />
</shape>
</item>
<item>
<bitmap
android:gravity="top" android:src="@drawable/back1">
</bitmap>
</item>
</layer-list>
并将其设置为顶级布局:android:background =“@ drawable / backlayer”
更新:尝试使用此BitmapDrawadle,将其设置为顶级布局(setBackgroundDrawable()),如果simpleMapping == true足够好,则可以删除“else”分支:
class D extends BitmapDrawable {
private Matrix mMatrix = new Matrix();
private int moldHeight;
public D(Resources res, Bitmap bitmap) {
super(res, bitmap);
}
@Override
protected void onBoundsChange(Rect bounds) {
if (bounds.height() > moldHeight) {
moldHeight = bounds.height();
Bitmap b = getBitmap();
RectF src = new RectF(0, 0, b.getWidth(), b.getHeight());
RectF dst;
// if simpleMapping is good enough then remove "else" branch and
// declare "dst" as:
// RectF dst = new RectF(bounds);
boolean simpleMapping = true;
if (simpleMapping) {
dst = new RectF(bounds);
} else {
float x = bounds.exactCenterX();
dst = new RectF(x, 0, x, bounds.height());
float scale = bounds.height() / src.height();
float dx = scale * src.width() / 2;
dst.inset(-dx, 0);
}
mMatrix.setRectToRect(src, dst, ScaleToFit.CENTER);
}
}
@Override
public void draw(Canvas canvas) {
canvas.drawColor(0xaa00ff00);
canvas.drawBitmap(getBitmap(), mMatrix, null);
}
}
答案 1 :(得分:0)
将所有内容放在FrameLayout中,第一个子视图将匹配它的父视图(frameLayout),然后根据需要配置背景,并在图像视图前放置您想要的任何内容(LinearLayout I)假设)
答案 2 :(得分:0)
在我搔了一会儿之后,这是我的“现在好”的解决方案。
共享可能对任何人都有用的示例XML。
<!-- RelativeLayout so that Views can overlap each other.
I believe a FrameLayout would work as well. -->
<RelativeLayout
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- I've put the ImageView inside
a ScrollView with android:fillViewport="true" and android:isScrollContainer="false" -->
<ScrollView
android:id="@+id/backgroundScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:isScrollContainer="false" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- The FullScreen, Center-Cropped Image Background -->
<ImageView
android:id="@+id/backgroundImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/background_image" />
</LinearLayout>
</ScrollView>
<!-- The rest of the Views, containing the data entry form... -->
<LinearLayout
android:id="@+id/form"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ScrollView
android:id="@+id/formScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" >
<!-- The "Form", with EditTexts, Checkboxes and whatnot... -->
</LinearLayout>
</ScrollView>
</LinearLayout>
</RelativeLayout>
通过这种布局,我完成了两件事:
formScrollView
,包含带有EditTexts的“表单”等,可以重新调整大小(我希望它)并在软键盘显示时滚动。
backgroundScrollView
包含ImageView,不会重新调整大小(因为android:isScrollContainer="false"
)并填充整个视口(android:fillViewport="true"
)。因此,无论键盘是否可见,背景都保持不变。
不是一个完美的解决方案,因为ImageView
在某种程度上会出现非常小的变化,但结果现在已经足够好了。如果有人知道更好的解决方案,请告诉我。
答案 3 :(得分:0)
答案中的解决方案是最好的,使用它:
Resources res = getActivity().getResources();
Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.some_image);
BackgroundBitmapDrawable background = new BackgroundBitmapDrawable(res, bitmap);
view.setBackgroundDrawable(background);
或
view.setBackground(background);
适用于API 16及更高版本。
答案 4 :(得分:0)
更改您的ScaleType
fn find_end(s: &str, i: usize) -> usize {
i + s[i..].chars().next().unwrap().len_utf8()
}
并在你的清单中
android:scaleType="FitXY"
答案 5 :(得分:-1)
在xml中创建一个ImageView。 将它放在Layout标签下面。 将translationZ设置为正值,例如10dp,将scaleType设置为centerCrop。