user2386226
user2386226

Reputation:

How do I show my fab on scroll when the first item in the recycler view is not visible but hide when the first item is visible?

So I am trying to implement a FAB button such that, when I scroll my recycler view and the first item is not visible (scrolled up etc) , fab button should be visible, else it should be hidden if the first position is showing. Right now I have implemented the code, but it doesn't show the fab button at all, just wanted to know what I am doing wrong?

my xml code is below:

<Linearlayout ....


    <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        <android.support.v4.widget.SwipeRefreshLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/pullToRefreshLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/myRecyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </android.support.v4.widget.SwipeRefreshLayout>

            <android.support.design.widget.FloatingActionButton
                android:id="@+id/emailFab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:src="@android:drawable/ic_dialog_email"
                app:layout_anchor="@id/myRecyclerView"
                android:layout_gravity="bottom|end"
                app:layout_behavior="com.example.fab.ScrollAwareFABBehavior"
                app:layout_anchorGravity="bottom|end"
                />
        </FrameLayout>

</LinearLayout>

my Kotlin code is below:

val positionView = (myRecyclerView.getLayoutManager() as LinearLayoutManager).findFirstVisibleItemPosition()

myRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                if (dy >0 && positionView > 0) {
                    emailFab.show();
                } else  {
                    emailFab.hide();
                }
            }

Any ideas how to go about it?

Thanks!

Upvotes: 1

Views: 1482

Answers (2)

Harkal
Harkal

Reputation: 1828

This code is 100% working:

public class TestActivity extends AppCompatActivity {

    private static final String TAG = "TestActivity";

    private ArrayList<String> datas = new ArrayList<>();

    private FloatingActionButton fabButton;
    private RecyclerView recyclerView;
    private LinearLayoutManager linearLayoutManager;
    private DataAdapter dataAdapter;

    private boolean isFabVisible = false;

    private OnFabVisibilityCallback onFabVisibilityCallback;

    public void setOnFabVisibilityCallback(OnFabVisibilityCallback onFabVisibilityCallback) {
        this.onFabVisibilityCallback = onFabVisibilityCallback;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_contacts);

        datas.add("one");
        datas.add("two");
        datas.add("three");
        datas.add("four");
        datas.add("five");
        datas.add("six");
        datas.add("seven");
        datas.add("eight");
        datas.add("nine");
        datas.add("ten");

        fabButton = (FloatingActionButton)findViewById(R.id.fabButton);
        fabButton.setVisibility(View.GONE);
        recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
        linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(linearLayoutManager);
        dataAdapter = new DataAdapter(this, datas);
        recyclerView.setAdapter(dataAdapter);


        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                if(linearLayoutManager.findFirstVisibleItemPosition() == 0){
                    //hide
                    if(onFabVisibilityCallback != null){
                        onFabVisibilityCallback.onChange(false);
                    }
                }else{
                    //show
                    if(onFabVisibilityCallback != null){
                        onFabVisibilityCallback.onChange(true);
                    }
                }

            }
        });

        setOnFabVisibilityCallback(new OnFabVisibilityCallback() {
            @Override
            public void onChange(boolean isVisible) {
                if(isVisible){
                    if(!isFabVisible){
                        isFabVisible = true;
                        fabButton.setVisibility(View.VISIBLE);
                    }
                }else{
                    if(isFabVisible){
                        isFabVisible = false;
                        fabButton.setVisibility(View.GONE);
                    }
                }
            }
        });

    }

    private class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

        private Activity activity;
        private ArrayList<String> datas;
        private LayoutInflater layoutInflater;

        public DataAdapter(Activity activity, ArrayList<String> datas) {
            this.activity = activity;
            this.datas = datas;
            this.layoutInflater = LayoutInflater.from(activity);
        }

        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new SimpleViewHolder(layoutInflater.inflate(R.layout.unit_test, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            ((SimpleViewHolder)holder).init(datas.get(position));
        }

        @Override
        public int getItemCount() {
            return datas.size();
        }

        private class SimpleViewHolder extends RecyclerView.ViewHolder{

            private TextView text;

            public SimpleViewHolder(View itemView) {
                super(itemView);
                initViews(itemView);
            }

            private void initViews(View v){
                text = (TextView)v.findViewById(R.id.text);
            }

            public void init(String data){
                text.setText(data);
            }

        }

    }

    public interface OnFabVisibilityCallback{

        void onChange(boolean isVisible);

    }

}

The activity layout files:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_margin="16dp"
        android:src="@drawable/ic_add_black_24dp"
        android:tint="@color/white" />

</RelativeLayout>

This is recyclerview child layout:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:gravity="center"
    android:background="@color/yellow"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="150dp">

    <TextView
        android:text="data"
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

Upvotes: 1

aminography
aminography

Reputation: 22832

I think the problem is that you should pull the findFirstVisibleItemPosition() into the OnScrollListener to find visible position in scroll changes:

myRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

            val positionView = (myRecyclerView.getLayoutManager() as LinearLayoutManager).findFirstVisibleItemPosition()

            if (positionView > 0) {
                if(!emailFab.isShown) {
                    emailFab.show();
                }
            } else  {
                if(emailFab.isShown) {
                    emailFab.hide();
                }
            }
        }
    })

Upvotes: 0

Related Questions