it-swarm.com.de

Die Softwaretastatur passt das Hintergrundbild auf Android an

Wenn die Software-Tastatur angezeigt wird, ändert sich die Größe des Hintergrundbilds. Siehe den Screenshot unten:

Wie Sie sehen können, ist der Hintergrund irgendwie zusammengedrückt. Kann jeder wissen, warum der Hintergrund die Größe ändert?

Mein Layout ist wie folgt:

<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>
118
Andreas Wong

Ok, ich habe es mit korrigiert 

Android:windowSoftInputMode="stateVisible|adjustPan"

eintrag im <Activity >-Tag in der manifest-Datei. Ich denke, es wurde durch ScrollView in der Aktivität verursacht.

179
Andreas Wong

Bei der Entwicklung einer Chat-App, dem Chat-Bildschirm mit Hintergrundbild, war ich mit dem gleichen Problem konfrontiert. Android:windowSoftInputMode="adjustResize" drückte mein Hintergrundbild an den verfügbaren Platz, nachdem die Softtastatur angezeigt wurde, und "adjustPan" verschob das gesamte Layout nach oben, um die Softtastatur anzupassen. Die Lösung für dieses Problem bestand darin, den Fensterhintergrund anstelle eines Layouthintergrunds im Inneren festzulegen eine Aktivität XML. Verwenden SiegetWindow().setBackgroundDrawable()in Ihrer Aktivität.

101
parulb

Hier ist die beste Lösung, um solche Probleme zu vermeiden.

Schritt 1: Erstellen Sie einen Stil

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

Schritt 2: Legen Sie Ihren Aktivitätsstil in der Datei AndroidManifest fest

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

Über Android: windowSoftInputMode = "adjustPan", was zu einer schlechten Benutzererfahrung führt, da durch den gesamten Bildschirm nach oben gerückt wird (nach oben verschoben). Daher ist das Folgen eine der besten Antworten.

Ich habe das gleiche Problem, aber danach habe ich großartige Antworte aus dem @Gem gefunden

In Manifest

Android:windowSoftInputMode="adjustResize|stateAlwaysHidden"

In XML

Stellen Sie hier keinen Hintergrund ein und behalten Sie Ihre Ansicht unter ScrollView

In Java

Sie müssen den Hintergrund auf Fenster setzen:

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

Danke an @Gem.

25
Joseph Mekwan

nur zur Ergänzung ...

wenn Sie eine Listenansicht für Ihre Aktivität haben Sie müssen dieses Android:isScrollContainer="false" in Ihre Listview-Eigenschaften einfügen ...

und vergessen Sie nicht, Android:windowSoftInputMode="adjustPan" in Ihrer Manifest-XML bei Ihrer Aktivität hinzuzufügen ...

wenn Sie Android:windowSoftInputMode="adjustUnspecified" mit scrollbarer Ansicht in Ihrem Layout verwenden, wird der Hintergrund weiterhin von der Soft-Tastatur angepasst ...

es wäre besser, wenn Sie den Wert "adjustPan" verwenden, um die Größenänderung Ihres Hintergrunds zu verhindern ...

14
BolbazarMarme

Falls jemand ein adjustResize-Verhalten benötigt und nicht möchte, dass seine ImageView hier geändert wird, ist dies eine andere Problemumgehung.

Geben Sie einfach ImageView in ScrollView => RelativeLayout mit ScrollView.fillViewport = true ein.

<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

Bei der Arbeit an meiner App ist das Hauptproblem aufgetreten. Zuerst verwende ich die von @parulb bereitgestellte Methode, um das Problem zu lösen. Ich danke ihm vielmals. Später bemerkte ich jedoch, dass das Hintergrundbild teilweise von der Aktionsleiste (und der Statusleiste ist mir sicher) verborgen ist. Dieses kleine Problem wurde bereits von @ zgc7009 vorgeschlagen, der vor einerinhalb Jahren die Antwort von @parulb kommentierte, aber niemand antwortete.

Ich habe einen ganzen Tag gearbeitet, um einen Weg herauszufinden, und zum Glück kann ich dieses Problem jetzt zumindest auf meinem Handy perfekt lösen. 

Zuerst benötigen wir eine Layer-Listen-Ressource im gezeichneten Ordner, um das Hintergrundbild oben mit Padding zu füllen:

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

Zweitens setzen wir diese Datei wie oben erwähnt als Ressource für den Hintergrund:

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

Ich verwende Nexus 5. Ich habe einen Weg gefunden, die Höhe der Actionbar in xml zu ermitteln, aber nicht die Statusleiste. Daher muss ich eine feste Höhe von 75dp für die Auffüllung verwenden. Ich hoffe, jeder kann das letzte Stück dieses Puzzles finden.

4
RaymondRexxar

Fügen Sie diese Zeile in der Datei AndroidManifest.xml hinzu:

Android:windowSoftInputMode=adjustUnspecified

siehe diesen Link für weitere Informationen.

1
David

Verwenden Sie einfach diesen Code in Ihrer onCreate():

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

und entfernen Sie diese Zeile in Ihrer XML:

Android:background="@drawable/background"

Lesen Sie mehr unter:

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

danke für: Adrian Cid Almaguer

1
M.A.R

Ich hatte ähnliche Probleme, aber es scheint, als würde die Verwendung von adjustPan mit Android:isScrollContainer="false" immer noch mein Layout nicht korrigieren (was eine RecyclerView unterhalb eines LinearLayout war). Die RecyclerView war in Ordnung, aber jedes Mal, wenn die virtuelle Tastatur auftauchte, wurde das LinearLayout neu eingestellt.

Um dieses Verhalten zu verhindern (ich wollte einfach, dass die Tastatur über mein Layout hinausgeht), habe ich folgenden Code verwendet:

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

Dadurch wird Android angewiesen, das Layout beim Aufruf der virtuellen Tastatur im Grunde allein zu lassen.

Weitere Informationen zu möglichen Optionen finden Sie hier (obwohl es merkwürdigerweise nicht so aussieht, als gäbe es einen Eintrag für adjustNothing).

1
welshk91

Ich stand vor dem gleichen Problem, aber es funktionierte so lange keine Lösung für mich, da ich ein Fragment verwendete und auch getActivity().getWindow().setBackgroundDrawable() keine Lösung für mich war.

Die Lösung, die für mich funktioniert hat, besteht darin, FrameLayout mit einer Logik für die Tastatur zu überschreiben, die angezeigt werden soll, und die Bitmap unterwegs zu ändern.

Hier ist mein FrameLayout-Code (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)
        }
    }
}

Und ich habe es wie einen normalen FrameLayout-Hintergrund verwendet.

frameLayout.backgroundImage = Drawable.createFromPath(path)

Ich hoffe es hilft.

0
Yela Tricks

Nachdem ich alle verfügbaren Antworten studiert und umgesetzt habe, füge ich hier eine Lösung hinzu.

Diese Antwort ist eine Kombination aus Code von:

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

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

Hier ist die benutzerdefinierte Klasse AppCompatImageView, die kein Strecken oder Scrollen w.r.t. Weiche Tastatur: -

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);
    }
}

Um es als Hintergrund für meine Klasse Fragment zu verwenden, habe ich es als erstes Element auf FrameLayout gesetzt.

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

Sie können Ihr LinearLayout mit FrameLayout umschließen und ImageView mit Hintergrund hinzufügen:

<FrameLayout>

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

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

Und Sie können die Höhe festlegen, wenn Sie eine Aktivität/ein Fragment erstellen (um eine Skalierung beim Öffnen der Tastatur zu verhindern). Code in Kotlin aus Fragment:

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

Ich war mit diesem Problem konfrontiert, als mein Hintergrundbild nur eine ImageView in einer Fragment war und die Größe der Tastatur geändert wurde. 

Meine Lösung war: Benutzerdefinierte ImageView von diese SO Antwort , bearbeitet, um mit androidx kompatibel zu sein.

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);
    }

}
0
Andrew

Fügen Sie einfach Ihre Aktivität hinzu

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

wenn du bild als fensterhintergrund gesetzt hast und feststeckst. Dann besteht die Möglichkeit, dass Sie drawable verwenden, das sich in einem einzelnen drawable-Ordner befindet. Wenn ja, müssen Sie es in drawable-nodpi oder drawable-xxxhdpi einfügen.

0
Nikul Vaghani