How to trigger the over scroll animation by code?

1.2k Views Asked by At

I am trying to trigger the over scroll animation on ListView by code. enter image description here

Ripple or Glow (how do you call it?) should appear on the edge.

I tried all the function in ListView like scroll* or scrollSmooth*, non of them could trigger the animation.

I also tried some solutions which could trigger the animation of Ripple background, but it's not the same as this edge effect.

I am new to Android. Please let me know if there are any method, thanks.

I also tried to use onDraw(Canvas canvas), because I didn't find any solution. As I always do this kind of thing on iOS, so I can draw the effect as animation. But here is another problem, the drawing speed is super low, I don't know why, just some typical drawing code on stackoverflow. And when I started a view transition later, everything messed up.

1

There are 1 best solutions below

4
On

I would advise you to use a RecyclerView instead for your purpose. The "Overscroll" animation is supported by default.

A RecyclerView is in a way pretty similar to a ListView, but it makes it for example way easier to deal with animations or forces you to use the ViewHolder Pattern. Furthermore it is way more flexible then a ListView.

However in my personal opinion using a ListView over a RecyclerView for simple use cases is still fine.

So what steps are necessary to create one?

Adding the dependency

First add the dependency to your app.gradle file. You will find this file under "Gradle Scripts -> build.gradle (Module: app)" or by simply pressing TAB twice and then entering gradle in the search menu (pretty useful when searching files :) ). There add the following dependency: implementation 'com.android.support:recyclerview-v7:26.1.0'

Alternatively you can Drag and Drop the RecyclerView from the Designer to your Layout (Designer can be found by going to your layout.xml file and switching to the Design Tab) by searching it (top left). This will automatically add the dependency for you.

Creating the Layout

Simply the same as ListView (note: this example does not use ConstraintLayout as parent ViewGroup):

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

I don't know if you are currently using a ConstraintLayout, but you should definitely check it out :).

Adapter explained

public class RecyclerViewAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private List<String> mData;
private LayoutInflater mInflater;

RecyclerViewAdapter(List<String> data, LayoutInflater inflater) {
    mData = data;
    mInflater = inflater;
}

@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    return new ExampleViewHolder(mInflater.inflate(R.layout.my_layout, parent, false));
}

@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
    holder.getTvText().setText(mData.get(position));
}

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

onCreateViewHolder: As it already says a new ViewHolder has to be created. This is not called everytime a new item pops up on screen when scrolling!

onBindViewHolder: Data for the ViewHolder given as parameter has to be updated.

getItemCount: How many items does this RecyclerView consist of?

ViewHolder

class ExampleViewHolder extends RecyclerView.ViewHolder {
private TextView mTvText;

    public ExampleViewHolder(View itemView) {
        super(itemView);
        mTvText = itemView.findViewById(R.id.tv_text);
    }

    public TextView getTvText() {
        return mTvText;
    }
}

There you just extract your Views so you can update them when the onBindViewHolder method is called. Layout for it:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="56dp">
<TextView
    android:id="@+id/tv_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</android.support.constraint.FrameLayout>

To finish Now you only have to set a LayoutManager and an Adapter to your RecyclerView and voilah! The LayoutManager simply tells the RecyclerView how those items should be arranged. Ok now let's finish:

mRvExample.setHasFixedSize(true); //set this if every item has the same size - performance gain
mRvExample.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRvExample.setAdapter(new RecyclerViewAdapter(Arrays.asList("asdf","asdfsdf"), getLayoutInflater());

Whilst I could not directly solve your problem using a ListView I hope that I was still able to help you out. Since I don't know which level you are at I hope it was also fine of me to include a description of how to set up a basic RecyclerView. Helpful links you should have a look it to get a more in depth understanding are:

Base description: https://developer.android.com/training/material/lists-cards.html

Talking about enter animations: https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213

Adding onClick: RecyclerView onClick

Using Kotlin: https://antonioleiva.com/recyclerview-adapter-kotlin/

Item decorartion: https://www.bignerdranch.com/blog/a-view-divided-adding-dividers-to-your-recyclerview-with-itemdecoration/

Pro RecyclerView talk: https://www.youtube.com/watch?v=KhLVD6iiZQs