소프트웨어 키보드가 Android의 배경 이미지 크기를 조정합니다


133

소프트웨어 키보드가 나타날 때마다 배경 이미지의 크기가 조정됩니다. 아래 스크린 샷을 참조하십시오 :

보시다시피, 배경은 일종의 압착입니다. 누구나 배경의 크기를 조정하는 이유를 밝힐 수 있습니까?

내 레이아웃은 다음과 같습니다.

<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>

답변:


190

확인을 사용하여 수정했습니다.

android:windowSoftInputMode="stateVisible|adjustPan"

파일의 <Activity >태그 내부 항목 manifest. 액티비티 내부에 ScrollView가 있기 때문에 발생했다고 생각합니다.


3
문제는 스크롤이 adjustPan을 사용할 때 작동하지 않는다는 것입니다 (ScrollView가있는 경우). 짜증나는 일입니다.
Ted

4
그러나 스크롤보기가 현재 작동하지 않습니다. 피할 수있는 방법이 있습니다
Mr.G

스크롤보기가 필요합니다. 스크롤보기를 유지하고 배경을 압축하지 않은 상태로 유지할 수 있습니다.
Rana Ranvijay Singh

4
그것은 충분하지 않아. 적어도 ScrollView를 사용하지 않는 경우. stackoverflow.com/a/29750860/2914140 또는 stackoverflow.com/a/18191266/2914140 의 솔루션이 훨씬 좋습니다 .
CoolMind

1
키보드를 자동으로 표시하지 않으려면 다음을 사용하십시오. android : windowSoftInputMode = "adjustPan"
satvinder singh

110

배경 이미지가있는 채팅 앱, 채팅 화면을 개발하는 동안 동일한 문제에 직면했습니다. android:windowSoftInputMode="adjustResize"소프트 키보드가 표시된 후 사용 가능한 공간에 맞게 배경 이미지를 꽉 쥐고 "adjustPan"이 전체 레이아웃을 위로 이동하여 소프트 키보드를 조정했습니다. 이 문제에 대한 해결책은 활동 XML 내부의 레이아웃 배경 대신 창 배경을 설정하는 것이 었습니다. getWindow().setBackgroundDrawable()활동에 사용하십시오 .


4
아주 좋아요! 최고의 답변! adjustPan은 다음과 같은 부수적 효과를 유발합니다. 키보드가 구성 요소를 재정의하지만 스크롤 막대가 표시되지 않습니다.
CelinHC

4
@parulb 또는 이것을 읽는 다른 사람이라면 배경 이미지에 관련 정보가 포함되어 있지 않는 한 훌륭하게 작동합니다 (감사합니다). 때때로 발생하는 문제는 배경에 로고와 같은 것이 포함되어 있고 창 배경을 이미지로 설정하면 로고가 ActionBar 뒤에 숨겨져 있다는 것입니다. 특정 화면에서는 이것이 문제가되지 않지만 때로는 ActionBar (숨김 없음)를 유지해야합니다. ActionBar를 고려하여 창 배경을 설정하는 동안 일종의 패딩을 처리하는 방법에 대한 아이디어가 있습니까?
zgc7009

1
조각을 처리하는 방법은 무엇입니까? 그것의 조각에 작동하지 않습니다
user2056563

user2056563 : 조각의 경우 getActivity (). getWindow (). setBackgroundDrawable () 또는 getActivity (). getWindow (). setBackgroundDrawableResource ()를 사용하십시오.
Andrei Aulaska

감사합니다. 스크롤 뷰에서도 작동했습니다. 나는 새로운 AppCompat에서 이것을 좋아했다 : getWindow (). setBackgroundDrawable (ContextCompat.getDrawable (this, R.drawable.background));
Lucas Eduardo

34

이러한 종류의 문제를 피하는 가장 좋은 해결책은 다음과 같습니다.

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" >

좋은! 가장 간단한 해결책
Matias Elorriaga

28

android : windowSoftInputMode = "adjustPan"을 통해 전체 화면이 맨 위로 이동하기 때문에 나쁜 사용자 경험을 제공하므로 다음은 가장 좋은 답변 중 하나입니다.

나는 같은 문제가 있지만 그 후에 @Gem에서 멋진 답변을 찾았습니다.

매니페스트에서

android:windowSoftInputMode="adjustResize|stateAlwaysHidden"

xml에서

여기에 배경을 설정하지 말고 ScrollView에서보기를 유지하십시오.

자바에서

배경을 창으로 설정해야합니다.

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

@Gem에게 감사합니다.


1
인정해 주셔서 감사합니다.
Gem

이것에 스케일 타입을 사용하려면 어떻게해야합니까? 노치 스크린 이미지가 늘어나 기 때문입니다.
Nil

14

덧붙여서 ...

당신이 당신의 활동에 대한 목록보기를 가지고 있다면 이것을 추가해야합니다 android:isScrollContainer="false" 속성에 합니다 ...

추가하는 것을 잊지 마세요 android:windowSoftInputMode="adjustPan"액티비티에서 매니페스트 XML ...

너희들이 사용한다면 android:windowSoftInputMode="adjustUnspecified"레이아웃에서 스크롤 가능한보기로 하는 에도 소프트 키보드로 배경 크기가 계속 조정됩니다 ...

"adjustPan"값을 사용하여 배경의 크기가 조정되지 않도록하는 것이 좋습니다.


2
android : windowSoftInputMode = "adjustPan"은 키보드로 전체보기를 이동시킵니다. 일반적으로 상단에 화면 제목이 있습니다. 이 플래그를 사용하면 가시 영역을 벗어나 사용자 경험이 좋지 않습니다.
보석

@ 보석 : 그래서 해결책은 무엇입니까?

@Copernic 채팅 응용 프로그램을 작업 할 때 오랫동안이 문제에 직면했습니다. 결국 나는 여기에 내 대답을 참조하시기 바랍니다 : stackoverflow.com/questions/5307264/…
Gem

7

누군가 adjustResize행동이 필요하고 ImageView여기에서 크기를 조정 하지 않으려 는 경우 또 다른 해결 방법이 있습니다.

ImageView안에 ScrollView=> RelativeLayout을 넣습니다 ScrollView.fillViewport = true.

<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>

1
이것은 이미지 이외의 배경에서 다른 뷰를 가지고있는 경우에 좋은 솔루션입니다 .... 감사합니다
Dominic D' Souza

4

앱에서 작업 할 때 주요 문제가 발생했습니다. 처음에는 @parulb에서 제공하는 방법을 사용하여 문제를 해결했습니다. 고마워 그러나 나중에 배경 이미지가 작업 표시 줄 (및 상태 표시 줄)에 의해 부분적으로 숨겨져 있음을 알았습니다. 이 작은 문제는 이미 @ zgc7009에 의해 제안되었으며 1 년 반 전에 @parulb의 답변 아래에 댓글을 달았지만 아무도 대답하지 않았습니다.

나는 하루 종일 일하는 방법을 찾기 위해 노력했으며 운 좋게도 적어도 지금은 휴대 전화 에서이 문제를 완벽하게 해결할 수 있습니다.

먼저 배경 이미지 위에 패딩을 추가하려면 드로어 블 폴더에 레이어 목록 리소스가 필요합니다.

<!-- 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를 사용해야합니다. 누구나이 퍼즐의 마지막 조각을 찾을 수 있기를 바랍니다.


3

나는 비슷한 문제를 겪었지만 사용하는 것 같아 adjustPanandroid:isScrollContainer="false"(A의 LinearLayout 아래 RecyclerView했다) 내 레이아웃을 수정하지 않았다 아직. RecyclerView는 괜찮 았지만 가상 키보드가 나타날 때마다 LinearLayout이 다시 조정되었습니다.

이 동작을 방지하기 위해 (단순히 키보드가 레이아웃을 넘기고 싶었습니다) 다음 코드를 사용했습니다.

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

이것은 가상 키보드가 호출 될 때 안드로이드가 기본적으로 레이아웃을 그대로 두도록 지시합니다.

가능한 옵션에 대한 자세한 내용은 여기 에서 찾을 수 있습니다 (이상하게도에 대한 항목이없는 것 같습니다 adjustNothing).


3

사용 가능한 모든 답변을 연구하고 구현 한 후에 여기에 솔루션을 추가하고 있습니다.

이 답변은 다음 코드의 조합입니다.

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

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

다음은 AppCompatImageViewwrt 소프트 키보드를 늘리거나 스크롤하지 않은 사용자 정의 클래스입니다.

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>

2

AndroidManifest.xml 파일에 다음 행을 추가 하십시오.

android:windowSoftInputMode=adjustUnspecified

자세한 내용은 이 링크 를 참조하십시오 .


이 작업을 수행 한 후에도 여전히 발생합니다. 실망스러워지고 있습니다 :(
Andreas Wong


1

내 배경 이미지가 단지 ImageView내부 Fragment에 있고 키보드로 크기가 조정 되었을 때이 문제에 직면 했습니다.

내 솔루션이었다 정의를 사용 ImageView에서 이 SO 응답 와 호환되도록 편집했습니다 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);
    }

}

그것은 위의 코드로 더 이상 늘어나지 않지만 여전히 작은 위 / 아래 wrt 소프트 키보드를 스크롤합니다.
Harpreet


0

나는 전에이 같은 문제에 직면하지만 난을 사용했기 때문에 해결책은 오랫동안 나를 위해 일하지 Fragment, 또한 getActivity().getWindow().setBackgroundDrawable() 저를위한 솔루션은 아니었다.

나를 위해 일한 해결책은 FrameLayout키보드를 처리하고 이동 중에 비트 맵을 변경 해야하는 로직 을 재정의 하는 것입니다.

내 FrameLayout 코드 (코 틀린)는 다음과 같습니다.

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

FrameLayout으로 LinearLayout을 감싸고 Background를 사용하여 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

이미지를 windowbackground로 설정하고 ui가 멈추는 경우. 그렇다면 단일 드로어 블 폴더에있는 드로어 블을 사용할 가능성이있을 수 있습니다. 그렇다면 drawable-nodpi 또는 drawable-xxxhdpi에 붙여 넣으십시오.


0

내 해결책은 창의 배경을 레이아웃 중 하나로 바꾼 다음 레이아웃 배경을 null로 설정하는 것입니다. 이런 식으로 이미지를 XML 미리보기 창에 유지합니다.

따라서 배경을 레이아웃에 유지하고 ID를 추가하십시오. 그런 다음 onCreate () 활동에 다음 코드를 입력하십시오.

    ConstraintLayout mainLayout = (ConstraintLayout)findViewById(R.id.mainLayout);
    getWindow().setBackgroundDrawable(mainLayout.getBackground());
    mainLayout.setBackground(null);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.