2

Hello I want to save the position of the recycler view when navigating from one fragment to another and then restore the scroll position when returning to the fragment

Note

I didn't try any method till now because I don't know where exactly I have to implement it in my Home_Fragmen.java or in PostAdapter_Home.java

now, how do I implement this in my code?

Home_Fragment.java

 public class Home_Fragment extends Fragment {
    private final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("uploads");
    public List<Upload> mUploads;
    PostAdapter_Home postsAdapter;
    RecyclerView postRecyclerView;
    ShimmerFrameLayout shimmerFrameLayout;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_home, container, false);
        requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        postRecyclerView = view.findViewById(R.id.recyclerViewHome);
        shimmerFrameLayout = view.findViewById(R.id.shimmerEffect);
        SnapHelper snapHelper = new PagerSnapHelper();
        snapHelper.attachToRecyclerView(postRecyclerView);
        postRecyclerView.setLayoutManager(
                new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
        );

        getData();
        shimmerFrameLayout.startShimmer();
        mUploads = new ArrayList<>();
        postsAdapter = new PostAdapter_Home(getContext(), mUploads);
        postRecyclerView.setAdapter(postsAdapter);
        return view;
    }

    private void getData() {
        databaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.exists()) {

                    postRecyclerView.setVisibility(View.VISIBLE);
                    shimmerFrameLayout.stopShimmer();
                    shimmerFrameLayout.setVisibility(View.GONE);
                    mUploads.clear();
                    for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                        Upload upload = dataSnapshot.getValue(Upload.class);
                        assert upload != null;
                        upload.setmKey(dataSnapshot.getKey());
                        mUploads.add(upload);


                    }

                }

                //notify the adapter
                postsAdapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
    }
}

PostAdapter_Home.java

public class PostAdapter_Home extends RecyclerView.Adapter<PostAdapter_Home.PostViewHolder> {
    public static List<Upload> mUploads;
    public Context mcontext;
    //    ShimmerFrameLayout shimmerFrameLayout;


    public PostAdapter_Home(Context context, List<Upload> uploads) {
        mUploads = uploads;
        mcontext = context;
    }


    @NonNull
    @Override
    public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        view = LayoutInflater.from(mcontext).inflate(R.layout.post_item_container_home, parent, false);
        return new PostViewHolder(view);

    }

    @Override
    public void onBindViewHolder(@NonNull PostViewHolder holder, int position) {
        Upload uploadCurrent = mUploads.get(position);
        Shimmer shimmer = new Shimmer.ColorHighlightBuilder()
                .setBaseColor(Color.parseColor("#F3F3F3"))
                .setBaseAlpha(1)
                .setHighlightColor(Color.parseColor("#E7E7E7"))
                .setHighlightAlpha(1)
                .setDropoff(50)
                .build();
        ShimmerDrawable shimmerDrawable = new ShimmerDrawable();
        shimmerDrawable.setShimmer(shimmer);
        Glide.with(mcontext)
                .load(uploadCurrent.getmImageUrl())
                .diskCacheStrategy(DiskCacheStrategy.DATA)
                .placeholder(shimmerDrawable)
                .into(holder.imageView);


    }

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

    public static class PostViewHolder extends RecyclerView.ViewHolder {
        ShapeableImageView imageView;

        public PostViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imagePostHome);
        }


        public void setOnItemClickListener(PostAdapter.OnItemClickListener listener) {

        }
    }
}

1 Answers1

0

One easy solution is using a static variable.

  1. Add the following as an attribute to your class: public static int saved_position = 0 (the 0 value must be the default value for your recyclerView position).
  2. Whenever the recyclerView value changes, add Home_Fragment.saved_position = ..., in order to save the actual position in the variable. This line of code can be run on any file without problem because the static variable is public.
  3. When you create the fragment, set the recyclerView position to the position saved in Home_Fragment.saved_position, that's why you have to set the default value as it's initial value.
  4. If for some reason the amount of elements in the recyclerView changes, remember to change the value of Home_Fragment.saved_position to the default value.
FelipeCruzV10
  • 426
  • 6
  • 13
  • 1
    The value will be stored as far as the app isn't closed completely. If the app is put on background, the value will be stored until other app occupies the RAM memory used by the variable... – FelipeCruzV10 Jun 02 '21 at 06:29
  • Brother, I understand it a little bit but it will be very helpful if you tell me what will be the exact code and where should I implement it in my code ,btw thanks for the answer –  Jun 02 '21 at 06:35
  • 1
    Well, the exact code depends on your PostAdapter_Home class. I'll suppose that it is a normal recyclerView adapter and that it has a RecyclerView.Holder... So, here's more information: 1. The exact code is there. Add it above "@Nullable". 2. Inside the "onBindViewHolder" method, add "Home_Fragment.saved_position = holder.getAbsoluteAdapterPosition()" 3. Before "return View" add "postRecyclerView.scrollToPosition(Home_Fragment.saved_position)" 4. It depends if the amount of views changes or not. If yes, in the part of your code where this happens, add "Home_Fragment.saved_position=0" – FelipeCruzV10 Jun 02 '21 at 07:05
  • 1
    If you don't understand about the "onBindViewHolder" or other RecyclerView related things. Check https://stackoverflow.com/questions/26682277/how-do-i-get-the-position-selected-in-a-recyclerview and https://stackoverflow.com/questions/26875061/scroll-recyclerview-to-show-selected-item-on-top – FelipeCruzV10 Jun 02 '21 at 07:06
  • Brother if you check my AdapterClass it will be very helpful I have included the adapter class in the question –  Jun 02 '21 at 07:21
  • Oh that's better. Well, you still have to implement the "onItemClickListener". That function is of the form "onItemClick(AdapterView> parent, View view, int position, long id)", so you can add 2. "Home_Fragment.saved_position = position" inside that method when you have it ready. – FelipeCruzV10 Jun 02 '21 at 07:51