web-dev-qa-db-ja.com

ソフトウェアキーボードは、Androidで背景画像のサイズを変更します

ソフトウェアキーボードが表示されるたびに、背景画像のサイズが変更されます。以下のスクリーンショットを参照してください。

ご覧のとおり、背景は少し絞られています。誰でも背景のサイズが変更される理由を知ることができますか?

私のレイアウトは次のとおりです。

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:background="@drawable/page_bg"
    Android:isScrollContainer="false"
>
    <LinearLayout Android:layout_height="wrap_content"
        Android:orientation="horizontal"
        Android:layout_width="fill_parent"
    >
        <EditText Android:id="@+id/CatName"
            Android:layout_width="fill_parent"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:inputType="textCapSentences"
            Android:lines="1"
        />
        <Button Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="@string/save"
            Android:onClick="saveCat"
        />
    </LinearLayout>
    <ImageButton
        Android:id="@+id/add_totalk"
        Android:layout_height="wrap_content"
        Android:layout_width="wrap_content"
        Android:background="@null"
        Android:src="@drawable/add_small"
        Android:scaleType="center"
        Android:onClick="createToTalk"
        Android:layout_marginTop="5dp"
    />
</LinearLayout>
122
Andreas Wong

OKを使用して修正しました

Android:windowSoftInputMode="stateVisible|adjustPan"

manifestファイルの<Activity >タグ内のエントリ。アクティビティ内にScrollViewを持っていることが原因だと思います。

182
Andreas Wong

背景画像付きのチャットアプリ、チャット画面の開発中に、同じ問題に直面しました。 _Android:windowSoftInputMode="adjustResize"_は、ソフトキーボードが表示され、ソフトキーボードを調整するために「adjustPan」がレイアウト全体をシフトした後、使用可能なスペースに合うように背景画像を圧縮しました。この問題の解決策は、アクティビティXML内にレイアウトの背景ではなくウィンドウの背景を設定することでした。アクティビティでgetWindow().setBackgroundDrawable()を使用します。

102
parulb

この種の問題を回避するための最良の解決策は次のとおりです。

ステップ1:スタイルを作成する

<style name="ChatBackground" parent="AppBaseTheme">
    <item name="Android:windowBackground">@drawable/bg_chat</item>
</style>

ステップ2:AndroidManifestファイルにアクティビティスタイルを設定します

<activity
    Android:name=".Chat"
    Android:screenOrientation="portrait"
    Android:theme="@style/ChatBackground" >
33
Ahsanwarsi

Android:windowSoftInputMode = "adjustPan"を使用すると、画面全体が最上部に移動する(topにシフトする)ため、ユーザーエクスペリエンスが低下します。したがって、以下が最良の回答の1つです。

私は同じ問題を抱えていますが、その後、@ Gemからの素晴らしい答えを見つけました

マニフェスト内

Android:windowSoftInputMode="adjustResize|stateAlwaysHidden"

XMLで

ここに背景を設定せず、ScrollViewの下にビューを保持します

Javaの場合

背景をウィンドウに設定する必要があります。

    getWindow().setBackgroundDrawableResource(R.drawable.bg_wood) ;

@Gemに感謝します。

27
Joseph Mekwan

加えて...

アクティビティのリストビューがある場合、リストビューのプロパティにこのAndroid:isScrollContainer="false"を追加する必要があります...

アクティビティでマニフェストxmlにAndroid:windowSoftInputMode="adjustPan"を追加することを忘れないでください...

レイアウトのスクロール可能なビューでAndroid:windowSoftInputMode="adjustUnspecified"を使用している場合、ソフトキーボードによって背景のサイズが変更されます...

背景のサイズ変更を防ぐために「adjustPan」値を使用するとよいでしょう...

14
BolbazarMarme

誰かがadjustResize動作を必要とし、ImageViewのサイズを変更したくない場合は、別の回避策があります。

ImageViewの中にScrollViewを入れるだけで、ScrollView.fillViewport = trueRelativeLayoutになります。

<ScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fillViewport="true">

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <FrameLayout
            Android:layout_width="100dp"
            Android:layout_height="100dp">

            <ImageView
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:scaleType="fitXY"
                Android:src="@drawable/gift_checked" />

        </FrameLayout>
    </RelativeLayout>
</ScrollView>
7
konmik

アプリの作業中に主な問題が発生しました。最初に、@ parulbが提供するメソッドを使用して問題を解決します。彼に感謝します。しかし、後で、背景画像がアクションバー(およびステータスバー)によって部分的に非表示になっていることに気付きました。この小さな問題は@ zgc7009によって既に提案されており、1年半前に@parulbの回答の下でコメントしましたが、誰も返信しませんでした。

方法を見つけるために丸1日働きましたが、幸いなことに、少なくとも今は携帯電話でこの問題を完全に解決できます。

まず、背景画像の上部にパディングを追加するために、ドロアブルフォルダーにレイヤーリストリソースが必要です。

<!-- my_background.xml -->
<?xml version="1.0" encoding="utf-8"?>

<layer-list
    xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:top="75dp">
        <bitmap Android:src="@drawable/bg" />
    </item>
</layer-list>

次に、上記のようにこのファイルをバックグラウンドのリソースとして設定します。

getWindow().setBackgroundDrawableResource(R.drawable.my_background);

Nexus 5を使用しています。ステータスバーではなくxmlでアクションバーの高さを取得する方法を見つけたため、上部のパディングに固定高さ75dpを使用する必要があります。誰もがこのパズルの最後のピースを見つけられることを願っています。

4
RaymondRexxar

AndroidManifest.xmlファイルに次の行を追加します。

Android:windowSoftInputMode=adjustUnspecified

詳細については このリンク を参照してください。

2
David

利用可能なすべての回答を調査および実装した後、ここでソリューションを追加しています。

この答えは、次のコードの組み合わせです。

https://stackoverflow.com/a/45620231/1164529

https://stackoverflow.com/a/27702210/1164529

これは、w.r.tで伸縮もスクロールもしなかったカスタムAppCompatImageViewクラスです。ソフトキーボード:-

public class TopCropImageView extends AppCompatImageView {

    public TopCropImageView(Context context) {
        super(context);
        setScaleType(ImageView.ScaleType.MATRIX);
    }

    public TopCropImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setScaleType(ImageView.ScaleType.MATRIX);
    }

    public TopCropImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setScaleType(ImageView.ScaleType.MATRIX);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        computeMatrix();
    }

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        computeMatrix();
        return super.setFrame(l, t, r, b);
    }


    private void computeMatrix() {
        if (getDrawable() == null) return;
        Matrix matrix = getImageMatrix();
        float scaleFactor = getWidth() / (float) getDrawable().getIntrinsicWidth();
        matrix.setScale(scaleFactor, scaleFactor, 0, 0);
        setImageMatrix(matrix);
    }
}

Fragmentクラスの背景として使用するには、最初の要素としてFrameLayoutに設定します。

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <complete.package.TopCropImageView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:src="@mipmap/my_app_background" />

    <!-- Enter other UI elements here to overlay them on the background image -->

<FrameLayout>
1
Harpreet

onCreate()でこのコードを使用するだけです:

protected void onCreate(Bundle savedInstanceState) {
...   
 getWindow().setBackgroundDrawableResource(R.drawable.your_image_resource);
...
}

xmlで次の行を削除します。

Android:background="@drawable/background"

続きを読む:

http://developer.Android.com/reference/Android/view/Window.html

おかげで: エイドリアン・シド・アルマグエル

1
M.A.R

背景画像がImageView内のFragmentであり、キーボードでサイズ変更されたときに、この問題に直面しました。

私の解決策は: this SO Answer のカスタムImageViewを使用し、androidxと互換性があるように編集しました。

import Android.content.Context;
import Android.graphics.Matrix;
import Android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatImageView;

/**
 * Created by chris on 7/27/16.
 */
public class TopCropImageView extends AppCompatImageView {

    public TopCropImageView(Context context) {
        super(context);
        setScaleType(ScaleType.MATRIX);
    }

    public TopCropImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setScaleType(ScaleType.MATRIX);
    }

    public TopCropImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setScaleType(ScaleType.MATRIX);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        recomputeImgMatrix();
    }

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        recomputeImgMatrix();
        return super.setFrame(l, t, r, b);
    }

    private void recomputeImgMatrix() {
        if (getDrawable() == null) return;

        final Matrix matrix = getImageMatrix();

        float scale;
        final int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        final int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom();
        final int drawableWidth = getDrawable().getIntrinsicWidth();
        final int drawableHeight = getDrawable().getIntrinsicHeight();

        if (drawableWidth * viewHeight > drawableHeight * viewWidth) {
            scale = (float) viewHeight / (float) drawableHeight;
        } else {
            scale = (float) viewWidth / (float) drawableWidth;
        }

        matrix.setScale(scale, scale);
        setImageMatrix(matrix);
    }

}
1
Andrew

私は同様の問題に苦しんでいましたが、adjustPanAndroid:isScrollContainer="false"で使用してもまだレイアウトが修正されなかったようです(これはLinearLayoutの下のRecyclerViewでした)。 RecyclerViewは問題ありませんでしたが、仮想キーボードが表示されるたびに、LinearLayoutが再調整されました。

この動作を防ぐために(キーボードをレイアウト上に配置したかっただけです)、次のコードを使用しました。

    <activity
        Android:name=".librarycartridge.MyLibraryActivity"
        Android:windowSoftInputMode="adjustNothing" />

これはAndroid=に、仮想キーボードが呼び出されたときに基本的にレイアウトをそのままにするように伝えます。

考えられるオプションについての詳細は、 here を参照してください(奇妙なことに、adjustNothingのエントリがあるようには見えません)。

1
welshk91

以前にも同じ問題に直面していましたが、Fragmentを使用していたので長い間解決できませんでした。また、getActivity().getWindow().setBackgroundDrawable()は私にとっては解決策ではありませんでした。

私のために働いた解決策は、表示されるはずのキーボードを処理し、外出先でビットマップを変更するロジックでFrameLayoutをオーバーライドすることです。

FrameLayoutコード(Kotlin)は次のとおりです。

_class FlexibleFrameLayout : FrameLayout {

    var backgroundImage: Drawable? = null
        set(bitmap) {
            field = bitmap
            invalidate()
        }
    private var keyboardHeight: Int = 0
    private var isKbOpen = false

    private var actualHeight = 0

    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
        init()
    }

    fun init() {
        setWillNotDraw(false)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        if (actualHeight == 0) {
            actualHeight = height
            return
        }
        //kb detected
        if (actualHeight - height > 100 && keyboardHeight == 0) {
            keyboardHeight = actualHeight - height
            isKbOpen = true
        }
        if (actualHeight - height < 50 && keyboardHeight != 0) {
            isKbOpen = false
        }
        if (height != actualHeight) {
            invalidate()
        }
    }

    override fun onDraw(canvas: Canvas) {
        if (backgroundImage != null) {
            if (backgroundImage is ColorDrawable) {
                backgroundImage!!.setBounds(0, 0, measuredWidth, measuredHeight)
                backgroundImage!!.draw(canvas)
            } else if (backgroundImage is BitmapDrawable) {
                val scale = measuredWidth.toFloat() / backgroundImage!!.intrinsicWidth.toFloat()
                val width = Math.ceil((backgroundImage!!.intrinsicWidth * scale).toDouble()).toInt()
                val height = Math.ceil((backgroundImage!!.intrinsicHeight * scale).toDouble()).toInt()
                val kb = if (isKbOpen) keyboardHeight else 0
                backgroundImage!!.setBounds(0, 0, width, height)
                backgroundImage!!.draw(canvas)
            }
        } else {
            super.onDraw(canvas)
        }
    }
}
_

そして、通常のFrameLayoutの背景のように使用しました。

frameLayout.backgroundImage = Drawable.createFromPath(path)

それが役に立てば幸い。

0
Yela Tricks

LinearLayoutをFrameLayoutでラップし、ImageViewを背景で追加できます。

<FrameLayout>

  <ImageView 
    Android:background="@drawable/page_bg"
    Android:id="@+id/backgroundImage" />

  <LinearLayout>
    ....
  </LinearLayout>
</FrameLayout>

また、アクティビティ/フラグメントを作成するときに高さを設定できます(キーボードを開いたときにスケーリングしないようにするため)。フラグメントのKotlinのコード:

activity?.window?.decorView?.height?.let {
        backgroundImage.setHeight(it)
}
0
Rafols

アクティビティを追加するだけです

getWindow().setBackgroundDrawable(R.drawable.your_image_name);
0

ウィンドウの背景として画像を設定し、uiがスタックする場合。単一のドロウアブルフォルダーにあるドロウアブルを使用している可能性があります。はいの場合、drawable-nodpiまたはdrawable-xxxhdpiに貼り付ける必要があります。

0
Nikul Vaghani