如何在不滚动到第一项的情况下更新嵌套的RecyclerView

时间:2019-02-26 18:48:02

标签: android scroll android-recyclerview nested position

我有一个问题,我想通过动态加载数据来更新嵌套的RecyclerView。外部recyclerView是垂直的,内部recyclerView是水平的。因此,我创建了2个适配器。

主要活动:

public class GroupScreenActivity extends AppCompatActivity {


    private RecyclerView recyclerView;
    private OuterRecyclerViewAdapter adapter;



    // the service connection
    private ServiceConnection connection = new ServiceConnection() {
         ... // code that handles the service connection (not relevant for my question)
        }
    };

    @Override
    protected void onStart(){
        // code that bind the service to the activity (not really relevant for my question)
    }

    @Override
    protected void onStop(){
    // code that unbinds the service from the activity (not really relevant for my question)
    }

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

        recyclerView = (RecyclerView) findViewById(R.id.recycler_View);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        updateUI();
    }

    // a Handler that calls a method of a bound service to retrieve the data of interest
    private void updateUI(final String token){

        final Handler handler = new Handler();

        handler.post(new Runnable() {
            @Override
            public void run() {
                if(bound && (mDownloadCliquesService != null)){

                    // holds the list of the statement lists
                    ArrayList<ArrayList<Statement>> myList = mDownloadCliquesService.getDataOfUser();

                    if(adapter == null){
                        // data is passed to the outer recyclerView adapter

                        adapter = new OuterRecyclerViewAdapter(this, myList);
                        recyclerView.setAdapter(adapter);
                    }
                    else{
                        // notify that the data is changed
                        adapter.notifyDataSetChanged();
                    }

                }
                // repeat the whole after 5 seconds
                handler.postDelayed(this, 5000);
            }
        });
    }
}

您将看到:主要活动只是从绑定服务中检索一些数据,并将其传递到外部回收者视图。数据是Statement类型的列表列表。 myList中的列表数给出了外部recyclerview的行,每个列表中的项目将定义每个内部recyclerview的列数。

外部回收站视图如下所示:

public class OuterRecyclerViewAdapter extends RecyclerView.Adapter<OuterRecyclerViewAdapter.InnerRecyclerViewHolder> {


    // some instance variables

    public OuterRecyclerViewAdapter( ... ) {
        ...
    }


    @Override
    public InnerRecyclerViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {

        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.inner_recyclerview_layout, parent, false);

        return new InnerRecyclerViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final InnerRecyclerViewHolder holder, int position) {

        // here, I create the inner recycler view adapter. Do I need to update it too???
        adapter = new InnerRecyclerViewAdapter(context, items, position);

        holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
        holder.recyclerView.setAdapter(adapter);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    public class InnerRecyclerViewHolder extends RecyclerView.ViewHolder {

        private RecyclerView recyclerView;
        private Button mAddButton;
        private Button mSendButton;
        private TextView tvCliqueName;
        private ArrayList<Object> mList;


        public InnerRecyclerViewHolder(View itemView) {
            super(itemView);

            // using 'itemView', get a reference to the inner recycler view.
            recyclerView = (RecyclerView) itemView.findViewById(R.id.inner_recyclerView);

            // get a reference to the clique name
            tvCliqueName = (TextView) itemView.findViewById(R.id.cliqueName);

            // get a reference to the send button
            mSendButton = (Button) itemView.findViewById(R.id.send);

            // get a reference to the add button
            mAddButton = (Button) itemView.findViewById(R.id.add);

        }
    }

}

为了简洁起见,我没有发布内部recyclerview适配器的代码,因为没有适配器参考要更新。 因此,每隔5秒,主要活动就会从我的绑定服务中获取新数据,并将其传递给外部recyclerview适配器,该适配器查看嵌套数组列表中存在多少列表。然后将每个列表传递到内部回收器视图适配器,该适配器再显示每个列表的元素。 因此,我的问题如下:每次更新后,列表都滚动到开头。假设我在第一个列表中有5个元素,并且在更新内部回收者视图自动转到第一个后,我滚动到第三个元素。这是一个简短的GIF输出:

enter image description here

我已经检查了以下StackOverflow帖子: How to save RecyclerView's scroll position using RecyclerView.State?

Nested Recyclerview scrolls by itself

How to save scroll position of recyclerview in fragment

How to save scroll position of RecyclerView in Android?

但是没有成功。我该如何更新以使滚动位置不受影响?

感谢和问候

1 个答案:

答案 0 :(得分:0)

保存水平滚动值:

outerRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        //save dx
    }
});

,并在更新后还原: outerRecyclerView.setScrollX(dx)