Tolgay Toklar
Tolgay Toklar

Reputation: 4343

Adding a hideable headerview to recyclerview

I want to add a headerview that hides when user scrolls to down and shows again when user scrolls to up.

Example: https://i.sstatic.net/KXm4c.jpg

As you can see in the link "You are writing as..." pharase is showing only when user scrolls to top. Is there something like that in Android sdk?

How can i achive the same thing?

Upvotes: 3

Views: 60

Answers (1)

Tor-Martin Holen
Tor-Martin Holen

Reputation: 1659

Obtaining the scroll event is just the first step to achieving this. Animations is required to achieve the effect. I recreated a simple version of the gif example you posted.

Example

Layout for the main activity, activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:animateLayoutChanges="true"> <!-- Note the last line-->

    <TextView
        android:id="@+id/textview_hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="8dp"
        android:text="Hello Stack Overflow!"/>


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

Below is the code for the main activity where we populate the RecyclerView and use the addOnScrollListener to provide animations to the TextView. Do note the commented out lines these will provide a default fade-out or fade-in animation due to the noted line in the xml layout above. The method slideAnimation() is an example of creating a custom animation. This link proved useful for creating the animations.

class MainActivity : AppCompatActivity() {
    private lateinit var viewAdapter: RecyclerView.Adapter<*>
    private lateinit var viewManager: LinearLayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Some data for the RecyclerView
        val data: List<String> = (1..100).toList().map { it.toString() }

        viewManager = LinearLayoutManager(this)
        viewAdapter = TextAdapter(data)

        findViewById<RecyclerView>(R.id.recyclerview_main).apply {
            setHasFixedSize(true)
            layoutManager = viewManager
            adapter = viewAdapter

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

                        val pastVisibleItems = viewManager.findFirstCompletelyVisibleItemPosition()
                        if (pastVisibleItems == 0) {
                            slideAnimation(0f, 1f, View.VISIBLE)
                            //textview_hello.visibility = View.VISIBLE
                        } else if (textview_hello.visibility != View.GONE) {
                            slideAnimation(-150f, 0f, View.GONE)
                            //textview_hello.visibility = View.GONE
                        }
                    }
                }
            )
        }

    ... // SlideAnimation function

    }

}

The slideAnimation function

private fun slideAnimation(translationY: Float, alpha: Float, viewVisibility: Int) {
    textview_hello.visibility = View.VISIBLE
    textview_hello.clearAnimation()
    textview_hello
        .animate()
        .translationY(translationY)
        .alpha(alpha)
        .setListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                super.onAnimationEnd(animation)
                textview_hello.clearAnimation()
                textview_hello.visibility = viewVisibility
            }
        })
        .duration = 500
}

The adapter for the RecycleView:

class TextAdapter(private val textList: List<String>) :
    RecyclerView.Adapter<TextAdapter.TextViewHolder>() {

    class TextViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): TextViewHolder {
        val textView = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_text_view, parent, false) as TextView
        return TextViewHolder(textView)
    }

    override fun onBindViewHolder(holder: TextViewHolder, position: Int) {
        holder.textView.text = textList[position]
    }

    override fun getItemCount() = textList.size
}

Item to display in the RecyclerView, item_text_view.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:padding="16dp"
    android:textAlignment="center"
    android:background="@android:color/darker_gray">

</TextView>

Upvotes: 2

Related Questions