Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a view with a Edittext field on top of an ImageView. When the keyboard comes up I want the window to resize so that EditText is no longer hidden by the keyboard. In the AndroidManifest file I declared android:windowSoftInputMode="adjustResize" and the screen is resized but the issue is that I want the ImageView to not be re-sized. How can I make the ImageView unaffected?

Could I inflate an additional layout with just the ImageView or will the resize still affect it? enter image description here

like image 809
pdfj Avatar asked Jan 18 '14 07:01

pdfj


People also ask

What is window soft input mode?

Android windowSoftInputMode – Resize the application for the soft-keyboard. Posted on October 25, 2010 by Lars Vogel. Android has the so-called Input Method Framework to support different input methods, e.g. keyboard, soft-keyboard, handwriting etc.

How do I scroll up layout when clicking on Edittext?

try this android:windowSoftInputMode="adjustResize" in your activity in manifest file.


2 Answers

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

like image 97
Brian Attwell Avatar answered Sep 17 '22 02:09

Brian Attwell


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.

like image 25
Nilesh Deokar Avatar answered Sep 19 '22 02:09

Nilesh Deokar