แป้นพิมพ์ซอฟต์แวร์ปรับขนาดภาพพื้นหลังบน Android


136

เมื่อใดก็ตามที่แป้นพิมพ์ซอฟต์แวร์ปรากฏขึ้นแป้นพิมพ์จะปรับขนาดภาพพื้นหลัง ดูภาพหน้าจอด้านล่าง:

อย่างที่คุณเห็นพื้นหลังเป็นแบบบีบ มีใครพอจะรู้ไหมว่าทำไมพื้นหลังจึงปรับขนาดได้?

รูปแบบของฉันมีดังนี้:

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

คำตอบ:


193

ตกลงฉันแก้ไขโดยใช้

android:windowSoftInputMode="stateVisible|adjustPan"

รายการภายใน<Activity >แท็กในmanifestไฟล์ ฉันคิดว่ามันเกิดจากการมี ScrollView ในกิจกรรม


3
ปัญหาคือการเลื่อนคือเมื่อใช้ adjustPan ไม่ทำงาน ... (ถ้าคุณมี ScrollView) และนั่นน่ารำคาญ ...
Ted

4
แต่ตอนนี้ scrollview ไม่ทำงาน มีวิธีใดที่จะหลีกเลี่ยงได้
Mr.G

ฉันต้องการมุมมองแบบเลื่อน คุณมีวิธีเก็บมุมมองแบบเลื่อนและไม่บีบอัดพื้นหลังหรือไม่
Rana Ranvijay Singh

4
นั่นยังไม่พอ. อย่างน้อยถ้าคุณไม่ใช้ ScrollView ดีมากเป็นวิธีแก้ปัญหาที่นี่stackoverflow.com/a/29750860/2914140หรือstackoverflow.com/a/18191266/2914140
CoolMind

1
หากคุณไม่ต้องการแสดงแป้นพิมพ์โดยอัตโนมัติให้ใช้: android: windowSoftInputMode = "adjustmentPan"
satvinder singh

110

ฉันประสบปัญหาเดียวกันในขณะที่พัฒนาแอพแชทหน้าจอแชทที่มีภาพพื้นหลัง android:windowSoftInputMode="adjustResize"บีบภาพพื้นหลังของฉันให้พอดีกับพื้นที่ว่างหลังจากที่แป้นพิมพ์อ่อนแสดงขึ้นและ "ปรับแพน" เลื่อนเค้าโครงทั้งหมดขึ้นเพื่อปรับแป้นพิมพ์แบบนุ่ม วิธีแก้ปัญหานี้คือการตั้งค่าพื้นหลังของหน้าต่างแทนที่จะเป็นพื้นหลังเค้าโครงภายใน XML ของกิจกรรม ใช้getWindow().setBackgroundDrawable()ในกิจกรรมของคุณ


4
ดีมาก! ตอบดีที่สุด! AdjustPan ทำให้เกิดเอฟเฟกต์หลักประกันเช่น: แป้นพิมพ์จะแทนที่ส่วนประกอบ แต่ไม่มีแถบเลื่อนปรากฏขึ้น
CelinHC

4
@parulb หรือใครก็ตามที่อ่านสิ่งนี้มันใช้งานได้ดี (และขอบคุณสำหรับมัน) ตราบใดที่ภาพพื้นหลังไม่มีข้อมูลที่เกี่ยวข้อง ปัญหาที่ฉันพบเป็นครั้งคราวคือพื้นหลังของฉันจะมีบางอย่างเช่นโลโก้และการตั้งค่าพื้นหลังหน้าต่างเป็นรูปภาพจะซ่อนโลโก้ไว้ด้านหลัง ActionBar สำหรับบางหน้าจอนี่ไม่ใช่ปัญหา แต่บางครั้งฉันจำเป็นต้องเก็บ ActionBar ไว้ (ไม่มีการซ่อน) มีแนวคิดเกี่ยวกับวิธีจัดการช่องว่างภายในบางประเภทในขณะที่ตั้งค่าพื้นหลังของหน้าต่างเพื่อพิจารณา ActionBar หรือไม่?
zgc7009

1
จะเกิดอะไรขึ้นถ้าฉันมีส่วนจะจัดการกับมันอย่างไร? มันไม่ทำงานสำหรับเศษ
user2056563

ถึงผู้ใช้ 2056563: สำหรับชิ้นส่วนเพียงใช้ getActivity () getWindow (). setBackgroundDrawable () หรือ getActivity (). getWindow (). setBackgroundDrawableResource ()
Andrei Aulaska

ขอบคุณมันใช้งานได้แม้กระทั่งกับ scrollview ฉันทำแบบนี้กับ 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

ใน Manifest

android:windowSoftInputMode="adjustResize|stateAlwaysHidden"

ใน xml

อย่าตั้งค่าพื้นหลังใด ๆ ที่นี่และเก็บมุมมองของคุณไว้ใน ScrollView

ใน Java

คุณต้องตั้งค่าพื้นหลังเป็นหน้าต่าง:

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

ขอบคุณข้อมูล @Gem


1
ขอบคุณสำหรับการรับรู้
อัญมณี

จะทำอย่างไรถ้าต้องการใช้ประเภทมาตราส่วนในสิ่งนี้ เพราะสำหรับรอยบากภาพหน้าจอจะยืด
ไม่มี

14

เพียงเพื่อเพิ่ม ...

หากคุณมีมุมมองรายการเกี่ยวกับกิจกรรมของคุณคุณต้องเพิ่มสิ่งนี้ android:isScrollContainer="false"ในคุณสมบัติ listview ของคุณ ...

และอย่าลืมเพิ่ม android:windowSoftInputMode="adjustPan" xml manifest ในกิจกรรมของคุณ ...

ถ้าพวกคุณใช้ android:windowSoftInputMode="adjustUnspecified"กับมุมมองที่เลื่อนได้ในเลย์เอาต์ของคุณพื้นหลังของคุณจะยังคงปรับขนาดโดยแป้นพิมพ์อ่อน ...

จะดีกว่าถ้าคุณใช้ค่า "adjustmentPan" เพื่อป้องกันไม่ให้พื้นหลังของคุณปรับขนาด ...


2
android: windowSoftInputMode = "adjustPan" เปลี่ยนมุมมองทั้งหมดด้วยแป้นพิมพ์ โดยทั่วไปเราจะมีชื่อของหน้าจออยู่ด้านบน การใช้แฟล็กนี้มันจะออกไปจากพื้นที่ที่มองเห็นได้ด้วยซึ่งจะทำให้ผู้ใช้ได้รับประสบการณ์ที่ไม่ดี
อัญมณี

@ เจม: แล้วทางออกคืออะไร?

@Copernic ฉันประสบปัญหานี้มานานแล้วเมื่อฉันทำงานกับแอปพลิเคชันแชท ในที่สุดฉันก็แก้ไขได้โปรดอ้างอิงคำตอบของฉันที่นี่: stackoverflow.com/questions/5307264/…
Gem

7

ในกรณีที่ใครบางคนต้องการadjustResizeพฤติกรรมและไม่ต้องการเขาImageViewปรับขนาดนี่เป็นวิธีแก้ปัญหาอื่น

เพียงแค่ใส่ImageViewภายในScrollView=> ด้วยRelativeLayoutScrollView.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 ซึ่งแสดงความคิดเห็นด้านล่างคำตอบของ @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

ฉันประสบปัญหาที่คล้ายกัน แต่ดูเหมือนว่าจะใช้adjustPanกับไฟล์android:isScrollContainer="false"ยังไม่ได้แก้ไขรูปแบบของฉัน (ซึ่งเป็น RecyclerView ด้านล่าง LinearLayout a) RecyclerView นั้นใช้ได้ แต่ทุกครั้งที่แป้นพิมพ์เสมือนปรากฏขึ้น LinearLayout จะปรับใหม่

เพื่อป้องกันพฤติกรรมนี้ (ฉันแค่ต้องการให้แป้นพิมพ์อยู่เหนือเค้าโครงของฉัน) ฉันใช้รหัสต่อไปนี้:

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

สิ่งนี้จะบอกให้ Android ปล่อยเค้าโครงของคุณไว้ตามลำพังเมื่อมีการเรียกแป้นพิมพ์เสมือน

อ่านเพิ่มเติมเกี่ยวกับตัวเลือกที่เป็นไปได้ที่นี่ (แม้ว่าจะแปลกพอสมควร แต่ดูเหมือนว่าจะไม่มีรายการสำหรับadjustNothing)


3

หลังจากศึกษาและปรับใช้คำตอบที่มีทั้งหมดแล้วฉันกำลังเพิ่มโซลูชัน

คำตอบนี้เป็นการรวมรหัสจาก:

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

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

นี่คือAppCompatImageViewคลาสที่กำหนดเองซึ่งไม่มีการยืดหรือเลื่อนคีย์บอร์ดแบบ WRT: -

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

ที่จะใช้เป็นพื้นหลังของฉันระดับผมตั้งเป็นองค์ประกอบแรกที่จะFragmentFrameLayout

<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

เพียงใช้ใน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

ขอบคุณสำหรับ: Adrian Cid Almaguer


1

ฉันประสบกับปัญหานี้เมื่อภาพพื้นหลังของฉันเป็นเพียงImageViewด้านในFragmentและแป้นพิมพ์ถูกปรับขนาด

วิธีแก้ปัญหาของฉันคือ: ใช้แบบกำหนดเองImageViewจาก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);
    }

}

มันไม่ยืดอีกต่อไปด้วยรหัสด้านบน แต่มันยังคงเลื่อนคีย์บอร์ดนุ่ม WRT ขึ้น / ลงเล็กน้อย
Harpreet

1

วิธีแก้ปัญหาของฉันคือแทนที่พื้นหลังของหน้าต่างด้วยหนึ่งในเค้าโครงจากนั้นตั้งค่าพื้นหลังของเค้าโครงเป็น null ด้วยวิธีนี้ฉันจะเก็บภาพไว้ในหน้าต่างแสดงตัวอย่าง XML:

ดังนั้นให้พื้นหลังอยู่ในเค้าโครงและเพิ่มรหัสสำหรับมัน จากนั้นในกิจกรรม onCreate () ให้ใส่รหัสนี้:

    ConstraintLayout mainLayout = (ConstraintLayout)findViewById(R.id.mainLayout);
    getWindow().setBackgroundDrawable(mainLayout.getBackground());
    mainLayout.setBackground(null);


0

ฉันประสบปัญหาเดียวกันนี้มาก่อน แต่ไม่มีวิธีแก้ปัญหาใด ๆ สำหรับฉันมานานเพราะฉันใช้ a 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

คุณสามารถรวม LinearLayout ของคุณด้วย FrameLayout และเพิ่ม ImageView พร้อมพื้นหลัง:

<FrameLayout>

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

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

และคุณสามารถตั้งค่าความสูงได้เมื่อคุณสร้างกิจกรรม / ส่วนย่อย (เพื่อป้องกันไม่ให้ปรับขนาดเมื่อเปิดแป้นพิมพ์) โค้ดบางส่วนใน Kotlin จาก Fragment:

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

0

หากคุณตั้งค่าภาพเป็น windowbackground และ ui จะติด จากนั้นอาจมีความเป็นไปได้ที่คุณจะใช้ drawable ซึ่งอยู่ในโฟลเดอร์ drawable เดียวถ้าใช่คุณต้องวางลงใน drawable-nodpi หรือ drawable-xxxhdpi

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.