我在NavigationView中创建了一个RecyclerView,其自定义的第一项与ListView的 addHeaderView()等效。在该标题布局的底部,我放置了一个EditText,以便我可以过滤掉下面的列表。
我想要做的是将RecyclerView一直向上滚动,直到EditText成为最重要的项目,只要EditText获得焦点。但是,如果我的项目数量足够小以至于无法填充NavigationView的整个高度,则RecyclerView会拒绝一直向上滚动,从而显示除EditText之外的更多标题。另外一个问题是,即使列表足够大,一旦我开始过滤列表项,它仍然会向下滚动。
即使我没有足够的物品来填充视图的高度,我仍然可以强制我的RecyclerView仍然向上滚动,以便我的其余部分不会偷看?
这是我想要实现的目标的可视化:
_______________
| HEADER LINE 1 |
| HEADER LINE 2 |
| HEADER LINE 3 |
| ------------- |
| Search box |
| ------------- |
| List item 1 |
| List item 2 |
| List item 3 |
---------------
当我专注于搜索框时的预期行为:
_______________
| ------------- |
| Search box | <- becomes the topmost item. I can already achieve this
| ------------- | with RecyclerView.smoothScrollBy(dx, dy)
| List item 1 | except when the list is small enough (see below)
| List item 2 |
| List item 3 |
| List item 4 |
| | <- empty space is okay and is desired if dataset
| | is small enough
---------------
实际发生的事情:
_______________
| HEADER LINE 2 | <- the header is 'bleeding' on top
| HEADER LINE 3 |
| ------------- |
| Search box | <- search box cannot take the topmost spot
| ------------- | as the recycler tries to position itself to fill in
| List item 1 | the bottom part with items
| List item 2 |
| List item 3 |
| List item 4 | <- items are pushed down to the bottom to fill
--------------- in the space
这是我的NavigationView xml的片段(只是您的典型设置):
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true">
<android.support.v7.widget.RecyclerView
android:id="@+id/drawer_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.NavigationView>
ViewHolder with custom header(RecyclerView Adapter):
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == HEADER) {
return new HeaderHolder(mHeaderView);
} else {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ItemViewHolder(v);
}
}
抽屉标题只是我在主要活动中膨胀的xml布局(我在那里指定了监听器和动画)并通过我制作的 setHeaderView(View header)传递给我的RecyclerView适配器。 / p>
答案 0 :(得分:1)
您需要的是一个与标题高度相同的页脚。
这里有两种情况需要考虑:
在第一种情况下,解决方案非常简单。只需在<dimen name="header_height">300dp</dimen>
等值中定义标题的高度,然后按以下方式定义页眉和页脚:
<FrameLayout
android:layout_height="@dimen/header_height">
<!-- Content goes here -->
</FrameLayout>
在第二种情况下,我们将不得不做几件事:
有很多方法可以做到这一点。我之前使用过的一种方法是,您可以在RecyclerView上使用ViewTreeObserver.OnPreDrawListener
来检测标题何时具有高度(以及随后是否已更改),然后将该高度传递给RecyclerView.Adapter
它会用它来设置页脚膨胀时所请求的页脚高度,然后你需要用你的页脚索引调用适配器上的notifyItemChanged(int)
来告诉它重新给你的页脚充气。这是我刚才在代码中描述的大部分内容:
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.drawer_content);
recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if(recyclerView.getChildCount() < 1 || recyclerView.getChildAt(0) == null || recyclerView.getChildAt(0).getHeight() == 0) {
return true;
}
int headerHeight = recyclerView.getChildAt(0).getHeight();
adapter.setFooterHeight(headerHeight);
return true;
}
});
在适配器中:
int footerHeight = 0;
public void setFooterHeight(int footerHeight){
if(this.footerHeight == footerHeight){
return;
}
this.footerHeight = footerHeight;
notifyItemChanged(getItemCount() - 1);
}
然后你唯一需要做的就是让你的页脚膨胀,就像你已经是你的标题一样,并将其高度设置为footerHeight
。
希望这有帮助。