Update
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.
Original
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>