Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/229.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 无法在设备旋转时使用onSaveInstanceState()和onRestoreInstanceState()滚动到正确的RecyclerView位置_Android - Fatal编程技术网

Android 无法在设备旋转时使用onSaveInstanceState()和onRestoreInstanceState()滚动到正确的RecyclerView位置

Android 无法在设备旋转时使用onSaveInstanceState()和onRestoreInstanceState()滚动到正确的RecyclerView位置,android,Android,我是Android开发的初学者。我尝试在LayoutManager上使用onSaveInstanceState()和onRestoreInstanceState()保存RecyclerView的LayoutManager的状态(在经历了许多堆栈溢出问题之后),但我无法这样做。我希望在设备旋转时恢复RecyclerView的滚动位置。我还尝试保存布局中使用的NestedScrollView的位置,但无法使其正常工作 片段类 public class RecipeDetailFragment ext

我是Android开发的初学者。我尝试在LayoutManager上使用onSaveInstanceState()和onRestoreInstanceState()保存RecyclerView的LayoutManager的状态(在经历了许多堆栈溢出问题之后),但我无法这样做。我希望在设备旋转时恢复RecyclerView的滚动位置。我还尝试保存布局中使用的NestedScrollView的位置,但无法使其正常工作

片段类

public class RecipeDetailFragment extends Fragment {

    private static final String BUNDLE_RECIPE_ID = "Recipe";
    private static final String BUNDLE_LAYOUT_MANAGER_KEY = "layout";
    public StepAdapter mStepAdapter;
    public IngredientAdapter mIngredientAdapter;
    private Recipe selectedRecipe;
    private StepAdapter.StepAdapterOnClickHandler mClickHandler;

    @BindView(R.id.rv_recipe_detail_steps)
    RecyclerView mStepRecyclerView;

    @BindView(R.id.rv_recipe_detail_ingredients)
    RecyclerView mIngredientRecyclerView;


    public RecipeDetailFragment() {
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_recipe_detail, container, false);
        ButterKnife.bind(this, rootView);

        mIngredientAdapter = new IngredientAdapter();
        mIngredientRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mIngredientRecyclerView.setHasFixedSize(true);
        mIngredientRecyclerView.setNestedScrollingEnabled(false);

        mStepAdapter = new StepAdapter(getContext(), mClickHandler);
        mStepRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mStepRecyclerView.setHasFixedSize(true);
        mStepRecyclerView.setNestedScrollingEnabled(false);

        if (savedInstanceState != null) {
            selectedRecipe = savedInstanceState.getParcelable(BUNDLE_RECIPE_ID);
        }
        mIngredientAdapter.setIngredientData(selectedRecipe.getIngredients());

        mStepAdapter.setStepData(selectedRecipe.getSteps());

        mIngredientRecyclerView.setAdapter(mIngredientAdapter);

        mStepRecyclerView.setAdapter(mStepAdapter);

        return rootView;
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        if (savedInstanceState != null) {

            Parcelable state = savedInstanceState.getParcelable(BUNDLE_LAYOUT_MANAGER_KEY);
            mStepRecyclerView.getLayoutManager().onRestoreInstanceState(state);
        }
    }


    public void setRecipe(Recipe recipe) {
        selectedRecipe = recipe;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mClickHandler = (StepAdapter.StepAdapterOnClickHandler) context;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(BUNDLE_RECIPE_ID, selectedRecipe);
        outState.putParcelable(BUNDLE_LAYOUT_MANAGER_KEY, mStepRecyclerView.getLayoutManager()
                .onSaveInstanceState());

    }
}
布局

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/recipe_detail_nested_scroll_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:descendantFocusability="beforeDescendants"
    android:fillViewport="true"
    android:focusableInTouchMode="true">


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/ll_recipe_detail_scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:descendantFocusability="beforeDescendants"
        android:fillViewport="true"
        android:focusableInTouchMode="true"
        android:orientation="vertical">

        <android.support.v7.widget.CardView xmlns:cardView="http://schemas.android.com/apk/res-auto"
            android:id="@+id/ingredients_card"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginLeft="12dp"
            android:layout_marginRight="12dp"
            android:layout_marginTop="8dp"
            cardView:cardCornerRadius="4dp"
            cardView:cardElevation="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tv_recipe_detail_ingredients_label"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:padding="8dp"
                    android:text="@string/label_ingredients"

                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Widget.ActionMode.Title"
                    android:textSize="28sp" />

                <android.support.v7.widget.RecyclerView xmlns:app="http://schemas.android.com/apk/res-auto"
                    android:id="@+id/rv_recipe_detail_ingredients"
                    android:layout_width="match_parent"
                    android:focusable="false"
                    android:layout_height="match_parent"
                    android:paddingBottom="8dp" />
            </LinearLayout>
        </android.support.v7.widget.CardView>

        <android.support.v7.widget.CardView xmlns:cardView="http://schemas.android.com/apk/res-auto"
            android:id="@+id/steps_card"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginLeft="12dp"
            android:layout_marginRight="12dp"
            android:layout_marginTop="8dp"
            cardView:cardCornerRadius="4dp"
            cardView:cardElevation="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/tv_recipe_detail_steps_label"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:padding="8dp"
                    android:paddingBottom="16dp"
                    android:text="@string/label_steps"
                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Widget.ActionMode.Title"
                    android:textSize="28sp" />

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/rv_recipe_detail_steps"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:focusable="false"
                    android:paddingBottom="16dp" />
            </LinearLayout>
        </android.support.v7.widget.CardView>
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

另外,这是我第一次在这里发布问题,如果我没有正确发布问题,请让我知道

在使用片段时,请确保在重新创建作为片段宿主的活动中savedInstanceState不为null时,不执行片段事务 首先,您需要将传递给适配器的数据保存在savedInstanceState中,如果savedInstanceState不为null,则使用该数据

并使用此自定义回收视图

包eu.f3rog.ui.custom;
导入android.content.Context;
导入android.os.Bundle;
导入android.os.Parcelable;
导入android.support.annotation.Nullable;
导入android.support.v7.widget.RecyclerView;
导入android.util.AttributeSet;
/**
*类{@link statefulrecyclererview}扩展了{@link recyclererview},并在配置更改时添加了位置管理。
*
*@作者FrantisekGazo
*@version 2016-03-15
*/
公共最终类StatefulRecyclerView
扩展回收视图{
保存的私有静态最终字符串\u SUPER\u STATE=“SUPER STATE”;
保存的私有静态最终字符串\u LAYOUT\u MANAGER=“LAYOUT MANAGER state”;
私人地块管理者SavedState;
public StatefulRecyclerView(上下文){
超级(上下文);
}
public StatefulRecyclerView(上下文上下文,@Nullable AttributeSet attrs){
超级(上下文,attrs);
}
public StatefulRecyclerView(上下文上下文,@Nullable AttributeSet attrs,int-defStyle){
超级(上下文、属性、定义样式);
}
@凌驾
受保护的地块onSaveInstanceState(){
Bundle=新Bundle();
bundle.putParcelable(保存的超级状态,SUPER.onSaveInstanceState());
bundle.putParcelable(保存的布局管理器,this.getLayoutManager().onSaveInstanceState());
返回包;
}
@凌驾
RestoreInstanceState上的受保护无效(可包裹状态){
if(包的状态实例){
Bundle=(Bundle)状态;
mLayoutManagerSavedState=bundle.getParcelable(已保存的布局管理器);
状态=bundle.getParcelable(已保存的超级状态);
}
super.onRestoreInstanceState(状态);
}
/**
*配置更改后恢复滚动位置。
*
*注意:必须在设置适配器后调用。
*/
私有无效恢复位置(){
if(mLayoutManagerSavedState!=null){
此.getLayoutManager().onRestoreInstanceState(mLayoutManagerSavedState);
mLayoutManagerSavedState=null;
}
}
@凌驾
公共void setAdapter(适配器适配器){
super.setAdapter(适配器);
恢复定位();
}

}
只要您的
RecyclerView
设置了
id
,您就不必做任何事情来让它在旋转设备时保存其滚动状态。下面是一个非常简单的应用程序来演示这一点

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView recycler = (RecyclerView) findViewById(R.id.recycler);
        recycler.setAdapter(new MyAdapter());
    }

    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) {
            holder.text.setText("" + position);
        }

        @Override
        public int getItemCount() {
            return 100;
        }
    }

    private static class MyViewHolder extends RecyclerView.ViewHolder {

        private final TextView text;

        public MyViewHolder(View itemView) {
            super(itemView);
            this.text = (TextView) itemView.findViewById(R.id.text);
        }
    }
}
public类MainActivity扩展了AppCompatActivity{
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recycler=(RecyclerView)findViewById(R.id.recycler);
setAdapter(新的MyAdapter());
}
私有静态类MyAdapter扩展了RecyclerView.Adapter{
@凌驾
公共MyViewHolder onCreateViewHolder(视图组父级,int-viewType){
LayoutInflater充气器=LayoutInflater.from(parent.getContext());
视图项视图=充气机。充气(R.layout.itemView,父项,false);
返回新的MyViewHolder(itemView);
}
@凌驾
公共无效onBindViewHolder(MyViewHolder,int位置){
holder.text.setText(“+位置);
}
@凌驾
public int getItemCount(){
返回100;
}
}
私有静态类MyViewHolder扩展了RecyclerView.ViewHolder{
私有最终文本查看文本;
公共MyViewHolder(查看项目视图){
超级(项目视图);
this.text=(TextView)itemView.findViewById(R.id.text);
}
}
}
activity_main.xml:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    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"/>

itemview.xml:

<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:padding="8dp"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <ImageView
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/ic_android_black_24dp"/>

    <TextView
        android:id="@+id/text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginLeft="12dp"
        android:layout_marginStart="12dp"
        android:textSize="14sp"
        tools:text="Hello world"/>

</LinearLayout>


在“保存实例”状态下,您是否尝试过
mStepRecyclerView.getAdapterPosition()
?是的。不知怎的,我没有工作。当我试图使用onCreateView()中的适配器位置检索视图时,它返回了一个空视图。这并没有真正帮助我。我使用RecyclerView作为CardView的子视图,CardView本身就是布局的子视图。我已经为RecyclerView设置了一个id,但它不会恢复滚动状态。如何填充RecyclerView适配器中的数据?如果在recyclerview恢复其位置时数据不在那里,系统的自动恢复功能将无法工作。我将所需数据存储在onSaveInstanceState()中,然后将其传递给适配器,适配器使用它填充recyclerview。您在何处检索数据?在哪个生命周期回调方法中?onCreateView()回调谢谢!我没有检查我的电脑