In my test app I disable expansion of AppBarLayout
when it is collapsed (by scrolling RecycleView
). I do that by adding addOnOffsetChangedListener
to AppBarLayout
.
However, when I click EditText
it expands again but, I do not want it to expand.
How to disable the expansion of AppBarLayout
when I click EditText
?
I have put the whole code, so that everyone can copy/paste the code, create new project and test this fast.
Here is how the .gif looks
Here is XML code:
<?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:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="400dp"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleTextAppearance="@android:color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beachcroatia"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?attr/actionBarSize"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<LinearLayout
android:id="@+id/messages_linear_layout"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_gravity="bottom"
android:background="#E1F5FE"
android:orientation="horizontal"
tools:layout_editor_absoluteY="453dp">
<EditText
android:id="@+id/editText_messageBox"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_gravity="center"
android:layout_weight="0.85"
android:hint="Enter a message"/>
<ImageView
android:id="@+id/messages_sendArrow"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_weight="0.15"
android:src="@drawable/ic_send_message_" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
Here is full MainActivity code:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerChat;
private AdapterChat mAdapterChat;
CollapsingToolbarLayout collapsingToolbarLayout;
AppBarLayout appBarLayout;
ImageView sendMessageImageViewButton;
EditText editTextMessage;
private List<Message> messagesList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
appBarLayout = findViewById(R.id.app_bar_layout);
sendMessageImageViewButton = findViewById(R.id.messages_sendArrow);
editTextMessage = findViewById(R.id.editText_messageBox);
messagesList = new ArrayList<>();
messagesList.addAll(getMessagesList());
mRecyclerChat = findViewById(R.id.recycleView);
LinearLayoutManager manager = new LinearLayoutManager(this);
mRecyclerChat.setLayoutManager(manager);
mAdapterChat = new AdapterChat(this, messagesList);
mRecyclerChat.setAdapter(mAdapterChat);
//move to the last item in recycleview
mRecyclerChat.getLayoutManager().scrollToPosition(mAdapterChat.getMessagesObekt().size() - 1);
editTextMessage.requestFocus();
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) {
// Collapsed
Toast.makeText(MainActivity.this, "Collapsed", Toast.LENGTH_SHORT).show();
// disable expanding
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
params.setScrollFlags(0);
} else if (verticalOffset == 0) {
Toast.makeText(MainActivity.this, "Extend", Toast.LENGTH_SHORT).show();
// Expanded
} else {
// Somewhere in between
}
}
});
//sending new message and updating recycleview
sendMessageImageViewButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Message Send", Toast.LENGTH_SHORT).show();
mAdapterChat.updateLastMessage(new Message(editTextMessage.getText().toString()));
editTextMessage.getText().clear();
mRecyclerChat.getLayoutManager().scrollToPosition(mAdapterChat.getMessagesObekt().size() - 1);
}
});
}
//ading some items to a list
private List<Message> getMessagesList() {
List<Message> mMessages = new ArrayList<>();
for (int i = 0; i < 200; i++) {
mMessages.add(new Message("message " + i));
}
return mMessages;
}
}
Here is my message class where i add dummy data to show in RecycleView
public class Message {
private String message;
public Message(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Here is RecycleView Adapter code:
package com.example.petar.collapsingtolbartestiramo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class AdapterChat extends RecyclerView.Adapter<AdapterChat.ChatHolder> {
private LayoutInflater mInflater;
private List<Message> messagesObekt;
public AdapterChat(Context context, List<Message> listOfMassages) {
mInflater = LayoutInflater.from(context);
messagesObekt = new ArrayList<>();
messagesObekt.addAll(listOfMassages);
notifyDataSetChanged();
}
public void updateChat(List<Message> porukeObjekt){
this.messagesObekt.addAll(porukeObjekt);
notifyDataSetChanged();
}
public void updateLastMessage(Message porukeObjekt) {
this.messagesObekt.add(porukeObjekt);
//notifyDataSetChanged();
notifyItemInserted(messagesObekt.size());
}
public List<Message> getMessagesObekt() {
return messagesObekt;
}
@Override
public ChatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.list_message, parent, false);
ChatHolder holder = new ChatHolder(view, messagesObekt);
return holder;
}
@Override
public void onBindViewHolder(ChatHolder holder, int position) {
holder.textViewMessage.setText(messagesObekt.get(position).getMessage());
}
@Override
public int getItemCount() {
return messagesObekt.size();
}
public static class ChatHolder extends RecyclerView.ViewHolder {
TextView textViewMessage;
public ChatHolder(View itemView, List<Message> messagesObekt) {
super(itemView);
textViewMessage = itemView.findViewById(R.id.rv_message);
}
}
}
Here is RecycleView item XML code (list_message.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:orientation="vertical">
<TextView
android:id="@+id/rv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Poruka Ovdje"
android:textSize="14sp"/>
</LinearLayout>
:
EDIT
I tried adding focus listener to EditText
but, that did not helped. This is how i try:
editTextMessage.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
appBarLayout.setExpanded(false);
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
params.setScrollFlags(0);
}
}
});
I do not know is the best solution, but it works nice. If someone has better solution, feel free to write it.
There is indeed a better, cleaner and simpler solution.
The culprit that leads to this "issue" is actually a feature that was added by Google inside AppBarLayout.ScrollingViewBehavior
. That's the one you set via app:layout_behavior="@string/appbar_scrolling_view_behavior"
. Inside that class, onRequestChildRectangleOnScreen
calls setExpanded(false, !immediate)
whenever the keyboard is shown. You simply override this method and return false to disable this default behavior. Add this class to your project:
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.appbar.AppBarLayout;
public class FixedScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {
public FixedScrollingViewBehavior() {
super();
}
public FixedScrollingViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onRequestChildRectangleOnScreen(@NonNull CoordinatorLayout parent,
@NonNull View child, @NonNull Rect rectangle, boolean immediate) {
return false;
}
}
Then just use this new class by changing app:layout_behavior="@string/appbar_scrolling_view_behavior"
to app:layout_behavior="your.source.package.FixedScrollingViewBehavior"
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With