每当出现软件键盘时,它都会调整背景图像的大小。请参阅下面的屏幕截图:
如你所见,背景有点挤压。任何人都可以了解为什么背景调整大小?
我的布局如下:
<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>
好的,我通过使用修复它
android:windowSoftInputMode="stateVisible|adjustPan"
在<Activity >
文件中的manifest
标签内输入。我认为这是由于在Activity中有ScrollView引起的。
只需在你的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
我遇到了这个问题,当我的背景图像只是ImageView
里面的Fragment
时,它被键盘重新调整大小。
我的解决方案是:使用来自ImageView
的自定义this SO Answer,编辑为与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);
}
}
在研究和实施所有可用答案之后,我在这里添加一个解决方案。
这个答案是来自以下代码的组合:
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>
只需添加您的活动即可
getWindow().setBackgroundDrawable(R.drawable.your_image_name);
我之前遇到过同样的问题,但没有解决方案对我有用,因为我使用的是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)
希望能帮助到你。
您可以使用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)
}
如果你将图像设置为windowbackground而ui会卡住。然后有可能你使用drawable,它在单个drawable文件夹中,如果是,那么你必须将它粘贴在drawable-nodpi或drawable-xxxhdpi中。
我在开发聊天应用程序,聊天屏幕和背景图像时遇到了同样的问题。 android:windowSoftInputMode="adjustResize"
在显示软键盘后挤压我的背景图像以适应可用空间,并且“adjustPan”将整个布局向上移动以调整软键盘。此问题的解决方案是在活动XML中设置窗口背景而不是布局背景。在您的活动中使用getWindow().setBackgroundDrawable()
。
这是避免此类问题的最佳解决方案。
第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" >
通过android:windowSoftInputMode =“adjustPan”给出糟糕的用户体验,因为通过整个屏幕进入顶部(转移到顶部)所以,以下是最好的回答之一。
我有同样的问题,但在那之后,我从@Gem找到了很棒的答案
在清单中
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
在xml中
不要在此处设置任何背景并在ScrollView下保持您的视图
在Java中
您需要将背景设置为窗口:
getWindow().setBackgroundDrawableResource(R.drawable.bg_wood) ;
感谢@Gem。
只是为了补充......
如果你对你的活动有一个列表视图你需要在listview属性中添加这个android:isScrollContainer="false"
...
并且不要忘记在您的活动中在清单xml中添加android:windowSoftInputMode="adjustPan"
...
如果你们在你的布局上使用带有可滚动视图的android:windowSoftInputMode="adjustUnspecified"
,那么你的背景仍将通过软键盘重新调整大小......
如果你使用“adjustPan”值来防止你的背景调整大小会更好...
如果有人需要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>
我在处理我的应用时遇到了主要问题。首先,我使用@parulb提供的方法来解决问题。非常感谢他。但后来我注意到背景图片被动作栏部分隐藏(我确定状态栏)。这个小问题已经由@ zgc7009提出,他在一年半之前评论了@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进行顶部填充。希望任何人都能找到这个难题的最后一块。
我遇到了类似的问题,但似乎使用adjustPan
与android:isScrollContainer="false"
仍然没有修复我的布局(这是一个LinearLayout下面的RecyclerView)。 RecyclerView很好,但每次虚拟键盘出现时,LinearLayout都会重新调整。
为了防止这种行为(我只是想让键盘覆盖我的布局),我使用了以下代码:
<activity
android:name=".librarycartridge.MyLibraryActivity"
android:windowSoftInputMode="adjustNothing" />
这告诉Android在调用虚拟键盘时基本上只保留布局。
关于可能的选项的更多阅读可以找到here(虽然奇怪的是,它似乎没有adjustNothing
的条目)。