Android 将snackbar移动到底部栏上方
我在使用新的底部栏时遇到了一些问题。Android 将snackbar移动到底部栏上方,android,layout,android-snackbar,snackbar,Android,Layout,Android Snackbar,Snackbar,我在使用新的底部栏时遇到了一些问题。 我不能强迫把蛇形杆移到底部杆的上方(这是设计指南告诉我的) 这是我的activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.androi
我不能强迫把蛇形杆移到底部杆的上方(这是设计指南告诉我的) 这是我的activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main_activity"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main_activity"
app:menu="@menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
替换您的xml->
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="test.tab_activity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/main_activity_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/placeSnackBar">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_menu_gallery" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="?attr/colorPrimary" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
通过更改snackbar的边距,您可以通过编程方式实现这一点,而不会使xml与额外的坐标布局混淆 Java示例:
Snackbar snack = Snackbar.make(findViewById(R.id.coordinatorLayout),
"Your message", Snackbar.LENGTH_LONG);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams)
snack.getView().getLayoutParams();
params.setMargins(leftMargin, topMargin, rightMargin, bottomBar.height);
snack.getView().setLayoutParams(params);
snack.show();
科特林单线:
Snackbar.make(coordinatorLayout, "Your message", Snackbar.LENGTH_LONG).apply {view.layoutParams = (view.layoutParams as CoordinatorLayout.LayoutParams).apply {setMargins(leftMargin, topMargin, rightMargin, bottomBar.height)}}.show()
我在目标操作系统kitkat、棒棒糖和棉花糖上使用25.3.1版设计支持库中的BottomNavigationView和Snackbar。在棒棒糖上和上面,Snackbar隐藏在BottomNavigationView后面,但在Kitkat中,BottomNavigationView隐藏在Snackbar后面 我试着用不同的方法展示Snackbar。当显示Snackbar时,BottomNavigationView将使用translationY属性和插值器在Y轴上平移(向下滚动)。Snackbar消失后,BottomNavigationView将再次显示,并具有相同的translationY属性 隐藏底部导航视图(朝向底部):
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) bottomNavigationView.getLayoutParams();
bottomNavigationView.animate().translationY(bottomNavigationView.getHeight() + layoutParams.bottomMargin).setInterpolator(new LinearInterpolator()).start();
bottomNavigationView.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
在屏幕上显示底部导航视图:
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) bottomNavigationView.getLayoutParams();
bottomNavigationView.animate().translationY(bottomNavigationView.getHeight() + layoutParams.bottomMargin).setInterpolator(new LinearInterpolator()).start();
bottomNavigationView.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
假设您正在使用CoordinatorLayout,则可以在调用show()之前修改Snackbar的layoutparams。通过设置anchorId和anchorGravity,snackBar将显示在底部导航栏上方:
val layoutParams = snackbar.view.layoutParams as CoordinatorLayout.LayoutParams
layoutParams.anchorId = R.id.navigation //Id for your bottomNavBar or TabLayout
layoutParams.anchorGravity = Gravity.TOP
layoutParams.gravity = Gravity.TOP
snackbar.view.layoutParams = layoutParams
有一篇关于如何使用它的好文章。在那里,您将知道如何在
BottomNavigationBar
基本上,下面的代码展示了工具栏
以及底部导航栏
和框架布局
作为片段容器的最常见用法
重要!请注意
BottomNavigationView
使用布局行为处理滚动和SnackBar位置
<android.support.design.widget.AppBarLayout
android:id="@+id/myAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStart="0dp"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_navigation"
app:layout_behavior="murt.shoppinglistapp.ui.BottomNavigationBehavior"
android:background="?android:attr/windowBackground"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_add_shopping_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:useCompatPadding="true"
app:srcCompat="@drawable/ic_add_24"
app:layout_anchor="@id/navigation_bar"
app:layout_anchorGravity="top|right"
android:layout_gravity="top"
/>
class BottomNavigationBehavior:CoordinatorLayout.Behavior{
构造函数():super()
构造函数(context:context,attrs:AttributeSet):super(context,attrs)
覆盖有趣的layoutDependsOn(父项:CoordinatorLayout,子项:BottomNavigationView,
依赖项:视图):布尔值{
if(依赖项为Snackbar.Snackbar布局){
updateSnackbar(子项,依赖项)
}
返回super.layoutDependsOn(父、子、依赖项)
}
私有乐趣更新nackbar(子:视图,snackbarLayout:Snackbar.snackbarLayout){
if(snackbarLayout.layoutParams是CoordinatorLayout.layoutParams){
val params=snackbarLayout.layoutParams作为CoordinatorLayout.layoutParams
params.anchorId=child.id
params.anchorgavity=重力.TOP
params.gravity=gravity.TOP
snackbarLayout.layoutParams=参数
}
}
覆盖启动时的乐趣嵌套滚动(
协调布局:协调布局,
子项:BottomNavigationView,
directTargetChild:视图,
目标:视图,
嵌套滚动轴:Int
):布尔值{
返回NestedScrollAxis==ViewCompat.SCROLL\u AXIS\u VERTICAL
}
覆盖所有已存储的数据滚动(
协调布局:协调布局,
子项:BottomNavigationView,
目标:视图,
dx:Int,
狄:Int,
消耗:无阵列
) {
if(dy<0){
showBottomNavigationView(子级)
}如果(dy>0),则为else{
hideBottomNavigationView(儿童)
}
}
private fun hideBottomNavigationView(视图:底部导航视图){
view.animate().translationY(view.height.toFloat())
}
私人娱乐节目BottomNavigationView(视图:BottomNavigationView){
view.animate().translationY(0f)
}
}
要实现这一点,您必须注意提供给snackbar的视图组是一个协调布局,否则snackbar将不会显示在底部导航菜单上方。如果父布局是协调布局,则可以简单地完成此操作
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams)
snackbar.getView().getLayoutParams();
params.setAnchorId(R.id.navigation); //id of the bottom navigation view
params.gravity = Gravity.TOP;
params.anchorGravity = Gravity.TOP;
snackbar.getView().setLayoutParams(params);
采用新材料设计有一种简单的方法:
Snackbar snackbar= Snackbar.make(view, text, duration);
snackbar.setAnchorView(bottomBar);
因此,
Snackbar
将显示在BottomNavigationView
上方,使用材质组件库,您可以使用该方法使Snackbar
显示在特定视图上方
如果您使用的是BottomAppBar
和fab,则应在setAanchorView
中定义fab。
比如:
FloatingActionButton fab = findViewById(R.id.fab);
Snackbar snackbar = Snackbar.make(view, "Snackbar over BottomAppBar", Snackbar.LENGTH_LONG);
snackbar.setAnchorView(fab);
结果是:
使用BottomNavigationView
可以将其定义为anchorView:
Snackbar snackbar = Snackbar.make(view,"Snackbar over BottomNav",Snackbar.LENGTH_INDEFINITE);
snackbar.setAnchorView(bottomNavigationView);
snackbar.show();
结果:
对于不能使用
协调器布局的任何人,即使使用锚定解决方案,如
知道您可以将侦听器添加到Snackbar
,并且最多(如果不是所有)视图可以在运行时添加布局\u marginBottom
,这可能会有所帮助
从我最初的测试来看,它似乎运行得很好
以下是我的代码,希望能对大家有所帮助
public class ItemActivity extends AppCompatActivity {
private ConstraintLayout mBottomViewConstraintLayout;
private int mPrevBottomPadding = 0;
private Snackbar mSnackbar;
private Snackbar.Callback mCallback = new Snackbar.Callback() {
@Override
public void onShown(Snackbar sb) {
super.onShown( sb );
addMarginToBottomView();
}
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
super.onDismissed( transientBottomBar, event );
initMarginToBottomView();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
//.....
mSnackbar = Snackbar.make(
findViewById( android.R.id.content ),
getString( R.string.snackbar_message_undo_item_removed ),
Snackbar.LENGTH_LONG)
.setAction( getString( R.string.snackbar_action_undo ),
new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemDao.undoDelete( );
}
} )
.addCallback( mCallback )
.setDuration( Constants.SNACKBAR_DURATION_MS );
}
private void addMarginToBottomView() {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mBottomViewConstraintLayout.getLayoutParams();
mPrevBottomPadding = layoutParams.bottomMargin;
layoutParams.bottomMargin += mSnackbar.getView().getHeight();
mBottomViewConstraintLayout.setLayoutParams(layoutParams);
}
private void initMarginToBottomView() {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mBottomViewConstraintLayout.getLayoutParams();
layoutParams.bottomMargin = mPrevBottomPadding;
mBottomViewConstraintLayout.setLayoutParams(layoutParams);
}
private void showSnackbar() {
mSnackbar.show();
}
受Gabriele Mariotti的启发,以下是我的Kotlin解决方案:
Snackbar.make(show_snack_btn, "Yeeeaaay!", Snackbar.LENGTH_LONG).also {
it.anchorView = fab
}.show()
我发现可以将一条准则(或视图,如果不使用ConstraintLayout的话)放置在Snackbar的上方,而不是通过编程方式操纵CoordinatorLayout参数。我在这里使用1表示100%,表示父约束列表的底部:
<androidx.constraintlayout.widget.Guideline
android:id="@+id/snackbar_anchor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="1" />
共享您的完整布局文件。您的布局文件不完整。已编辑我的问题。我想,这是不必要的。你想把snackbar放在bottombar上面吗?是的,就像谷歌的设计指南一样。注意:如果你在片段中显示snackbar,请确保你没有使用com.android。支持:desi
public class ItemActivity extends AppCompatActivity {
private ConstraintLayout mBottomViewConstraintLayout;
private int mPrevBottomPadding = 0;
private Snackbar mSnackbar;
private Snackbar.Callback mCallback = new Snackbar.Callback() {
@Override
public void onShown(Snackbar sb) {
super.onShown( sb );
addMarginToBottomView();
}
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
super.onDismissed( transientBottomBar, event );
initMarginToBottomView();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
//.....
mSnackbar = Snackbar.make(
findViewById( android.R.id.content ),
getString( R.string.snackbar_message_undo_item_removed ),
Snackbar.LENGTH_LONG)
.setAction( getString( R.string.snackbar_action_undo ),
new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemDao.undoDelete( );
}
} )
.addCallback( mCallback )
.setDuration( Constants.SNACKBAR_DURATION_MS );
}
private void addMarginToBottomView() {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mBottomViewConstraintLayout.getLayoutParams();
mPrevBottomPadding = layoutParams.bottomMargin;
layoutParams.bottomMargin += mSnackbar.getView().getHeight();
mBottomViewConstraintLayout.setLayoutParams(layoutParams);
}
private void initMarginToBottomView() {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mBottomViewConstraintLayout.getLayoutParams();
layoutParams.bottomMargin = mPrevBottomPadding;
mBottomViewConstraintLayout.setLayoutParams(layoutParams);
}
private void showSnackbar() {
mSnackbar.show();
}
Snackbar.make(show_snack_btn, "Yeeeaaay!", Snackbar.LENGTH_LONG).also {
it.anchorView = fab
}.show()
<androidx.constraintlayout.widget.Guideline
android:id="@+id/snackbar_anchor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="1" />
Snackbar
.make(containerView, alert.description, Snackbar.LENGTH_LONG).apply {
anchorView = binding?.snackbarAnchor
show()
}