问题
My application revolves around a HomeActivity which contains 4 tabs at the bottom. Each of these tabs is a fragment, all of them are added (not replaced) from the start, and they are hidden/shown upon tapping the appropriate tab.
My problem is that whenever I change tab, the state of my scroll is lost. Each fragment which exhibits that issue uses a android.support.v4.widget.NestedScrollView
(see below for an example).
Note: My fragments that use a RecyclerView or ListView keep their scroll state for some reason.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/include_appbar_title" />
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Content -->
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
I read several posts regarding saving the instance state (this one, that one for example), and their solution either don't work in my scenario, or are not practical to implement given I have 4-12 different fragments I'd need to modify to make it work.
What is the best way to have a Nested Scroll View keep its scroll position on fragment changes ?
回答1:
One solution I found on inthecheesefactory is that fragments, by default, have their state saved (from the input in a EditText, to the scroll position), but ONLY if an ID is given to the xml element.
In my case, just adding an ID to my NestedScrollView fixed the problem:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/include_appbar_title" />
<android.support.v4.widget.NestedScrollView
android:id="@+id/NestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Content -->
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
回答2:
You can manage the instance state (which includes the scroll state) by yourself by first making the corresponding methods public:
class SaveScrollNestedScrollViewer : NestedScrollView {
constructor(context: Context) : super(context)
constructor(context: Context, attributes: AttributeSet) : super(context, attributes)
constructor(context: Context, attributes: AttributeSet, defStyleAttr: Int) : super(context, attributes, defStyleAttr)
public override fun onSaveInstanceState(): Parcelable? {
return super.onSaveInstanceState()
}
public override fun onRestoreInstanceState(state: Parcelable?) {
super.onRestoreInstanceState(state)
}
}
Then use it in your view with (YOUR_NAMESPACE
is the namespace of the SaveScrollNestedScrollViewer
class):
<YOUR_NAMESPACE.SaveScrollNestedScrollViewer
android:id="@+id/my_scroll_viewer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</YOUR_NAMESPACE.SaveScrollNestedScrollViewer>
and then in the activity which displays it, save / recover the state as needed. For example, if you want to recover the scroll position after navigating away use the following:
class MyActivity : AppCompatActivity() {
companion object {
var myScrollViewerInstanceState: Parcelable? = null
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.my_activity)
if (myScrollViewerInstanceState != null) {
my_scroll_viewer.onRestoreInstanceState(myScrollViewerInstanceState)
}
}
public override fun onPause() {
super.onPause()
myScrollViewerInstanceState = my_scroll_viewer.onSaveInstanceState()
}
}
来源:https://stackoverflow.com/questions/44407092/saving-scroll-state-of-nestedscrollview