我的应用程序围绕着底部包含4个选项卡的托运性。这些标签中的每一个都是一个片段,从一开始就添加了所有选项卡(未替换(,并且在敲击适当的选项卡时被隐藏/显示。
我的问题是,每当我更改选项卡时,滚动的状态就会丢失。表现出该问题的每个片段都使用android.support.v4.widget.NestedScrollView
(示例见下文(。
注意:我使用recyclerview或ListView的片段由于某种原因保持其滚动状态。
<?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>
我读了几篇有关保存实例状态的文章(例如,一个,例如一个(,并且他们的解决方案要么在我的情况下不起作用,要么在实现我的情况下不实用,因为我有4-12个不同的片段I'D需要修改以使其正常工作。
拥有嵌套滚动视图的最佳方法是在片段上保持其滚动位置?
我在Inthecheesefactory上找到的一种解决方案是,默认情况下,片段保存了其状态(从EditText中的输入到滚动位置(,但前提XML元素。
在我的情况下,只需在我的NestedScrollview中添加ID解决了问题:
<?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>
查看nestedscrollview的实现,我们看到nestedscrollview的 scrolly 属性存储在其 sav_s> savedstate 中滚动位置。
// Source: NestedScrollView.java
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.scrollPosition = getScrollY();
return ss;
}
因此,我确实同意Ramiro G.M.关于在跨配置变化的滚动位置的想法方面。在这种情况下
如果您使用的是片段和MVVM,那么我将嵌套的滚动位置保存在片段中的viewModel中 onviewDestroyed 方法。稍后,您可以在创建片段视图时通过livedata对象观察状态。
override fun onViewCreated(...) {
mViewModel.scrollState.observe(viewLifecycleOwner, { scrollState ->
binding.myNestedScrollView.scrollY = scrollState
})
}
override fun onDestroyView() {
val scrollState = binding.myNestedScrollView.scrollY
mViewModel.setScrollState(scrollState)
super.onDestroyView()
}
这只是一个简单的示例,但该概念是正确的。
您可以通过首先公开相应的方法来管理实例状态(包括卷轴状态(:
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)
}
}
然后在视图中使用它(YOUR_NAMESPACE
是SaveScrollNestedScrollViewer
类的名称空间(:
<YOUR_NAMESPACE.SaveScrollNestedScrollViewer
android:id="@+id/my_scroll_viewer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</YOUR_NAMESPACE.SaveScrollNestedScrollViewer>
然后在显示它的活动中,根据需要保存/恢复状态。例如,如果要在导航后要恢复滚动位置,请使用以下内容:
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()
}
}
由于现在所有答案都弃用了,我会给大家一个新的选项。
- 创建一个变量以将嵌套的滚动视图保存在您的视图模型上:
class DummyViewModel : ViewModel() {
var estadoNestedSV:Int?=null
}
- 覆盖片段上的覆盖以在嵌套卷轴视图被破坏之前保存状态:
override fun onStop() {
try {
super.onStop()
viewModel.estadoNestedSV = binding.nestedSV.scrollY
} catch (e: Exception) {
Log.i((activity as MainActivity).constantes.TAG_GENERAL, e.message!!)
}
}
- 通过覆盖范围的浏览在您的片段上创建视图后,恢复状态:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
try {
//Check first if data exists to know if this load is a first time or if the device was rotated.
if(viewModel.data.value != null)
binding.nestedSVPelisDetalles.scrollY = viewModel.estadoNestedSV!!
} catch (e: Exception) {
Log.i((activity as MainActivity).constantes.TAG_GENERAL, e.message!!)
}
}
快乐编码!