当在 Fragment 中使用 recyclerview 而不是 Activity 时,在滚动时隐藏工具栏
Hide toolbar on scroll when the using a recyclerview inside a Fragment instead of an Activity
我正在尝试调整隐藏/显示工具栏(或任何可视元素)的策略,该策略来自解释得很好且很棒的文章:
http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/
但在我的例子中,我使用片段来保存回收视图而不是 activity。我的问题是没有应用填充,所以第一个元素在工具栏下面,我还有另一个奇怪的行为,因为工具栏也在状态栏下面。我不知道这里发生了什么。
以下是我的"moving pieces":
BasicActivity.java:基于上一个 post 中给出的,但将 recycleview 部分移到片段部分。它还公开了显示和隐藏方法以允许片段访问它:
public class BasicActivity extends ActionBarActivity {
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container,new RecycleFragment())
.commit();
overridePendingTransition(0, 0);
initToolbar();
}
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
}
public void hideViews() {
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));
}
public void showViews() {
mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
}
}
我的activiy_basic.xml如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<include layout="@layout/toolbar_actionbar" />
</FrameLayout>
布局toolbar_actionbar.xml
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:clipToPadding="false"/>
片段RecycleFragment.java:
public class RecycleFragment 扩展片段 {
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler, container, false);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initRecyclerView(view);
}
private void initRecyclerView(View view) {
RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setOnScrollListener(new HidingScrollListener() {
@Override
public void onHide() {
((BasicActivity)getActivity()).hideViews();
}
@Override
public void onShow() {
((BasicActivity)getActivity()).showViews();
}
});
}
private List<String> createItemList() {
List<String> itemList = new ArrayList<>();
for(int i=0;i<20;i++) {
itemList.add("Item "+i);
}
return itemList;
}
}
片段的布局只是一个回收视图 fragment_recycler.xml:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
回收器的适配器和查看器与文章相同,它们不影响行为。
代码有什么问题?
更新:
下面的一位 Michał Z. 指出。缺少的是 Recyclerview 视图上的 paddingTop 和 clipptoPadding
所以最后的xml应该是:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>
而为了解决状态栏重叠的问题,需要在activity布局上添加一个"fitsystemwindows" = "true"元素。所以它必须如下所示:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<FrameLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<include layout="@layout/toolbar_actionbar" />
</FrameLayout>
更新2
仅当主题将状态栏设置为半透明时才需要 fitSystemWindows
您的 fragment_recycler.xml
文件缺少 paddingTop
和 clipToPadding
属性。
它应该是这样的:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>
同时从您的 toolbar_actionbar.xml
中删除 clipToPadding
。
我正在尝试调整隐藏/显示工具栏(或任何可视元素)的策略,该策略来自解释得很好且很棒的文章: http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/
但在我的例子中,我使用片段来保存回收视图而不是 activity。我的问题是没有应用填充,所以第一个元素在工具栏下面,我还有另一个奇怪的行为,因为工具栏也在状态栏下面。我不知道这里发生了什么。 以下是我的"moving pieces":
BasicActivity.java:基于上一个 post 中给出的,但将 recycleview 部分移到片段部分。它还公开了显示和隐藏方法以允许片段访问它:
public class BasicActivity extends ActionBarActivity {
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container,new RecycleFragment())
.commit();
overridePendingTransition(0, 0);
initToolbar();
}
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
}
public void hideViews() {
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));
}
public void showViews() {
mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
}
}
我的activiy_basic.xml如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<include layout="@layout/toolbar_actionbar" />
</FrameLayout>
布局toolbar_actionbar.xml
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:clipToPadding="false"/>
片段RecycleFragment.java: public class RecycleFragment 扩展片段 {
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler, container, false);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initRecyclerView(view);
}
private void initRecyclerView(View view) {
RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setOnScrollListener(new HidingScrollListener() {
@Override
public void onHide() {
((BasicActivity)getActivity()).hideViews();
}
@Override
public void onShow() {
((BasicActivity)getActivity()).showViews();
}
});
}
private List<String> createItemList() {
List<String> itemList = new ArrayList<>();
for(int i=0;i<20;i++) {
itemList.add("Item "+i);
}
return itemList;
}
} 片段的布局只是一个回收视图 fragment_recycler.xml:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
回收器的适配器和查看器与文章相同,它们不影响行为。
代码有什么问题?
更新: 下面的一位 Michał Z. 指出。缺少的是 Recyclerview 视图上的 paddingTop 和 clipptoPadding 所以最后的xml应该是:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>
而为了解决状态栏重叠的问题,需要在activity布局上添加一个"fitsystemwindows" = "true"元素。所以它必须如下所示:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<FrameLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<include layout="@layout/toolbar_actionbar" />
</FrameLayout>
更新2 仅当主题将状态栏设置为半透明时才需要 fitSystemWindows
您的 fragment_recycler.xml
文件缺少 paddingTop
和 clipToPadding
属性。
它应该是这样的:
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>
同时从您的 toolbar_actionbar.xml
中删除 clipToPadding
。