安卓系统中的软键盘会改变背景图片的大小

141

每当软键盘出现时,它都会调整背景图像的大小。请参考下面的截图:

正如您所看到的,背景被挤压了。有人能解释一下为什么背景会重新调整大小吗?

我的布局如下:

<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个回答

2
我遇到了这个问题,当我的背景图片只是一个位于片段中的ImageView时,并且它被键盘调整大小时。
我的解决方案是:使用来自此SO答案的自定义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
以上代码不再拉伸,但仍会相对于软键盘略微上下滚动。 - Harpreet

1
我的解决方案是用布局的背景替换窗口的背景,然后将布局的背景设置为null。这样我就可以在XML预览窗口中保留图像:
因此,在布局中保留背景并为其添加一个id。然后在activity onCreate()中添加以下代码:
    ConstraintLayout mainLayout = (ConstraintLayout)findViewById(R.id.mainLayout);
    getWindow().setBackgroundDrawable(mainLayout.getBackground());
    mainLayout.setBackground(null);

0

如果您将图像设置为窗口背景并且用户界面卡住了,那么可能是因为您使用的可绘制对象位于单个drawable文件夹中, 如果是这样,您需要将其粘贴到drawable-nodpi或drawable-xxxhdpi中。


0

只需在您的活动中添加

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

0

我之前遇到过同样的问题,但是没有一个解决方案能够长期适用于我,因为我正在使用一个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

你可以使用FrameLayout对LinearLayout进行包装,并添加具有背景的ImageView:

<FrameLayout>

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

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

而且您可以在创建活动/片段时设置其高度(以防止打开键盘时进行缩放)。以下是来自片段的Kotlin代码:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接