在 recyclerview 中滚动会滚动到视图底部而不是顶部

Scroll in recyclerview scrolls to bottom of view instead of top

我正在使用 RecyclerView 来显示书中的页面。我有一个 EditText 框,可以将您带到书中的一页。唯一的问题是,当它滚动到书页时,有时会滚动到页面顶部,有时会滚动到底部。我认为这与 RecyclerView 有关,并且在我滚动到页面之前它没有加载页面视图。我希望它始终滚动到页面顶部,但我不确定最好的方法。

这里是相关代码

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

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

        EditText editText = (EditText) findViewById(R.id.page);
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                boolean handled = false;
                if (actionId == EditorInfo.IME_ACTION_GO) {
                    int p = Integer.valueOf(v.getText().toString()) - 1;
                    scrollToPage(p);
                    handled = true;
                }
                return handled;
            }
        });

        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mAdapter = new MyAdapter(pages);
        mRecyclerView.setAdapter(mAdapter);

    }

    //*******************RECYCLERVIE***************************************8//
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
        private String[] mDataset;
        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder
        public class ViewHolder extends RecyclerView.ViewHolder {
            // each data item is just a string in this case
            public TextView mTextView;
            public TextView pageNumber;
            public ViewHolder(View v) {
                super(v);
                mTextView = (TextView) v.findViewById(R.id.info_text);
                pageNumber = (TextView) v.findViewById(R.id.page_number);
            }
        }

        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(String[] myDataset) {
            //my Dataset is an array with 4 members making up the 4 pages//
            mDataset = myDataset;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                       int viewType) {
            // create a new view
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.cards, parent, false);
            // set the view's size, margins, paddings and layout parameters
            ViewHolder vh = new ViewHolder(v);
            return vh;
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element
            holder.mTextView.setText(mDataset[position]);
            int page = position + 1;
            holder.pageNumber.setText("" + page);

        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return mDataset.length;
        }
    }


    //******SCROLL TO TOP BUTTON************//
    public void scrollToTop(View v){
        mLayoutManager.scrollToPosition(0);
    }

    //*******************SCROLL TO SELECTED PAGE***********//
    public void scrollToPage(int p){
        mLayoutManager.scrollToPosition(p);
    }


}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- A RecyclerView with some commonly used attributes -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="GO TO TOP"
            android:onClick="scrollToTop"
            android:layout_gravity="bottom|left"/>

        <EditText
            android:id="@+id/page"
            android:layout_width="50dp"
            android:layout_height="20dp"
            android:layout_gravity="bottom|center_horizontal"
            android:imeOptions="actionGo"
            android:inputType="number"
            android:background="@color/cardview_light_background"/>

    </LinearLayout>
</RelativeLayout>

cards.xml

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

<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="300dp"
    android:layout_height="500dp"
    android:layout_gravity="center"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/frayedpaper"
        android:text="@string/body" />

    <TextView
        android:id="@+id/page_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:text="page"/>

</android.support.v7.widget.CardView>

我自己之前 运行 遇到过这个问题,我发现调用 LayoutManager.scrollToPositionWithOffset(position, 1) 而不是简单地 LayoutManager.scrollToPosition(position) 为我解决了这个问题。

不幸的是,我真的不知道为什么这行得通。似乎一个像素的偏移以某种方式改变了布局管理器的计算;调用 scrollToPositionWithOffset(position, 0) 对我不起作用。幸运的是,在我的应用程序中,过度滚动一个像素并不明显。