当 RecyclerView 适合屏幕时不要折叠工具栏
Don't collapse Toolbar when RecyclerView fits the screen
我使用 Android Design Library 制作了一个带有工具栏和 TabLayout 的应用程序。
实际上有 2 个选项卡,都有 2 个 RecyclerView,滚动时会自动折叠工具栏。
我的问题是:当 RecyclerView 的项目很少并且完全适合屏幕时(如在 TAB 2 中),我可以禁用工具栏折叠吗?
我见过很多像 CheeseSquare 这样的例子,由 Google 员工制作,问题仍然存在:即使 RecyclerView 只有 1 个项目,工具栏仍然隐藏在滚动。
我想我可以查明 RecyclerView 的第一项是否在屏幕上可见,如果是,则禁用工具栏折叠。前者好实现,后者呢?
这是我的布局:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
android:background="?attr/colorPrimary"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/glucosio_pink"
app:tabSelectedTextColor="@android:color/white"
app:tabIndicatorColor="@color/glucosio_accent"
app:tabTextColor="#80ffffff"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/main_fab"
android:layout_margin="16dp"
android:onClick="onFabClicked"
app:backgroundTint="@color/glucosio_accent"
android:src="@drawable/ic_add_black_24dp"
android:layout_gravity="bottom|right"
/>
</android.support.design.widget.CoordinatorLayout>
您可以检查 RecyclerView
中的最后一项是否可见。如果不是,则使用此方法以编程方式关闭滚动:
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
mToolbar.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(null);
appBarLayout.setLayoutParams(appBarLayoutParams);
最终解决方案(感谢 Michał Z.)
off/on 工具栏滚动的方法:
public void turnOffToolbarScrolling() {
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout);
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
mToolbar.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(null);
appBarLayout.setLayoutParams(appBarLayoutParams);
}
public void turnOnToolbarScrolling() {
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout);
//turn on scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
mToolbar.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(new AppBarLayout.Behavior());
appBarLayout.setLayoutParams(appBarLayoutParams);
}
查看 RecyclerView 的最后一项是否在我的 Fragment 中可见。
如果是,请禁用滚动:
public void updateToolbarBehaviour(){
if (mLayoutManager.findLastCompletelyVisibleItemPosition() == items.size()-1) {
((MainActivity) getActivity()).turnOffToolbarScrolling();
} else {
((MainActivity)getActivity()).turnOnToolbarScrolling();
}
}
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
mToolbar.setLayoutParams(toolbarLayoutParams);
我采用了稍微不同的方法来解决这个问题。
我创建了一个基于单元格禁用自身的自定义 AppBarBehavior。
public class CustomAppBarBehavior extends AppBarLayout.Behavior {
private RecyclerView recyclerView;
private boolean enabled;
public CustomAppBarBehavior() {
}
public CustomAppBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
updatedEnabled();
return enabled && super.onInterceptTouchEvent(parent, child, ev);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
return enabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
return enabled && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
private void updatedEnabled() {
enabled = false;
if(recyclerView != null) {
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
int count = adapter.getItemCount();
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager != null) {
int lastItem = 0;
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
lastItem = Math.abs(linearLayoutManager.findLastCompletelyVisibleItemPosition());
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
int[] lastItems = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(new int[staggeredGridLayoutManager.getSpanCount()]);
lastItem = Math.abs(lastItems[lastItems.length - 1]);
}
enabled = lastItem < count - 1;
}
}
}
}
public void setRecyclerView(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
}
}
然后在应用栏布局上设置自定义行为
appBarBehavior = new CustomAppBarBehavior();
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(appBarBehavior);
appBarLayout.setLayoutParams(appBarLayoutParams);
视图寻呼机的最后一次页面更改更新了 RecyclerView 的行为
private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
@Override
public void onPageSelected(final int position) {
appBarLayout.setExpanded(true, true);
appBarLayout.post(new Runnable() {
@Override
public void run() {
appBarBehavior.setRecyclerView(childFragments.get(position).getRecyclerView());
}
});
}
@Override
public void onPageScrollStateChanged(int state) { }
};
这应该适用于不断变化的数据集。
RecyclerView
现在(自版本 23.2 起)支持 wrap_content
。只需使用 wrap_content
作为高度。
只需从
中删除卷轴
app:layout_scrollFlags="scroll|enterAlways"
所以应该是
app:layout_scrollFlags="enterAlways"
在适配器中更改数据后添加此代码:
recyclerView.afterMeasured {
val isTurnedOff = recyclerView.turnOffNestedScrollingIfEnoughItems()
if (isTurnedOff) appBarLayout.setExpanded(true)
}
这是函数:
inline fun <T: View> T.afterMeasured(crossinline action: T.() -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
action()
}
})
}
fun RecyclerView.turnOffNestedScrollingIfEnoughItems(): Boolean {
val lm = (layoutManager as LinearLayoutManager)
val count = if (lm.itemCount <= 0) 0 else lm.itemCount - 1
val isFirstVisible = lm.findFirstCompletelyVisibleItemPosition() == 0
val isLastItemVisible = lm.findLastCompletelyVisibleItemPosition() == count
isNestedScrollingEnabled = !(isLastItemVisible && isFirstVisible)
return isNestedScrollingEnabled.not()
}
您可以在您的 XML 中添加值为 @string/appbar_scrolling_view_behavior
的 属性 layout_behaviour
:
app:layout_behavior="@string/appbar_scrolling_view_behavior"
如果根据正确答案帮助了 Kotlin 中的任何人,我为 Kotlin 做了这个:
fun changeToolbarScroll(isToScrolling: Boolean){
val params = toolbar.layoutParams as AppBarLayout.LayoutParams
val appBarLayoutParams = appBarLayout.layoutParams as
CoordinatorLayout.LayoutParams
params.scrollFlags = 0
toolbar.layoutParams = params
appBarLayoutParams.behavior = null
appBarLayout.layoutParams = appBarLayoutParams
if(isToScrolling){
params.scrollFlags =
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or
AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
toolbar.layoutParams = params
appBarLayoutParams.behavior = AppBarLayout.Behavior()
appBarLayout.layoutParams = appBarLayoutParams
}
}
就我而言,我的 MainActivity 有问题,它由 2 个 Fragment 管理导航、工具栏和其他共享内容,第一个 Framgent 使用 RecyclerView,第二个用于显示 deatil。
问题是当我设置菜单并从 MainAcitivity
更改 MenuItem 时
这听起来可能很愚蠢而且完全合乎逻辑,但请记住 在调用 supportFragmentManager.beginTransaction() 之前总是对 Menu 或 MenuItems 进行更改,否则更改片段将不起作用,或者没有正确更新,无论 .add、.replace()、show()...
fun showDetailImageFragment(searchImage: SearchImage) {
val searchFragment =
supportFragmentManager.findFragmentByTag(SEARCH_IMAGES)
changeToolbarScroll(false)
if (supportActionBar != null) {
supportActionBar!!.collapseActionView()
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.title = getString(R.string.detail_image_title)
}
actionSearch.isVisible = false
actionNighMOde.isVisible = false
actionAppSetings.isVisible = false
actionAbout.isVisible = false
supportFragmentManager.beginTransaction()
.setCustomAnimations(
R.animator.fade_in,
R.animator.fade_out,
R.animator.fade_in,
R.animator.fade_out
)
.hide(searchFragment!!)
.add(
R.id.frameLayout,
DetailImageFragment().newInstance(searchImage)
).addToBackStack(null)
.commit()
}
我想这是最好的解决方案。
您需要定义自定义 AppBarLayout 行为:
class CustomScrollingViewBehavior : AppBarLayout.Behavior {
constructor() : super()
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
var shouldScroll = true
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
return shouldScroll && when (target) {
is NestedScrollView, is ScrollView, is RecyclerView -> {
return target.canScrollVertically(1) || target.canScrollVertically(-1)
}
else -> super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
}
}
}
然后你只需要在你的布局中使用它作为 AppBarLayout 的属性:
...
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="56dp"
app:layout_behavior=".CustomScrollingViewBehavior">
...
就是这样。
注意:自定义行为还支持完全禁用滚动 - 您只需将 shouldScroll 标志设置为 false
customScrollingViewBehavior.shouldScroll = false
我使用 Android Design Library 制作了一个带有工具栏和 TabLayout 的应用程序。
实际上有 2 个选项卡,都有 2 个 RecyclerView,滚动时会自动折叠工具栏。
我的问题是:当 RecyclerView 的项目很少并且完全适合屏幕时(如在 TAB 2 中),我可以禁用工具栏折叠吗?
我见过很多像 CheeseSquare 这样的例子,由 Google 员工制作,问题仍然存在:即使 RecyclerView 只有 1 个项目,工具栏仍然隐藏在滚动。
我想我可以查明 RecyclerView 的第一项是否在屏幕上可见,如果是,则禁用工具栏折叠。前者好实现,后者呢?
这是我的布局:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
android:background="?attr/colorPrimary"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/glucosio_pink"
app:tabSelectedTextColor="@android:color/white"
app:tabIndicatorColor="@color/glucosio_accent"
app:tabTextColor="#80ffffff"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/main_fab"
android:layout_margin="16dp"
android:onClick="onFabClicked"
app:backgroundTint="@color/glucosio_accent"
android:src="@drawable/ic_add_black_24dp"
android:layout_gravity="bottom|right"
/>
</android.support.design.widget.CoordinatorLayout>
您可以检查 RecyclerView
中的最后一项是否可见。如果不是,则使用此方法以编程方式关闭滚动:
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
mToolbar.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(null);
appBarLayout.setLayoutParams(appBarLayoutParams);
最终解决方案(感谢 Michał Z.)
off/on 工具栏滚动的方法:
public void turnOffToolbarScrolling() {
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout);
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
mToolbar.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(null);
appBarLayout.setLayoutParams(appBarLayoutParams);
}
public void turnOnToolbarScrolling() {
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout);
//turn on scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
mToolbar.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(new AppBarLayout.Behavior());
appBarLayout.setLayoutParams(appBarLayoutParams);
}
查看 RecyclerView 的最后一项是否在我的 Fragment 中可见。
如果是,请禁用滚动:
public void updateToolbarBehaviour(){
if (mLayoutManager.findLastCompletelyVisibleItemPosition() == items.size()-1) {
((MainActivity) getActivity()).turnOffToolbarScrolling();
} else {
((MainActivity)getActivity()).turnOnToolbarScrolling();
}
}
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
mToolbar.setLayoutParams(toolbarLayoutParams);
我采用了稍微不同的方法来解决这个问题。
我创建了一个基于单元格禁用自身的自定义 AppBarBehavior。
public class CustomAppBarBehavior extends AppBarLayout.Behavior {
private RecyclerView recyclerView;
private boolean enabled;
public CustomAppBarBehavior() {
}
public CustomAppBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
updatedEnabled();
return enabled && super.onInterceptTouchEvent(parent, child, ev);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
return enabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
return enabled && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
private void updatedEnabled() {
enabled = false;
if(recyclerView != null) {
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
int count = adapter.getItemCount();
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager != null) {
int lastItem = 0;
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
lastItem = Math.abs(linearLayoutManager.findLastCompletelyVisibleItemPosition());
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
int[] lastItems = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(new int[staggeredGridLayoutManager.getSpanCount()]);
lastItem = Math.abs(lastItems[lastItems.length - 1]);
}
enabled = lastItem < count - 1;
}
}
}
}
public void setRecyclerView(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
}
}
然后在应用栏布局上设置自定义行为
appBarBehavior = new CustomAppBarBehavior();
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(appBarBehavior);
appBarLayout.setLayoutParams(appBarLayoutParams);
视图寻呼机的最后一次页面更改更新了 RecyclerView 的行为
private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
@Override
public void onPageSelected(final int position) {
appBarLayout.setExpanded(true, true);
appBarLayout.post(new Runnable() {
@Override
public void run() {
appBarBehavior.setRecyclerView(childFragments.get(position).getRecyclerView());
}
});
}
@Override
public void onPageScrollStateChanged(int state) { }
};
这应该适用于不断变化的数据集。
RecyclerView
现在(自版本 23.2 起)支持 wrap_content
。只需使用 wrap_content
作为高度。
只需从
中删除卷轴app:layout_scrollFlags="scroll|enterAlways"
所以应该是
app:layout_scrollFlags="enterAlways"
在适配器中更改数据后添加此代码:
recyclerView.afterMeasured {
val isTurnedOff = recyclerView.turnOffNestedScrollingIfEnoughItems()
if (isTurnedOff) appBarLayout.setExpanded(true)
}
这是函数:
inline fun <T: View> T.afterMeasured(crossinline action: T.() -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
action()
}
})
}
fun RecyclerView.turnOffNestedScrollingIfEnoughItems(): Boolean {
val lm = (layoutManager as LinearLayoutManager)
val count = if (lm.itemCount <= 0) 0 else lm.itemCount - 1
val isFirstVisible = lm.findFirstCompletelyVisibleItemPosition() == 0
val isLastItemVisible = lm.findLastCompletelyVisibleItemPosition() == count
isNestedScrollingEnabled = !(isLastItemVisible && isFirstVisible)
return isNestedScrollingEnabled.not()
}
您可以在您的 XML 中添加值为 @string/appbar_scrolling_view_behavior
的 属性 layout_behaviour
:
app:layout_behavior="@string/appbar_scrolling_view_behavior"
如果根据正确答案帮助了 Kotlin 中的任何人,我为 Kotlin 做了这个:
fun changeToolbarScroll(isToScrolling: Boolean){
val params = toolbar.layoutParams as AppBarLayout.LayoutParams
val appBarLayoutParams = appBarLayout.layoutParams as
CoordinatorLayout.LayoutParams
params.scrollFlags = 0
toolbar.layoutParams = params
appBarLayoutParams.behavior = null
appBarLayout.layoutParams = appBarLayoutParams
if(isToScrolling){
params.scrollFlags =
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or
AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
toolbar.layoutParams = params
appBarLayoutParams.behavior = AppBarLayout.Behavior()
appBarLayout.layoutParams = appBarLayoutParams
}
}
就我而言,我的 MainActivity 有问题,它由 2 个 Fragment 管理导航、工具栏和其他共享内容,第一个 Framgent 使用 RecyclerView,第二个用于显示 deatil。 问题是当我设置菜单并从 MainAcitivity
更改 MenuItem 时这听起来可能很愚蠢而且完全合乎逻辑,但请记住 在调用 supportFragmentManager.beginTransaction() 之前总是对 Menu 或 MenuItems 进行更改,否则更改片段将不起作用,或者没有正确更新,无论 .add、.replace()、show()...
fun showDetailImageFragment(searchImage: SearchImage) {
val searchFragment =
supportFragmentManager.findFragmentByTag(SEARCH_IMAGES)
changeToolbarScroll(false)
if (supportActionBar != null) {
supportActionBar!!.collapseActionView()
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.title = getString(R.string.detail_image_title)
}
actionSearch.isVisible = false
actionNighMOde.isVisible = false
actionAppSetings.isVisible = false
actionAbout.isVisible = false
supportFragmentManager.beginTransaction()
.setCustomAnimations(
R.animator.fade_in,
R.animator.fade_out,
R.animator.fade_in,
R.animator.fade_out
)
.hide(searchFragment!!)
.add(
R.id.frameLayout,
DetailImageFragment().newInstance(searchImage)
).addToBackStack(null)
.commit()
}
我想这是最好的解决方案。 您需要定义自定义 AppBarLayout 行为:
class CustomScrollingViewBehavior : AppBarLayout.Behavior {
constructor() : super()
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
var shouldScroll = true
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
return shouldScroll && when (target) {
is NestedScrollView, is ScrollView, is RecyclerView -> {
return target.canScrollVertically(1) || target.canScrollVertically(-1)
}
else -> super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
}
}
}
然后你只需要在你的布局中使用它作为 AppBarLayout 的属性:
...
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="56dp"
app:layout_behavior=".CustomScrollingViewBehavior">
...
就是这样。
注意:自定义行为还支持完全禁用滚动 - 您只需将 shouldScroll 标志设置为 false
customScrollingViewBehavior.shouldScroll = false