I have a problem that is driving me nuts and been searching several hours around the web but cant find a solution. I want to set an animation on the first view in my recyclerview when I add new data to the list. But I cant because the recyclerview is null.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    orientation = getResources().getConfiguration().orientation;

    model = ViewModelProviders.of(getActivity()).get(ViewModelAdvices.class);
    model.getAdvices().observe(this, new Observer <List <Advice>>() {

        //Update recyclerview automatically when data is changed
        @Override
        public void onChanged(List <Advice> advices) {
            filtered_advices_list.clear();
            filtered_advices_list.addAll(advices);
            adapter_recycler_view.notifyDataSetChanged();

        }
    });
}

@Override
public void onResume() {
    super.onResume();
    Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.test_item);
    View v = recycler_view.getChildAt(0);
    v.startAnimation(animation);

}



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.show_advices_fragment, container, false);

    setupLayoutDifferences(view);

    recycler_view = (RecyclerView) view.findViewById(R.id.recycler_view);
    layout_manager = new LinearLayoutManager(getContext());
    recycler_view.setLayoutManager(layout_manager);
    adapter_recycler_view = new AdapterRV(filtered_advices_list);
    recycler_view.setAdapter(adapter_recycler_view);

 spinner_1 = (Spinner) view.findViewById(R.id.spinner_1);
    adapter_spinner_1 = ArrayAdapter.createFromResource(view.getContext(), R.array.categories, android.R.layout.simple_spinner_item);
    adapter_spinner_1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner_1.setAdapter(adapter_spinner_1);

    spinner_1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView <?> parent, View view, int position, long id) {
            String category = spinner_1.getItemAtPosition(spinner_1.getSelectedItemPosition()).toString();
            model.setCategory(category);
        }
        @Override
        public void onNothingSelected(AdapterView <?> parent) { }
    });

    return view;
    }
} 

show_advices_fragment

    <LinearLayout 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:background="@color/colorBlueGreen"
        android:paddingBottom="6dp">



    <Spinner
            android:id="@+id/spinner_1"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:backgroundTint="@color/colorBlack" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom">

            <Button
                android:id="@+id/button_add_activity"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginTop="6dp"
                android:layout_marginLeft="6dp"
                android:layout_marginRight="6dp"
                android:visibility="gone"
                android:text="@string/button_add_activity" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_above="@+id/button_add_activity"
                android:background="@color/colorLightGrey"
                android:scrollbars="vertical"
                />

        </RelativeLayout>

    </LinearLayout>

list_item_activity_main

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:background="@color/colorWhite"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:weightSum="3">

<TextView
    android:id="@+id/text_view_advice"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/border"
    android:textColor="@color/colorPrimary"
    android:paddingRight="4dp"
    android:layout_weight="1"
    android:text="TextView" />

<TextView
    android:id="@+id/text_view_author"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/colorGrey"
    android:layout_weight="2"
    android:gravity="center"
    android:text="TextView" />

 </LinearLayout>

And test_item

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_longAnimTime">

    <translate
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="100%p"
        android:toXDelta="0"
        />

    <alpha
        android:fromAlpha="0.5"
        android:toAlpha="1"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        />

</set>

In the onResume I am in the last lifecycle I suppose and the recyclerview is being build up already in onCreateView. I guess that the build-up of the recyclerview aint finished before I reach onResume, but how can I solve this? If I do the animation with a mouseclick when the fragment is already loaded it works but not when I switch fragment and the recyclerview is being built up again.

3 Answers

0
Vishrut Mavani On

Try this

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        orientation = getResources().getConfiguration().orientation;

        model = ViewModelProviders.of(getActivity()).get(ViewModelAdvices.class);
        model.getAdvices().observe(this, new Observer<List<Advice>>() {

            //Update recyclerview automatically when data is changed
            @Override
            public void onChanged(List<Advice> advices) {
                filtered_advices_list.clear();
                filtered_advices_list.addAll(advices);

            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.test_item);
        View v = recycler_view.getChildAt(0);
        v.startAnimation(animation);

    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.show_advices_fragment, container, false);

        setupLayoutDifferences(view);

        recycler_view = (RecyclerView) view.findViewById(R.id.recycler_view);
        layout_manager = new LinearLayoutManager(getContext());
        recycler_view.setLayoutManager(layout_manager);
        populateAdapter();


        spinner_1 = (Spinner) view.findViewById(R.id.spinner_1);
        adapter_spinner_1 = ArrayAdapter.createFromResource(view.getContext(), R.array.categories, android.R.layout.simple_spinner_item);
        adapter_spinner_1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner_1.setAdapter(adapter_spinner_1);

        spinner_1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String category = spinner_1.getItemAtPosition(spinner_1.getSelectedItemPosition()).toString();
                model.setCategory(category);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        if (adapter_recycler_view != null){
            adapter_recycler_view.notifyDataSetChanged();
        }

        return view;
    }

    private void populateAdapter() {
        adapter_recycler_view = new AdapterRV(filtered_advices_list);
        recycler_view.setAdapter(adapter_recycler_view);
    }
0
ישו אוהב אותך On

You can't depends on onResume() in Fragment, because it's not 100% called after onCreateView() on some Android versions (More details at Fragment onResume() & onPause() is not called on backstack). So, there is a probability that you're fragment layout creation is not yet finished.

You can wait until the RecyclerView is finished inflating all the items with OnGlobalLayoutListener then show the animation for the first item:

recycler_view.getViewTreeObserver()
             .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                 @Override
                public void onGlobalLayout() {

                  // show the animation
                  Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.test_item);
                  View v = recycler_view.getChildAt(0);
                  v.startAnimation(animation);

                  // remove listener so that this won't be called multiple time.
                  recycler_view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        }); 
0
potatoman On

Thank you for trying to help me. Problem is that my application is probably not the best organized so everything runs before my recyclerview is done with the list it gets from ViewModel. But doing the animation on a separate thread works like a charm, then I also have full control over the animation.

if(action.equals("addData")) {

            Thread thread = new Thread() {
                @Override
                public void run() {
                    try {

                        boolean recycler_view_loading = true;

                        while(recycler_view_loading ) {
                            sleep(250);

                            if (recycler_view.getChildAt(0) != null) {

                                Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.item_animation_side);
                                View v = recycler_view.getChildAt(0);
                                v.startAnimation(animation);
                                recycler_view_loading  = false;
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            thread.start();
        }