2

I'm disabling the normal top action bar by using:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">

& I want to use a bottom action bar to have the done/cancel actions like this calendar app: enter image description here

but when I try to write something to the editTexts available in the scrollView, the bottom action bar hides the fields, & I want it to be visible like also the calendar app below: enter image description here

So, how can I achieve similar behavior? (so the bottom action bar won't hide any field when opening the soft keyboard),

I'm using code like this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="vertical"
android:weightSum="1">

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    android:fillViewport="false"
    android:id="@+id/formScrollView">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <!-- all form fields goes here -->
    </LinearLayout>

</ScrollView>

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:padding="@dimen/done_button_padding"
    android:id="@+id/happeningDoneLayout">

    <Button
        android:id="@+id/doneButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="@string/done"
        android:layout_alignParentBottom="true"/>
    <Button
        android:id="@+id/cancelButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="@string/cancel"
        android:layout_alignParentBottom="true"/>
</FrameLayout>

</RelativeLayout>
AbdelHady
  • 9,334
  • 8
  • 56
  • 83

3 Answers3

2

Simplest thing to do is to prevent your layout from being resized when the virtual keyboard comes up:

    <activity
        android:name=".ShareFromDriveActivity_"
        android:hardwareAccelerated="true"
        android:label="@string/titleSharingCalendar"
        android:launchMode="standard"
        android:parentActivityName=".AppWidgetConfigure_"
        android:screenOrientation="sensor"
        android:theme="@style/Theme.Materialamberpurple"
        android:windowSoftInputMode="stateHidden|adjustPan" >
        <intent-filter>
            <action android:name="de.kashban.android.picturecalendar.INTENT_ACTION_SHARE_FROM_DRIVE" />
        </intent-filter>
    </activity>

The important line is android:windowSoftInputMode="stateHidden|adjustPan". stateHidden ensures the keyboard is not opened up when starting the activity even if an EditText has focus.

adjustPan is what you are looking for: The Layout will no longer be resized (including your lower buttons), but the keyboad will overlay the layout. It is still possible to scroll them into the visible part, but when the keyboard comes up, they are not visible.

Source: Android Guides

Perhaps this setting alone will help your case.

If that's not enough and you require the Buttons to be really gone, try using this:

// Detect soft keyboard visibility changes
final SoftKeyboardStateHelper softKeyboardStateHelper = 
        new SoftKeyboardStateHelper(lyt_share_from_drive_main);
softKeyboardStateHelper.addSoftKeyboardStateListener(this);

SoftKeyboardStateHelper is a class from Artem Zinnatullin to detect state changes of the Softkeyboard:

/**
 * 
 */
package de.kashban.android.picturecalendar.util.local;

/**
 * @author Artem Zinnatullin
 * http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android/9108219#9108219
 * Usage: final SoftKeyboardStateHelper softKeyboardStateHelper = new SoftKeyboardStateHelper(findViewById(R.id.activity_main_layout);
 *        softKeyboardStateHelper.addSoftKeyboardStateListener(...);
 */
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;

import java.util.LinkedList;
import java.util.List;

public class SoftKeyboardStateHelper implements ViewTreeObserver.OnGlobalLayoutListener {

    public interface SoftKeyboardStateListener {
        void onSoftKeyboardOpened(int keyboardHeightInPx);
        void onSoftKeyboardClosed();
    }

    private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
    private final View activityRootView;
    private int        lastSoftKeyboardHeightInPx;
    private boolean    isSoftKeyboardOpened;

    public SoftKeyboardStateHelper(View activityRootView) {
        this(activityRootView, false);
    }

    public SoftKeyboardStateHelper(View activityRootView, boolean isSoftKeyboardOpened) {
        this.activityRootView     = activityRootView;
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @Override
    public void onGlobalLayout() {
        final Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
            isSoftKeyboardOpened = true;
            notifyOnSoftKeyboardOpened(heightDiff);
        } else if (isSoftKeyboardOpened && heightDiff < 100) {
            isSoftKeyboardOpened = false;
            notifyOnSoftKeyboardClosed();
        }
    }

    public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
    }

    public boolean isSoftKeyboardOpened() {
        return isSoftKeyboardOpened;
    }

    /**
     * Default value is zero (0)
     * @return last saved keyboard height in px
     */
    public int getLastSoftKeyboardHeightInPx() {
        return lastSoftKeyboardHeightInPx;
    }

    public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.add(listener);
    }

    public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.remove(listener);
    }

    private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
        this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;

        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardOpened(keyboardHeightInPx);
            }
        }
    }

    private void notifyOnSoftKeyboardClosed() {
        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardClosed();
            }
        }
    }
}

In your activity implement the Interface SoftKeyboardStateListener and override these methods:

@Override
public void onSoftKeyboardOpened(int keyboardHeightInPx) {
    if (D.DEBUG_APP) Log.d(TAG, "onSoftKeyboardOpened() called with keyboard height " + keyboardHeightInPx);
    rdgVisibility.setVisibility(View.GONE);
    if (tvPermissionLabel != null)
        tvPermissionLabel.setVisibility(View.GONE);
    lyt_ShareDriveOkCancel.setVisibility(View.GONE);
    cbShareWithDev.setVisibility(View.GONE);

}

@Override
public void onSoftKeyboardClosed() {
    if (D.DEBUG_APP) Log.d(TAG, "onSoftKeyboardClosed() called.");
    rdgVisibility.setVisibility(View.VISIBLE);
    if (tvPermissionLabel != null)
        tvPermissionLabel.setVisibility(View.VISIBLE);
    lyt_ShareDriveOkCancel.setVisibility(View.VISIBLE);
    cbShareWithDev.setVisibility(View.VISIBLE);
}

In these two methods change the Visibility of your lower Buttons accordingly. Done.

Here's how it looks in my app:

Full Dialog Screenshot

Keyboard is closed, full layout visible

Most Controls hidden Screenshot

Keyboard is open, all controls but EditText gone. Reason is that the EditText could span several lines and on small screens it was too cluttered with the full layout in place.

1

Android Keyboard hides EditText

android:windowSoftInputMode="adjustPan|adjustResize"

That should give you the effect your looking for. Put that in the manifest of the relevant activity.

Community
  • 1
  • 1
Razz
  • 220
  • 1
  • 6
  • but this is not the problem exactly, I need a behavior similar to the calendar app in the question, so the bottom bar will still be visible above the soft keyboard, but will push the editText a little bit farther than usual to be visible above the bar – AbdelHady Oct 20 '14 at 13:45
1

To make sure the bottom action bar will not hide any other controls, the ScrollView and the bar can be stacked in a vertical linear layout. This allows the ScrollView to shrink/expand with the focused control visible when the keyboard appears/disappears, while keeping the bottom action bar always visible at the bottom of the screen below the ScrollView.

adjustPan should not be used with this solution.

The weights are distributed such that the ScrollView is the part that would change its height dynamically.

Here's a minimized sample of the code:

<?xml version="1.0" encoding="utf-8"?>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


        <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/formScrollView"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            ... >

                ...

        </ScrollView>

        <FrameLayout
            android:id="@+id/bottomBar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"
            ... >

                ...

        </FrameLayout>

    </LinearLayout>
Ahmed Nasser
  • 210
  • 1
  • 9