Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AppBarLayout CollapsingToolbar how to disable expand on EditText click?

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

enter image description here

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);
                }
            }
        });
like image 483
NoName Avatar asked Jun 09 '18 12:06

NoName


1 Answers

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".

like image 131
0101100101 Avatar answered Nov 20 '22 09:11

0101100101