如何让AppBarLayout背景透明
How to make AppBarLayout background transparent
我正在尝试制作类似于 Play 商店中的搜索片段:
我的AppBarLayout
里面有一个CardView
,背景设置为透明:
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:elevation="0dp">
<!-- CardView -->
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- Main content -->
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
但是正如你所看到的,CardView
后面有一个坚实的背景,所以它后面的内容被隐藏了:
如何使 AppBarLayout
的背景透明,以便后面的内容可见?
尝试将 CardView 放入尺寸为 match_parent
的 FrameLayout 中,以便 CardView 周围有 space。我不是 100% 相信它会起作用,但值得一试。
我尝试了很多代码来或多或少地给出你要找的东西。这是一个替代解决方案,但您需要将 AppBarLayout 更改为简单视图...看这个:
<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/annonce.main.coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="RtlHardcoded">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!-- here you put your search bar, can be any view !-->
<android.support.v7.widget.CardView
android:id="@+id/searchbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_behavior="[package].RecyclerSearchBehavior">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:hint="Pesquise aqui"
android:minHeight="58dp"/>
</android.support.v7.widget.CardView>
注意:这是在 CoordinatorLayout 中。
创建一个视图是您使用的搜索栏类型的行为:
public class RecyclerSearchBehavior extends CoordinatorLayout.Behavior<CardView> {
//Initial height and location
private int mViewHeight;
private int[] mViewStartLocation;
public RecyclerSearchBehavior(Context context, AttributeSet attrs) {
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, final CardView child, View dependency) {
//the first function called. The initial variables settings.
//getting height
mViewHeight = child.getHeight();
//getting location on screen
mViewStartLocation = new int[2];
child.getLocationOnScreen(mViewStartLocation);
//if the dependecy is your recycler
if (dependency instanceof RecyclerView)
//add scroll listener
((RecyclerView) dependency).addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
//here the magic happens
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//animate function
animate(child, dy);
}
});
return dependency instanceof RecyclerView;
}
private void animate(CardView child, int dy) {
//the initial position of your search bar is 0, because it is on top, so...
if (child.getY() <= 0)
//dy is an integer that shows you if user scrolls up or down
if (dy >= 0) {
//move to top is a negative value, so *-1
//if that is < than height, scrools up
if ((child.getY() * -1) <= (mViewHeight))
child.setTranslationY(child.getY() - dy * 0.1f);
} else {
//if the position of search bar is < than zero, scrolls down
if (child.getY() < 0)
child.setTranslationY(child.getY() - dy * 0.1f);
//else, put the view on 0y
else child.setY(0);
}
//else, put the view on 0y again. this function is called after any user
//touches... so everything happens fast and with numbers different than
//1
else child.setY(0);
}
}
完成了。你的 "search bar" 在这里。
这里唯一的问题是,您需要为 Recycler 上的第一个项目添加填充,或者将透明视图作为第一个项目。
同样的问题发生在我身上,此时它与AppBarLayout
的透明度无关。但是 AppBarLayout
在淡入时将 NestedScrollView
的内容推到自身下方。
你可以通过
解决这个问题
- 将您的
NestedScrollView
向上移动到 AppBarLayout
和 之后
- 向您的
NestedScrollView
添加一个 space 元素,其大小与 AppBar 相同
步骤 1 可以通过将此添加到您的 onCreate()
中轻松实现
mNestedScroll.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mNestedScroll.getViewTreeObserver().removeOnGlobalLayoutListener(this);
final int appBarHeight = mAppBar.getHeight();
mNestedScroll.setTranslationY(-appBarHeight);
mNestedScroll.getLayoutParams().height = mNestedScroll.getHeight() + appBarHeight;
}
});
对于第 2 步,您需要添加一个空视图,其中 appBar 的高度作为 spacer 到您的 NestedScrollView
。注意:我在我的方法中使用了 RecyclerView
而不是 NestedScrollView
,所以我不得不向我的 RecyclerView 添加一个带有 appBarHeight 的空 ViewHolder。所以这个片段没有经过测试,但它应该可以为你解决问题:
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
另一种选择是将负上边距添加到 NestedScrollView
(或使用 appbar_scrolling_view_behavior
的任何视图)并为其直接子级添加相同的正上边距(或填充):
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_marginTop="-100dp" >
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="100dp" >
...
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null" >
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed" >
...
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
请注意,为了使此方法起作用,AppBarLayout
应放在布局文件中的 NestedScrollView
下方。如果 NestedScrollView
的褪色边缘产生视觉伪像,请将 android:overScrollMode="never"
添加到其参数中。使用 elevation
时也要小心,因为当它用在错误的地方时(例如,当应用于整个 AppBarLayout
时),也可能会产生视觉伪影。
我正在尝试制作类似于 Play 商店中的搜索片段:
我的AppBarLayout
里面有一个CardView
,背景设置为透明:
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:elevation="0dp">
<!-- CardView -->
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- Main content -->
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
但是正如你所看到的,CardView
后面有一个坚实的背景,所以它后面的内容被隐藏了:
如何使 AppBarLayout
的背景透明,以便后面的内容可见?
尝试将 CardView 放入尺寸为 match_parent
的 FrameLayout 中,以便 CardView 周围有 space。我不是 100% 相信它会起作用,但值得一试。
我尝试了很多代码来或多或少地给出你要找的东西。这是一个替代解决方案,但您需要将 AppBarLayout 更改为简单视图...看这个:
<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/annonce.main.coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="RtlHardcoded">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!-- here you put your search bar, can be any view !-->
<android.support.v7.widget.CardView
android:id="@+id/searchbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_behavior="[package].RecyclerSearchBehavior">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:hint="Pesquise aqui"
android:minHeight="58dp"/>
</android.support.v7.widget.CardView>
注意:这是在 CoordinatorLayout 中。 创建一个视图是您使用的搜索栏类型的行为:
public class RecyclerSearchBehavior extends CoordinatorLayout.Behavior<CardView> {
//Initial height and location
private int mViewHeight;
private int[] mViewStartLocation;
public RecyclerSearchBehavior(Context context, AttributeSet attrs) {
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, final CardView child, View dependency) {
//the first function called. The initial variables settings.
//getting height
mViewHeight = child.getHeight();
//getting location on screen
mViewStartLocation = new int[2];
child.getLocationOnScreen(mViewStartLocation);
//if the dependecy is your recycler
if (dependency instanceof RecyclerView)
//add scroll listener
((RecyclerView) dependency).addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
//here the magic happens
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//animate function
animate(child, dy);
}
});
return dependency instanceof RecyclerView;
}
private void animate(CardView child, int dy) {
//the initial position of your search bar is 0, because it is on top, so...
if (child.getY() <= 0)
//dy is an integer that shows you if user scrolls up or down
if (dy >= 0) {
//move to top is a negative value, so *-1
//if that is < than height, scrools up
if ((child.getY() * -1) <= (mViewHeight))
child.setTranslationY(child.getY() - dy * 0.1f);
} else {
//if the position of search bar is < than zero, scrolls down
if (child.getY() < 0)
child.setTranslationY(child.getY() - dy * 0.1f);
//else, put the view on 0y
else child.setY(0);
}
//else, put the view on 0y again. this function is called after any user
//touches... so everything happens fast and with numbers different than
//1
else child.setY(0);
}
}
完成了。你的 "search bar" 在这里。
这里唯一的问题是,您需要为 Recycler 上的第一个项目添加填充,或者将透明视图作为第一个项目。
同样的问题发生在我身上,此时它与AppBarLayout
的透明度无关。但是 AppBarLayout
在淡入时将 NestedScrollView
的内容推到自身下方。
你可以通过
解决这个问题- 将您的
NestedScrollView
向上移动到AppBarLayout
和 之后
- 向您的
NestedScrollView
添加一个 space 元素,其大小与 AppBar 相同
步骤 1 可以通过将此添加到您的 onCreate()
mNestedScroll.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mNestedScroll.getViewTreeObserver().removeOnGlobalLayoutListener(this);
final int appBarHeight = mAppBar.getHeight();
mNestedScroll.setTranslationY(-appBarHeight);
mNestedScroll.getLayoutParams().height = mNestedScroll.getHeight() + appBarHeight;
}
});
对于第 2 步,您需要添加一个空视图,其中 appBar 的高度作为 spacer 到您的 NestedScrollView
。注意:我在我的方法中使用了 RecyclerView
而不是 NestedScrollView
,所以我不得不向我的 RecyclerView 添加一个带有 appBarHeight 的空 ViewHolder。所以这个片段没有经过测试,但它应该可以为你解决问题:
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
另一种选择是将负上边距添加到 NestedScrollView
(或使用 appbar_scrolling_view_behavior
的任何视图)并为其直接子级添加相同的正上边距(或填充):
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_marginTop="-100dp" >
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="100dp" >
...
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null" >
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed" >
...
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
请注意,为了使此方法起作用,AppBarLayout
应放在布局文件中的 NestedScrollView
下方。如果 NestedScrollView
的褪色边缘产生视觉伪像,请将 android:overScrollMode="never"
添加到其参数中。使用 elevation
时也要小心,因为当它用在错误的地方时(例如,当应用于整个 AppBarLayout
时),也可能会产生视觉伪影。