web-dev-qa-db-fra.com

Android: ne redimensionnez que certaines parties de la vue avec le clavier virtuel à l'écran

J'ai une vue avec un champ Edittext au-dessus d'un ImageView. Lorsque le clavier apparaît, je souhaite que la fenêtre soit redimensionnée afin que EditText ne soit plus masqué par le clavier. Dans le fichier AndroidManifest j'ai déclaré Android:windowSoftInputMode="adjustResize" et l’écran est redimensionné, mais le problème est que je ne veux pas redimensionner ImageView. Comment puis-je rendre le ImageView non affecté?

Pourrais-je gonfler une mise en page supplémentaire avec uniquement ImageView ou le redimensionnement l'affectera-t-il toujours? enter image description here

49
pdfj

La solution complète implique quelques points clés

  • Utilisez RelativeLayout, de sorte que Views puisse être configuré pour se chevaucher
  • Alignez le EditText avec le bas du Windows en utilisant Android:layout_alignParentBottom="true"
  • Utilisez Android:windowSoftInputMode="adjustResize" Dans votre manifeste, de sorte que le bas de la Window change lorsque le clavier apparaît (comme vous l'avez mentionné)
  • Placez le ImageView dans un ScrollView afin que le ImageView puisse être plus grand que le Window et désactivez le défilement sur le ScrollView en utilisant ScrollView#setEnabled(false)

Voici le fichier de mise en page

<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.so3.MainActivity">
    <ScrollView
        Android:id="@+id/scroll"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content">
        <ImageView
            Android:layout_width="fill_parent"
            Android:layout_height="wrap_content"
            Android:adjustViewBounds="true"
            Android:src="@drawable/stickfigures"/>
    </ScrollView>
    <EditText
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:layout_alignParentBottom="true"
        Android:background="@Android:color/holo_blue_bright"
        Android:text="Please enter text"
        Android:textSize="40sp"
        Android:gravity="center_horizontal"/>
</RelativeLayout>

Voici mon activité

package com.so3;

import Android.app.Activity;
import Android.os.Bundle;
import Android.widget.ScrollView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ScrollView sv = (ScrollView)findViewById(R.id.scroll);
        sv.setEnabled(false);
    }
}

Mon Manifeste Android

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"    package="com.so3" >
    <application
        Android:allowBackup="true"
        Android:icon="@drawable/ic_launcher"
        Android:label="@string/app_name"
        Android:theme="@style/AppTheme" >
        <activity
            Android:name="com.so3.MainActivity"
            Android:windowSoftInputMode="adjustResize"
            Android:label="@string/app_name" >
            <intent-filter>
                <action Android:name="Android.intent.action.MAIN" />
                <category Android:name="Android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Captures d'écran de ma solution

screenshot 1screenshot 2

87
Brian Attwell

Ajouter ScrollView faisait défiler mon image, ce que je voulais éviter, donc j’ai utilisé la calculatrice samples-keyboardheight et onKeyboardHeightChanged recalculée du bas Edittext l'a placé au-dessus du clavier et a utilisé ce drapeau dans Manifest.

Android:windowSoftInputMode="adjustNothing|stateHidden"

Voici KeyboardHeightProvider:

import Android.app.Activity;
import Android.content.res.Configuration;
import Android.graphics.Point;
import Android.graphics.Rect;
import Android.graphics.drawable.ColorDrawable;
import Android.view.Gravity;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewTreeObserver.OnGlobalLayoutListener;
import Android.view.WindowManager.LayoutParams;
import Android.widget.PopupWindow;
/**
 * The keyboard height provider, this class uses a PopupWindow
 * to calculate the window height when the floating keyboard is opened and closed. 
 */
public class KeyboardHeightProvider extends PopupWindow {

    /** The tag for logging purposes */
    private final static String TAG = "sample_KeyboardHeightProvider";

    /** The keyboard height observer */
    private KeyboardHeightObserver observer;

    /** The cached landscape height of the keyboard */
    private int keyboardLandscapeHeight;

    /** The cached portrait height of the keyboard */
    private int keyboardPortraitHeight;

    /** The view that is used to calculate the keyboard height */
    private View popupView;

    /** The parent view */
    private View parentView;

    /** The root activity that uses this KeyboardHeightProvider */
    private Activity activity;

    /** 
     * Construct a new KeyboardHeightProvider
     * 
     * @param activity The parent activity
     */
    public KeyboardHeightProvider(Activity activity) {
        super(activity);
        this.activity = activity;

        LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        this.popupView = inflator.inflate(R.layout.popupwindow, null, false);
        setContentView(popupView);

        setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);

        parentView = activity.findViewById(Android.R.id.content);

        setWidth(0);
        setHeight(LayoutParams.MATCH_PARENT);

        popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    if (popupView != null) {
                        handleOnGlobalLayout();
                    }
                }
            });
    }

    /**
     * Start the KeyboardHeightProvider, this must be called after the onResume of the Activity.
     * PopupWindows are not allowed to be registered before the onResume has finished
     * of the Activity.
     */
    public void start() {

        if (!isShowing() && parentView.getWindowToken() != null) {
            setBackgroundDrawable(new ColorDrawable(0));
            showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0);
        }
    }

    /**
     * Close the keyboard height provider, 
     * this provider will not be used anymore.
     */
    public void close() {
        this.observer = null;
        dismiss();
    }

    /** 
     * Set the keyboard height observer to this provider. The 
     * observer will be notified when the keyboard height has changed. 
     * For example when the keyboard is opened or closed.
     * 
     * @param observer The observer to be added to this provider.
     */
    public void setKeyboardHeightObserver(KeyboardHeightObserver observer) {
        this.observer = observer;
    }

    /**
     * Get the screen orientation
     *
     * @return the screen orientation
     */
    private int getScreenOrientation() {
        return activity.getResources().getConfiguration().orientation;
    }

    /**
     * Popup window itself is as big as the window of the Activity. 
     * The keyboard can then be calculated by extracting the popup view bottom 
     * from the activity window height. 
     */
    private void handleOnGlobalLayout() {

        Point screenSize = new Point();
        activity.getWindowManager().getDefaultDisplay().getSize(screenSize);

        Rect rect = new Rect();
        popupView.getWindowVisibleDisplayFrame(rect);

        // REMIND, you may like to change this using the fullscreen size of the phone
        // and also using the status bar and navigation bar heights of the phone to calculate
        // the keyboard height. But this worked fine on a Nexus.
        int orientation = getScreenOrientation();
        int keyboardHeight = screenSize.y - rect.bottom;

        if (keyboardHeight == 0) {
            notifyKeyboardHeightChanged(0, orientation);
        }
        else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            this.keyboardPortraitHeight = keyboardHeight; 
            notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation);
        } 
        else {
            this.keyboardLandscapeHeight = keyboardHeight; 
            notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation);
        }
    }

    /**
     *
     */
    private void notifyKeyboardHeightChanged(int height, int orientation) {
        if (observer != null) {
            observer.onKeyboardHeightChanged(height, orientation);
        }
    }

    public interface KeyboardHeightObserver {
        void onKeyboardHeightChanged(int height, int orientation);
    }
}

popupwindow.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/popuplayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@Android:color/transparent"
    Android:orientation="horizontal"/>

Voici MainActivity.Java:

import Android.os.Bundle;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;
import Android.view.ViewGroup;

public class MainActivity extends AppCompatActivity  implements KeyboardHeightProvider.KeyboardHeightObserver {

    private KeyboardHeightProvider keyboardHeightProvider;

    private ViewGroup relativeView;
    private float initialY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        keyboardHeightProvider = new KeyboardHeightProvider(this);

        relativeView = findViewById(R.id.bottomEditor);
        relativeView.post(() -> initialY = relativeView.getY());

        View view = findViewById(R.id.activitylayout);
        view.post(() -> keyboardHeightProvider.start());


    }

    @Override
    public void onKeyboardHeightChanged(int height, int orientation) {
        if(height == 0){
            relativeView.setY(initialY);
            relativeView.requestLayout();
        }else {

            float newPosition = initialY - height;
            relativeView.setY(newPosition);
            relativeView.requestLayout();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        keyboardHeightProvider.setKeyboardHeightObserver(null);
    }

    @Override
    public void onResume() {
        super.onResume();
        keyboardHeightProvider.setKeyboardHeightObserver(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        keyboardHeightProvider.close();
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="@+id/activitylayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <ImageView
        Android:id="@+id/imageView2"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:adjustViewBounds="true"
        Android:scaleType="fitCenter"
        />

    <RelativeLayout
        Android:id="@+id/bottomEditor"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_alignParentBottom="true"
        >

        <EditText
            Android:id="@+id/edit_message"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_margin="4dp"
            Android:layout_toStartOf="@+id/btn_send"
            Android:hint="Add caption"
            Android:paddingBottom="12dp"
            Android:paddingLeft="8dp"
            Android:paddingRight="8dp"
            Android:paddingStart="8dp"
            Android:paddingTop="12dp"
            />

        <ImageButton
            Android:id="@+id/btn_send"
            Android:layout_width="48dp"
            Android:layout_height="48dp"
            Android:layout_alignBottom="@+id/edit_message"
            Android:layout_alignParentEnd="true"
            Android:layout_alignParentRight="true"
            Android:layout_marginEnd="4dp"
            Android:layout_marginRight="4dp"
            app:srcCompat="@Android:drawable/ic_menu_send"
            />

    </RelativeLayout>
</RelativeLayout>

P.S. : Le code de calcul de la hauteur du clavier est copié à partir de siebeprojects

Voici un exemple d'application d'application.

3
Nilesh Deokar
final View activityRootView = findViewById(R.id.mainScroll);

activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 1) {

                    Log.d("keyboarddddd      visible", "no");
                    relativeLayoutForImage.setVisibility(View.GONE);
                    relativeLayoutStatic.setVisibility(View.GONE);
                    //Make changes for Keyboard not visible


                } else {

                    Log.d("keyboarddddd      visible ", "yes");

                    relativeLayoutForImage.setVisibility(View.VISIBLE);
                    relativeLayoutStatic.setVisibility(View.VISIBLE);
                    //Make changes for keyboard visible


                }
            }
        });
1
miral patel

La meilleure solution consiste à utiliser un DialogFragment

Afficher le dialogue

DialogFragment.show(getSupportFragmentManager(), DialogFragment.TAG);

Plein écran

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity(), R.style.MainDialog) { //set the style, the best code here or with me, we do not change
        @Override
        public void onBackPressed() {
            super.onBackPressed();
            getActivity().finish();
        }
    };
    return dialog;
}

Style

<style name="MainDialog" parent="@Android:style/Theme.Dialog">
        <item name="Android:windowBackground">@Android:color/transparent</item>
        <item name="Android:windowFrame">@null</item>
        <item name="Android:windowNoTitle">true</item>
        <item name="Android:windowIsFloating">false</item>
        <item name="Android:windowIsTranslucent">true</item>
        <item name="Android:windowContentOverlay">@null</item>
        <item name="Android:background">@null</item>
        <item name="Android:windowAnimationStyle">@null</item>
    </style>

Activité de mise en page

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@color/black">

    <ImageView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" />

</RelativeLayout>

Fragment de dialogue de mise en page

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@color/transparent">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="50dp"
        Android:layout_alignParentBottom="true"
        Android:layout_alignParentStart="true"
        Android:background="@color/background_transparent_60"
        Android:gravity="center_vertical">

        <EditText
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:layout_margin="@dimen/spacing_1_8dp"
            Android:layout_marginLeft="@dimen/spacing_1_8dp"
            Android:layout_marginRight="@dimen/spacing_1_8dp"
            Android:layout_weight="1"
            Android:hint="@string/comment_entry_hint"
            Android:inputType="textMultiLine"
            Android:maxLines="4"
            Android:textColor="@color/white"
            Android:textColorHint="@color/secondary_text_hint"
            Android:textSize="@dimen/text_2_12sp" />

        <ImageView
            Android:layout_width="@dimen/livestream_comment_height"
            Android:layout_height="@dimen/livestream_comment_height"
            Android:layout_margin="@dimen/spacing_1_8dp"
            Android:src="@drawable/ic_send" />

    </LinearLayout>

</RelativeLayout>
0
Nankai

À mon avis, la façon la plus simple de procéder est la suivante combinaison des deux modifications:

Android:windowSoftInputMode="adjustResize"

dans votre AndroidManifest.xml

+

getWindow().setBackgroundDrawable(your_image_drawable);

dans votre activité dans la méthode @onCreate ()

Ça marche pour moi.

0
valerybodak

Pour moi, je ne voulais pas supposer que les hauteurs de clavier étaient une certaine mesure. Quel que soit le point de vue qui vous préoccupe, créez un onTouchListener puis procédez comme suit:

    setOnTouchListener(new OnTouchListener()  {



        Runnable shifter=new Runnable(){
            public void run(){
                try {
                    int[] loc = new int[2];                 
                    //get the location of someview which gets stored in loc array
                    findViewById(R.id.someview).getLocationInWindow(loc);
                    //shift so user can see someview
                    myscrollView.scrollTo(loc[0], loc[1]);   
                }
                catch (Exception e) {
                    e.printStackTrace();
                }   
            }}
        };

        Rect scrollBounds = new Rect();
        View divider=findViewById(R.id.someview);
        myscollView.getHitRect(scrollBounds);
        if (!divider.getLocalVisibleRect(scrollBounds))  {
            // the divider view is NOT  within the visible scroll window thus we need to scroll a bit.
            myscollView.postDelayed(shifter, 500);
        }



    });

// nous faisons essentiellement un runnable qui défile vers un nouvel emplacement d’une vue que vous voulez VU visible à l’écran. vous n'exécutez cette exécution que si ce n'est pas dans les limites de scrollviews (ce n'est pas à l'écran). De cette façon, il fait passer la vue de défilement à la vue référencée (dans mon cas, "someview", qui était un diviseur de ligne).

0
j2emanue

La solution qui a fonctionné pour moi était dans AndroidManifest.xml dans cette balise d'activité qui vient d'être mise

Android:windowSoftInputMode="stateHidden|adjustResize|adjustNothing"

Tout est mis en place. J'espère que cela fonctionnera pour vous.

0
Ali Nawaz