[英]How to have a Fullscreen Background Image (with center-crop) that doesn't Resize
我正在嘗試將照片設置為Activity
的背景。 我希望背景是一個全屏圖像(沒有邊框) 。
因為我希望圖像在沒有拉伸/擠壓的情況下填充整個活動的背景(即X和Y的不成比例的縮放),我不介意是否必須裁剪照片,我正在使用帶有ImageView
的RelativeLayout
(帶有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>
問題是布局的其余部分有一些EditText
視圖,當軟鍵盤出現時,ImageView會重新調整大小。 我希望背景保持不變,無論軟鍵盤是否可見。
我已經看到很多關於ImageViews重新調整大小的問題但是(imo)沒有令人滿意的答案。 其中大多數只是設置android:windowSoftInputMode="adjustPan"
- 這並不總是實用的,特別是如果你希望用戶能夠滾動活動 - 或使用getWindow().setBackgroundDrawable()
不裁剪圖像。
我設法將ImageView子類化並覆蓋其onMeasure()
(請參閱我的答案: ImageView在鍵盤打開時調整大小 )以便它可以強制固定的高度和寬度 - 等於設備的屏幕尺寸 - 根據標志但是我想知道是否有更好的方法來實現我想要的結果。
總而言之,我的問題是: 如何將活動的背景設置為全屏照片
使用scale type =“centerCrop”,使照片均勻縮放(保持其縱橫比),因此兩個尺寸(寬度和高度)將等於或大於視圖的相應尺寸;
彈出軟鍵盤時不會調整大小;
回答:
我最后關注了@pskink的建議並將子類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);
}
}
然后只需創建一個BackgroundBitmapDrawable
並將其設置為根視圖的背景。
試試這個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);
}
}
將所有內容放在FrameLayout中,第一個子圖像將與其父圖像(frameLayout)相匹配,並將其配置為您想要的背景,並在圖像視圖前放置您想要的任何內容(我猜想是LinearLayout)
抓了一會兒后,這是我的“現在好”的解決方案。
共享可能對任何人都有用的示例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
某種程度上的尺寸變化非常小,但結果現在已經足夠好了。 如果有人知道更好的解決方案,請告訴我。
答案中的解決方案是最好的,使用它:
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及以上版本。
更改您的ScaleType
android:scaleType="FitXY"
在你的清單中
<activity
android:name=".activity.MainActivity"
android:windowSoftInputMode="adjustPan|stateHidden" />
在xml中創建一個ImageView。 將它放在Layout標簽下面。 將translationZ設置為正值,例如10dp,將scaleType設置為centerCrop。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.