Android: Resize only parts of view with soft keyboard on screen Android: Resize only parts of view with soft keyboard on screen android android

Android: Resize only parts of view with soft keyboard on screen


The full solution involves a few key points

  • Use RelativeLayout, so that Views can be setup to overlap one another
  • Align the EditText with the bottom of the Windows using android:layout_alignParentBottom="true"
  • Use android:windowSoftInputMode="adjustResize" in your manifest, so that the bottom of the Window changes when the keyboard pops up (as you mentioned)
  • Put the ImageView inside a ScrollView so that the ImageView can be larger than the Window, and disable scrolling on the ScrollView by using ScrollView#setEnabled(false)

Here is the layout file

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

Here is my Activity

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

My AndroidManifest

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

Screen shots of my solution

screenshot 1screenshot 2


Adding ScrollView was making my image scrollable which I wanted to avoid so I used this samples-keyboardheight calculator and onKeyboardHeightChanged recalculated position of the bottom Edittext placed it above Keyboard and used this flag in Manifest.

android:windowSoftInputMode="adjustNothing|stateHidden"

Here is 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"/>

Here is 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. : Keyboard height calculation code is copied from siebeprojects

Here is demo example app of implementation.


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