I have followed so many answers from here.. but not a single one solving my issue .. that's why i am asking.
I want to save scroll position in a fragment. In So many articles they have suggested to follow
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
and
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
But this two method is not available in fragment.
My code:
private int mPositionIng = RecyclerView.NO_POSITION;
private String KEY_POSITION_ING = "KeyPositionIng";
in OnCreateView()
if (savedInstanceState != null) {
if (savedInstanceState.containsKey(KEY_POSITION_ING)) {
mPositionIng = savedInstanceState.getInt(KEY_POSITION_ING);
}
}
Override Methods in fragment They are not same method as above. i don't know where i am doing wrong.
@Override
public void onSaveInstanceState(Bundle outState) {
int scrollPositionIng = mRecyclerViewIngredients.computeVerticalScrollOffset();
mPositionIng = scrollPositionIng;
outState.putInt(KEY_POSITION_ING, mPositionIng);
super.onSaveInstanceState(outState);
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
if (mPositionIng != RecyclerView.NO_POSITION) {
mRecyclerViewIngredients.getLayoutManager().scrollToPosition(mPositionIng);
}
super.onViewStateRestored(savedInstanceState);
}
I just need to save scroll position while the orientation changes .. Please help. Any Suggestion will be help full. Thanks......
To be able to scroll through a vertical list of items that is longer than the screen, you need to add a vertical scrollbar. Inside RecyclerView , add an android:scrollbars attribute set to vertical .
To Implement recyclerview in fragment, Create a Blank fragment on which we want to implement recyclerview. and give it name NewFragment. To create Recyclerview with cardview we need to add two dependencies in build. gradle file.
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. notifyDataSetChanged() method of your adapter class.
Everything I wrote below is correct, but the reason it didn't work for you is that I didn't realize how your Activity
's layout was structured. Here is your Activity
's layout (slightly cleaned up):
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tapan.recipemaster.activity.RecipeDetailActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/fl_fragment_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/padding_10dp"/>
</RelativeLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>
Meanwhile, this is your Fragment
's layout (again, slightly cleaned up):
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tapan.recipemaster.fragment.RecipeDetailFragment">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/padding_10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_ingredient"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:textSize="@dimen/text_23sp"
android:text="Ingredients"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_ingredients"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_8dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_step"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_8dp"
android:textColor="@color/colorPrimaryDark"
android:textSize="@dimen/text_23sp"
android:text="Steps"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_steps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_8dp"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
Both RecyclerView
s have android:layout_height="wrap_content"
, which means they do not scroll. Rather, the ScrollView
in your Activity
is the view providing the scrolling behavior, so it is this view whose scroll position must be saved.
You can have the system do this for you by giving this ScrollView
an id. Any id you want, as long as it's unique. You don't have to write any Java at all.
<ScrollView
android:id="@+id/thisfixestheproblem"
android:layout_width="match_parent"
android:layout_height="match_parent">
Make sure you're modifying the ScrollView
in your activity's layout, not the one in your fragment's layout.
None of the code you posted should be necessary to save your RecyclerView
's scroll position on orientation change. As long as the RecyclerView
has a unique ID in your layout, it will save the scroll position for you automatically.
Here is a very small sample app that shows automatic saving of scroll position, even with a dynamically added Fragment
. As you can see, the only instance state I'm saving myself is whether the button to start the fragment should be visible.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("buttonVisible", button.getVisibility() == View.VISIBLE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content, new MyFragment())
.commit();
button.setVisibility(View.GONE);
}
});
if (savedInstanceState != null) {
boolean buttonVisible = savedInstanceState.getBoolean("buttonVisible");
button.setVisibility(buttonVisible ? View.VISIBLE : View.GONE);
}
}
}
MyFragment.java
public class MyFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.myfragment, container, false);
RecyclerView recycler = (RecyclerView) root.findViewById(R.id.recycler);
recycler.setAdapter(new MyAdapter());
return root;
}
private static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.itemview, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Drawable d = new ColorDrawable(Color.argb(0xff, 0, 0, position));
ViewCompat.setBackground(holder.image, d);
holder.text.setText("" + position);
}
@Override
public int getItemCount() {
return 256;
}
}
private static class MyViewHolder extends RecyclerView.ViewHolder {
final View image;
final TextView text;
MyViewHolder(View itemView) {
super(itemView);
this.image = itemView.findViewById(R.id.image);
this.text = (TextView) itemView.findViewById(R.id.text);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="create fragment"/>
</FrameLayout>
myfragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:listitem="@layout/itemview"/>
itemview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
android:id="@+id/image"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="12dp"
tools:background="#333"/>
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:text="text"/>
</LinearLayout>
Let the Android OS handle that for you, in AndroidManifest.xml
inside your wanted tag activity add:
android:configChanges="orientation|screenSize"
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