24

I want to build a message layout like WhatsApp. I have an EditText and a RecyclerView.

The problem is when the keyboard appears, it hide the messages at the bottom of the list.

So let's say this the RecyclerView:

---item 1---  
---item 2---  
---item 3---  
---item 4---  
---EditText---

when the the keyboard appears, I get this:

---item 1---  
---item 2---  
---EditText---
---Keyboard---  

but I want to get this:

---item 3---  
---item 4---  
---EditText---
---Keyboard---

NOTE: when I set linearLayoutManager.setStackFromEnd(true); it works but when there is one message it appears at the bottom of the page.

afollestad
  • 2,929
  • 5
  • 30
  • 44
david
  • 3,310
  • 7
  • 36
  • 59

5 Answers5

29

set adjustresize for the activity with recyclerview and editText :

android:windowSoftInputMode="adjustResize"

add onLayoutChangeListener to your RecyclerView and set scrollToPosition to data.size() -1 in onLayoutChange:

  mRecyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
 @Override

public void onLayoutChange(View v, int left, int top, int right,int bottom, int oldLeft, int oldTop,int oldRight, int oldBottom)
{

mRecyclerView.scrollToPosition(mMessages.size()-1);

}
    });
devdoot Ghosh
  • 391
  • 3
  • 2
  • and if you use reverseLayout and setStackFromEnd = true then need use scrollToPosition(0), at what with post. Example: `recycler.post{recycler.scrollToPosition(0)}` – abbath0767 Feb 12 '19 at 12:16
  • 1
    Thanks! Probably you should check `mMessages.size()` > 0 in order not to get an exception. See my answer below in Kotlin. – CoolMind Aug 31 '20 at 09:58
  • After implementing this I cannot even scroll recycler view it pushes me to the bottom (conversation view case) when I try to scroll a bit – MRamzan Dec 11 '20 at 09:41
2

The way I did it, is to set setStackFromEnd() according the size of the item holder, and set adjustResize in androidManifest.

This is how I check:

if (recycleView.getChildCount() == items.size()){
    mLayoutManager.setStackFromEnd(true);
}
else{
    mLayoutManager.setStackFromEnd(false);
}
VHanded
  • 2,079
  • 4
  • 30
  • 55
  • What's the meaning of the condition here? What if `setStackFromEnd(true)` for all cases? – Jian Guo Oct 10 '19 at 09:36
  • Not a good solution. Even if you insert it into `addOnLayoutChangeListener` as in the top answer, it will lift the `RecyclerView` if it is already scrolled to the end. Also, if the `RecyclerView` contains few items, it will have an empty space above, see https://stackoverflow.com/questions/44873389/android-only-setstackfromend-only-if-recycleview-list-is-larger-than-screen. – CoolMind Aug 31 '20 at 10:53
2

I am not good at English. Use ChatRecyclerView and set the stackfromend of the linearlayoutmanager to false.

public class ChatRecyclerView extends RecyclerView {
    private int oldHeight;

    public ChatRecyclerView(Context context) {
        super(context);
    }

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

    public ChatRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        int delta = b - t - this.oldHeight;
        this.oldHeight = b - t;
        if (delta < 0) {
            this.scrollBy(0, -delta);
        }
    }
}
1

I got the solution from Push up content when clicking in edit text

Just put below code in

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
hikky36
  • 323
  • 2
  • 14
1

Thanks to devdoot Ghosh in Kotlin (I check if adapter size > 0):

recycler_view.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
    // Wait till recycler_view will update itself and then scroll to the end.
    recycler_view.post {
        adapter?.itemCount?.takeIf { it > 0 }?.let {
            scrollToPosition(it - 1)
        }
    }
}

In AndroidManifest add to the activity:

<activity
    ...
    android:windowSoftInputMode="adjustResize"
    />

Note that the RecyclerView will scroll to the last item.

CoolMind
  • 26,736
  • 15
  • 188
  • 224