在 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)
对我不起作用。幸运的是,在我的应用程序中,过度滚动一个像素并不明显。
我正在使用 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)
对我不起作用。幸运的是,在我的应用程序中,过度滚动一个像素并不明显。