Программная клавиатура изменяет размер фонового изображения на Android - PullRequest
122 голосов
/ 26 ноября 2010

Всякий раз, когда появляется программная клавиатура, она изменяет размер фонового изображения. Смотрите на скриншот ниже:

Как видите, фон как бы сжат. Кто-нибудь может пролить свет на то, почему размер фона изменяется?

Мой макет выглядит следующим образом:

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

Ответы [ 16 ]

1 голос
/ 28 сентября 2016

У меня возникли похожие проблемы, но похоже, что использование adjustPan с android:isScrollContainer="false" все еще не исправило мой макет (который был RecyclerView ниже LinearLayout). RecyclerView был в порядке, но каждый раз, когда появлялась виртуальная клавиатура, LinearLayout перестраивался.

Чтобы предотвратить это поведение (я просто хотел, чтобы клавиатура перебирала мою раскладку), я использовал следующий код:

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

Это говорит Android о том, что при вызове виртуальной клавиатуры Android в основном остается в одиночестве.

Более подробную информацию о возможных вариантах можно найти здесь (хотя, как ни странно, не похоже, что есть запись для adjustNothing).

0 голосов
/ 12 апреля 2019

, если вы установили изображение как фон окна и пользовательский интерфейс застрянет. тогда может быть вероятность того, что вы используете drawable, которое находится в одной папке drawable, если да, то вы должны вставить его в drawable-nodpi или drawable-xxxhdpi.

0 голосов
/ 27 марта 2019

Вы можете обернуть свой LinearLayout с FrameLayout и добавить ImageView с Background:

<FrameLayout>

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

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

И Вы можете установить его высоту при создании действия / фрагмента (чтобы предотвратить масштабирование при открытой клавиатуре).Немного кода в Котлине из фрагмента:

activity?.window?.decorView?.height?.let {
        backgroundImage.setHeight(it)
}
0 голосов
/ 20 марта 2019

После изучения и реализации всех доступных ответов, здесь я добавляю решение.

Этот ответ является комбинацией кода из:

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

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

Вот пользовательский класс AppCompatImageView, который не показывал растяжения или прокрутки w.r.t. программная клавиатура: -

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

    <app.utils.view.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>
0 голосов
/ 26 апреля 2018

Просто добавьте в свою деятельность

getWindow().setBackgroundDrawable(R.drawable.your_image_name);
0 голосов
/ 10 августа 2017

Я сталкивался с этой же проблемой раньше, но ни одно решение не работало для меня так долго, потому что я использовал 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)

Надеюсь, это поможет.

...