Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyboard covers screen instead of pushing up layout?

I have a problem where when I click on my keyboard, the contents of my screen doesn't get pushed up--rather the keyboard simply overlaps everything (namely covers my ListView) on my screen. This is the structure of my layout:

<ScrollView>
  <RelativeLayout>
  </RelativeLayout>
</ScrollView>
<ListView>
</ListView>
<LinearLayout>
  <EditText></EditText>
</LinearLayout>

I nested my RelativeLayout in a ScrollView because I thought that would make my entire layout scrollable, which would "push up" all the layouts so that the user can view those parts while typing his or her response. I also have in my AndroidManifest.xml: android:windowSoftInputMode="adjustResize|stateVisible|stateAlwaysHidden" Here is an image of what is happening:

Image of what is happening

And here is my code. Any help would be appreciated!

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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" android:fitsSystemWindows="true"
    xmlns:fresco="http://schemas.android.com/tools"
    android:id="@+id/comments_coordinator_layout">

<android.support.design.widget.AppBarLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/comments_appbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/comments_coordinator_layout"
        >

        <RelativeLayout
            android:layout_marginTop="?attr/actionBarSize"
            android:id="@+id/view_post"
            android:layout_width="match_parent"
            android:paddingRight="5dp"
            android:paddingLeft="5dp"
            android:orientation="horizontal"
            android:layout_height="175dp"
            android:background="#e6e6e6">

            <com.facebook.drawee.view.SimpleDraweeView
                android:layout_marginTop="15dp"
                android:id="@+id/poster_picture"
                android:layout_width="75dp"
                android:layout_height="75dp"
                android:layout_marginLeft="10dp"
                fresco:placeholderImage="@mipmap/blank_prof_pic"
                fresco:roundedCornerRadius="5dp"
                />

            <TextView
                android:layout_marginLeft="5dp"
                android:layout_marginTop="15dp"
                android:layout_toRightOf="@id/poster_picture"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="15sp"
                android:textStyle="bold"
                android:id="@+id/poster_name"/>

            <TextView
                android:layout_alignParentRight="true"
                android:layout_marginTop="15dp"
                android:layout_toRightOf="@id/poster_name"
                android:layout_marginLeft="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="15sp"
                android:id="@+id/post_date"/>

            <TextView
                android:layout_marginLeft="5dp"
                android:layout_toRightOf="@id/poster_picture"
                android:layout_below="@id/poster_name"
                android:textSize="20sp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/view_status" />

        </RelativeLayout>

    </ScrollView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:layout_marginTop="225dp"
            android:id="@+id/lv_comments_feed"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/send_message">
        </ListView>


        <LinearLayout
            android:id="@+id/send_message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal" >

            <EditText
                android:id="@+id/write_comment"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|center_horizontal"
                android:layout_weight="5"
                android:gravity="top|left"
                android:hint="Comment back!"
                android:inputType="textMultiLine"
                android:scrollHorizontally="false" />

            <Button
                android:id="@+id/send_comment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|center_horizontal"
                android:gravity="center"
                android:text="send"
                android:textAppearance="?android:attr/textAppearanceMedium" />
        </LinearLayout>

    </RelativeLayout>


</android.support.design.widget.CoordinatorLayout>

EDIT: My attempt to add in a parent LinearLayout for ScrollView. Issue is now: The vertically scrolling ScrollView should not contain another vertically scrolling widget when I hover over ListView

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:fitsSystemWindows="true"
    xmlns:fresco="http://schemas.android.com/tools"
    android:id="@+id/comments_coordinator_layout">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/comments_appbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/comments_coordinator_layout"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <RelativeLayout
                android:layout_marginTop="?attr/actionBarSize"
                android:id="@+id/view_post"
                android:layout_width="match_parent"
                android:paddingRight="5dp"
                android:paddingLeft="5dp"
                android:orientation="horizontal"
                android:layout_height="175dp"
                android:background="#e6e6e6">

                <com.facebook.drawee.view.SimpleDraweeView
                    android:layout_marginTop="15dp"
                    android:id="@+id/poster_picture"
                    android:layout_width="75dp"
                    android:layout_height="75dp"
                    android:layout_marginLeft="10dp"
                    fresco:placeholderImage="@mipmap/blank_prof_pic"
                    fresco:roundedCornerRadius="5dp"
                    />

                <TextView
                    android:layout_marginLeft="5dp"
                    android:layout_marginTop="15dp"
                    android:layout_toRightOf="@id/poster_picture"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="15sp"
                    android:textStyle="bold"
                    android:id="@+id/poster_name"/>

                <TextView
                    android:layout_alignParentRight="true"
                    android:layout_marginTop="15dp"
                    android:layout_toRightOf="@id/poster_name"
                    android:layout_marginLeft="5dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="15sp"
                    android:id="@+id/post_date"/>

                <TextView
                    android:layout_marginLeft="5dp"
                    android:layout_toRightOf="@id/poster_picture"
                    android:layout_below="@id/poster_name"
                    android:textSize="20sp"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/view_status" />

            </RelativeLayout>

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <ListView
                    android:layout_marginTop="225dp"
                    android:id="@+id/lv_comments_feed"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_above="@+id/send_message">
                </ListView>


                <LinearLayout
                    android:id="@+id/send_message"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="5dp"
                    android:layout_alignParentBottom="true"
                    android:orientation="horizontal" >

                    <EditText
                        android:id="@+id/write_comment"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical|center_horizontal"
                        android:layout_weight="5"
                        android:gravity="top|left"
                        android:hint="Comment back!"
                        android:inputType="textMultiLine"
                        android:scrollHorizontally="false" />

                    <Button
                        android:id="@+id/send_comment"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical|center_horizontal"
                        android:gravity="center"
                        android:text="send"
                        android:textAppearance="?android:attr/textAppearanceMedium" />
                </LinearLayout>

            </RelativeLayout>

        </LinearLayout>


    </ScrollView>

</android.support.design.widget.CoordinatorLayout>

EDIT: I think the best solution may be to create a custom ListView... that contains the same layout that is in each ListView item. Any suggestions or ideas on how to implement this?

EDIT: Tried @VanillaBoy's answer. I know the image produced is because I have marginTop = 225 dp but even if I remove it, when I click on my EditText, it only shows my ListView and my RelativeLayout above is hidden Image

EDIT: As per @Fllo's answer, I am still able to reproduce the error I had in the beginning with this layout, and so here is what I have in my layout. Also if it helps my Android Manifest looks like this android:windowSoftInputMode="adjustResize|stateAlwaysHidden">.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:fitsSystemWindows="true"
    xmlns:fresco="http://schemas.android.com/tools"
    android:id="@+id/comments_coordinator_layout">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/comments_appbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/comments_coordinator_layout"
        android:fillViewport="true"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <RelativeLayout
                android:layout_marginTop="?attr/actionBarSize"
                android:id="@+id/view_post"
                android:layout_width="match_parent"
                android:paddingRight="5dp"
                android:paddingLeft="5dp"
                android:orientation="horizontal"
                android:layout_height="175dp"
                android:background="#e6e6e6">

                <com.facebook.drawee.view.SimpleDraweeView
                    android:layout_marginTop="15dp"
                    android:id="@+id/poster_picture"
                    android:layout_width="75dp"
                    android:layout_height="75dp"
                    android:layout_marginLeft="10dp"
                    fresco:placeholderImage="@mipmap/blank_prof_pic"
                    fresco:roundedCornerRadius="5dp"
                    />

                <TextView
                    android:layout_marginLeft="5dp"
                    android:layout_marginTop="15dp"
                    android:layout_toRightOf="@id/poster_picture"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="15sp"
                    android:textStyle="bold"
                    android:id="@+id/poster_name"/>

                <TextView
                    android:layout_alignParentRight="true"
                    android:layout_marginTop="15dp"
                    android:layout_toRightOf="@id/poster_name"
                    android:layout_marginLeft="5dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="15sp"
                    android:id="@+id/post_date"/>

                <TextView
                    android:layout_marginLeft="5dp"
                    android:layout_toRightOf="@id/poster_picture"
                    android:layout_below="@id/poster_name"
                    android:textSize="20sp"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/view_status" />

            </RelativeLayout>

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <LinearLayout
                    android:orientation="vertical"
                    android:id="@+id/container_list"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_above="@+id/send_message">
                </LinearLayout>


                <LinearLayout
                    android:id="@+id/send_message"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="5dp"
                    android:layout_alignParentBottom="true"
                    android:orientation="horizontal" >

                    <EditText
                        android:id="@+id/write_comment"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical|center_horizontal"
                        android:layout_weight="5"
                        android:gravity="top|left"
                        android:hint="Comment back!"
                        android:inputType="textMultiLine"
                        android:scrollHorizontally="false" />

                    <Button
                        android:id="@+id/send_comment"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical|center_horizontal"
                        android:gravity="center"
                        android:text="send"
                        android:textAppearance="?android:attr/textAppearanceMedium" />
                </LinearLayout>

            </RelativeLayout>

        </LinearLayout>


    </ScrollView>

</android.support.design.widget.CoordinatorLayout>
like image 310
user1871869 Avatar asked Oct 31 '22 13:10

user1871869


1 Answers

Using an inner ListView with ScrollView should be avoided in Android. Indeed, these layouts have their own scroll detections and gestures. The solutions are to prevent the scroll gesture on the list or to calculate the height and expand it by default. But this will make too much work and don't respect the Android pattern and guidelines.

Instead of replace ListView by LinearLayout and keep the parent's ScrollView, as my old answer pointed out, I found a possible workaround, which has these steps:

  • Create your own ListView
  • Override onSizeChanged() which redraws the ListView when keyboard is opening
  • Get the lastVisiblePosition and retrieve its height in the previous method
  • Finally, move the list to the previous lastVisiblePosition and calculate the offset
  • Beside, set a headerView for the header picture container
  • And you need to update the child item's height before the user opens the keyboard, so you could update the value in onClickListener of the EditText

And it needs this kind of layouts:

  • layout's activity:

    <CoordinatorLayout>
        <AppBarLayout>
            ...
        </AppBarLayout>
        <RelativeLayout>
            <CustomListView />
            <LinearLayout>
                ...
            </LinearLayout>
        </RelativeLayout>
    </CoordinatorLayout>
    
  • header's layout (which will be above the list):

    <RelativeLayout>
        <SimpleDraweeView />
        <TextView />
        ...
    </RelativeLayout>
    

Hum, that's all... So, good to go:

Create a Listview:

public class CustomListView extends ListView {
    // last height item variable (updated from Activity)
    public int lastItemHeight = 0;

    public CustomListView(Context context) {
        super(context, null);
    }

    public CustomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

Override onSizeChanged():

@Override
protected void onSizeChanged(int w, final int h, int oldw, int oldh) {
    // save last position visible before resize
    final int lastPosition = super.getLastVisiblePosition();
    // call super SizeChanged method
    super.onSizeChanged(w, h, oldw, oldh);
    // after resizing, show the last visible item at the bottom of new listview's height, above the edit text
    // see : http://developer.android.com/reference/android/widget/AbsListView.html#setSelectionFromTop(int, int)
    super.setSelectionFromTop(lastPosition, (h - lastItemHeight));
}

That's all for the ListView.
The lastItemHeight variable will be updated when the user clicks on the input (below the list, thanks to setting your "header" picture container as a headerView in your Activity).

Now, let see the Activity:

Setup your custom ListView and your Adapter:

// get custom listview element
final CustomListView list = (CustomListView) findViewById(R.id.container_list);
// example items child
ArrayList<String> items = new ArrayList<>();
for (int n=0; n<25; ++n) items.add("Blablabla n."+n);
// example adapter
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.item_list_text_simple, android.R.id.text1, items);

Create the HeaderView and set the Adapter:

// prepare the header content with picture
View header = getLayoutInflater().inflate(R.layout.test_header_image, null);
// set datas to the header elements (example)
Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) header.findViewById(R.id.poster_picture);
draweeView.setImageURI(uri);
// add the header to listview
list.addHeaderView(header, null, false);
// set the adapter
list.setAdapter(adapter);

Handle the softkeyboard open with EditText.setOnClickListener:

// when the user clicks on EditText...
editMessage.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // set a new Thread
        list.post(new Runnable() {
            @Override
            public void run() {
                // get last position of child
                int lastPosition = list.getLastVisiblePosition() - 1;
                // if the list can give the view's last child
                if (list.getChildAt(lastPosition) != null) {
                    // update the height of the last child in custom listview
                    list.lastItemHeight = list.getChildAt(lastPosition).getHeight();
                }
            }
        });
    }
});

That's all for the code! And the last thing (Ow.. where is the end?), here's the layouts:

The main layout of Activity:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/comments_coordinator_layout"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent">

        <android.support.v7.widget.Toolbar ... />
    </android.support.design.widget.AppBarLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="?attr/actionBarSize">

        <com.package.name.CustomListView
            android:id="@+id/container_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_above="@+id/send_message"/>

        <LinearLayout
            android:id="@+id/send_message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal" >

            <EditText ... />

            <Button ... />
        </LinearLayout>
    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

The head layout of ListView:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/view_post"
    android:layout_width="match_parent"
    android:layout_height="225dp"
    android:paddingRight="5dp"
    android:paddingLeft="5dp"
    android:orientation="horizontal"
    android:background="#e6e6e6">

    <com.facebook.drawee.view.SimpleDraweeView ... />

    <TextView ... />

    <TextView ... />

    <TextView ... />
</RelativeLayout>

Aw! I've finally finished. I really hope you will be able to have the right behaviour. I tested it, and it seems to work good enough.
Here's another workaround with adjustPan, but you have to keep your list starting at the bottom. Whereas this solution keeps any child at the bottom of the list when it's resize.

Hope you'll enjoy it ;)

like image 155
Blo Avatar answered Nov 08 '22 04:11

Blo