写真をActivity
の背景として設定しようとしています。背景を フルスクリーン画像(境界線なし) にします。
画像をストレッチ/スクイーズせずにアクティビティの背景全体に塗りつぶしたいので(つまり、XとYの不均衡なスケーリング)、写真をトリミングする必要があるかどうかは気にしないので、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>
問題は、レイアウトの残りの部分にEditText
ビューがいくつかあり、ソフトキーボードが表示されると、ImageViewのサイズが変更されることです。ソフトキーボードが表示されているかどうかに関係なく、背景は同じままにしておきたいです。
私は たくさんの質問 on SO 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);
}
}
答えの解決策は、それを使用するのに最適です:
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);
aPI16以降の場合。
しばらく頭をかいた後、これは私の「今のところ良い」解決策でした。
誰にとっても役立つかもしれないサンプル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>
このレイアウトで、私は2つのことを達成します。
EditTextsなどを含む「フォーム」を含むformScrollView
は、ソフトキーボードが表示されたときにサイズが変更され(必要に応じて)スクロール可能になります。
ImageViewを含むbackgroundScrollView
は、サイズが変更されません( Android:isScrollContainer="false"
)そしてビューポート全体を埋めます(Android:fillViewport="true"
)。したがって、キーボードが表示されているかどうかに関係なく、背景は同じままです。
ImageView
はサイズのばらつきが非常に小さいため、完全な解決策ではありませんが、今のところ結果は十分です。誰かがより良い解決策を知っているなら、私に知らせてください。
すべてをFrameLayoutに配置し、最初の子でその親(frameLayout)に一致するimageviewを配置し、背景に合わせて構成し、画像ビューの前に必要なものを配置します(LinearLayoutだと思います)
ScaleTypeを変更します
Android:scaleType="FitXY"
そしてあなたのマニフェストで
<activity
Android:name=".activity.MainActivity"
Android:windowSoftInputMode="adjustPan|stateHidden" />