Request to moderators: This is not a duplicate question, please read the below information.
Before asking this question, i'd tried almost every available solution on SO, but none of them worked for me, some resulted in crash and some didn't work at all (I'm a beginner, it is possible that i've done something wrong in my code, i'm not blaming anyone's answer available on SO for not working in my case). Below are my codes, please have a look:
fragment_tab1.xml (which contains recyclerview):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#333333"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="96dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="42dp"
android:background="@color/colorPrimaryDark"
android:id="@+id/sort1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/sort"
android:layout_marginLeft="10dp"
android:fontFamily="@font/quicksand"
android:textStyle="bold"
android:text="Sort by:"
android:textColor="#ffffff"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
style="@style/Widget.AppCompat.Button.Colored"
android:text="Oldest first"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.Button.Colored"
android:text="Newest first"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_below="@id/sort1"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:padding="5dp" />
</RelativeLayout>
</LinearLayout>
Fragmenttab1.java
public class tab1 extends Fragment {
RecyclerView mRecyclerView;
FirebaseDatabase mFirebaseDatabase;
DatabaseReference mRef;
LinearLayoutManager manager;
private static final String TAG = "tab1";
ProgressDialog progressDialog;
View rootView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
rootView = inflater.inflate(R.layout.fragment_tab1, container, false);
return rootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
manager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setItemViewCacheSize(20);
mRecyclerView.setDrawingCacheEnabled(true);
mFirebaseDatabase = FirebaseDatabase.getInstance();
mRef = mFirebaseDatabase.getReference("memes");
mFirebaseDatabase.getInstance().getReference().keepSynced(true);
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Please Wait");
progressDialog.show();
}
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Model, ViewHolder> firebaseRecyclerAdapter =
new FirebaseRecyclerAdapter<Model, ViewHolder>(
Model.class,
R.layout.row2,
ViewHolder.class,
mRef
) {
@Override
protected void populateViewHolder(ViewHolder viewHolder, Model model, int position) {
viewHolder.setDetails(getActivity(), model.getTitle(), model.getDesc(), model.getImage());
progressDialog.cancel();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder viewHolder = super.onCreateViewHolder(parent, viewType);
viewHolder.setOnClickListener(new ViewHolder.ClickListener(){
@Override
public void onItemClick(View view, int position){
//get data from firebase here
String mTitle = getItem(position).getTitle();
String mDesc= getItem(position).getDesc();
String mImage = getItem(position).getImage();
//pass this data to new activity
Intent intent = new Intent(view.getContext(), ArticleDetail.class);
intent.putExtra("title", mTitle);// put title
intent.putExtra("desc", mDesc);// put description
intent.putExtra("image", mImage); //put image urls
startActivity(intent);
}
@Override
public void onItemLongClick(View view, int position){
//TODO your own implementation on long item click
}
});
return viewHolder;
}
};
mRecyclerView.setAdapter(firebaseRecyclerAdapter);
}
@Override
public void onPause() {
super.onPause();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
View firstChild = mRecyclerView.getChildAt(0);
int firstVisiblePosition = mRecyclerView.getChildAdapterPosition(firstChild);
int offset = firstChild.getTop();
Log.d(TAG, "Postition: " + firstVisiblePosition);
Log.d(TAG, "Offset: " + offset);
preferences.edit()
.putInt("position", firstVisiblePosition)
.putInt("offset", offset)
.apply();
}
@Override
public void onResume(){
super.onResume();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
}
}
If you are trying to clear all items from the RecyclerView, you need to delete all items from its adapter and then notify it via an appropriate method. If you are trying to only remove whatever filter applied on it, in order to show all items, then it will depend on how results are being filtered.
Just set your LayoutManager and adapter for the first time. Make a setDataList method in your adapter class. And set your updated list to adapter list. And then every time of calling API set that list to setDataList and call adapter.
You can use scrollToPosition() with the index of the last position. Based on the doc, " RecyclerView does not implement scrolling logic, rather forwards the call to scrollToPosition(int)". It does not implement the logic, simply call this function will does nothing.
After paying so many days, after trying many many solutions, finally found a working solution for my problem, thanks to https://stackoverflow.com/a/42563804/2128364
I've moved the working solution to another methods to make it work in the fragment.
Maybe this can save someone's day, Here is how it worked:
mBundleRecyclerViewState = new Bundle();
mListState = mRecyclerView.getLayoutManager().onSaveInstanceState();
mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
if (mBundleRecyclerViewState != null) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
mRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);
}
}, 50);
}
mRecyclerView.setLayoutManager(staggeredGridLayoutManager);
If you don't have already, add the recyclerView
dependency in your build.gradle
implementation "androidx.recyclerview:recyclerview:1.2.0"
Than just set the stateRestorationPolicy
just after you initialize your list adapter.
listAdapter = ListAdapter()
// Set scroll restore policy
listdapter.stateRestorationPolicy =
RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
For more information on stateRestorationPolicy
and different types of policies visit this article
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With