Android高级UI开发(十五)ToolBar随Scrollview滚动而逐渐透明
前几篇都讲了Toolbar自身的用法,今天讲一下Toolbar结合Scrollview常用的一个效果,效果图如下
1. 我们先实现布局,一个Toolbar,一个列表,布局文件如下:
-
<RelativeLayout 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:layout_width="match_parent"
-
android:layout_height="match_parent"
-
>
-
-
<com.example.administrator.scrolltoolba.MyScrollView
-
android:id="@+id/scrollView"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
>
-
-
<android.support.v7.widget.LinearLayoutCompat
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:orientation="vertical">
-
-
<Button
-
android:id="@+id/button1"
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button0" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button1" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button2" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button3" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button4" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
-
<Button
-
style="?android:attr/buttonStyleSmall"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:text="Button" />
-
</android.support.v7.widget.LinearLayoutCompat>
-
</com.example.administrator.scrolltoolba.MyScrollView>
-
-
<android.support.v7.widget.Toolbar
-
android:id="@+id/toolbar"
-
android:layout_width="match_parent"
-
android:layout_height="?attr/actionBarSize"
-
android:background="?attr/colorPrimary"
-
app:title="Toolbar隐藏研究"></android.support.v7.widget.Toolbar>
-
-
</RelativeLayout>
通过观察布局,RelativeLayout里先有MyScrollView(自定义Scrollview稍后讲解)后有Toolbar,这是为了能让Toolbar浮动在滚动页面之上,否则Toolbar就被盖在底下不可见了。然后我们用MainAcitivity加载这个布局
-
package com.example.administrator.scrolltoolba;
-
-
import android.support.v7.app.AppCompatActivity;
-
import android.os.Bundle;
-
import android.support.v7.widget.Toolbar;
-
-
public class MainActivity extends AppCompatActivity {
-
Toolbar toolbar;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
toolbar = (Toolbar)findViewById(R.id.toolbar);
-
setSupportActionBar(toolbar);
-
}
-
}
我们运行一下看看效果,结果报错了:This Activity already has an action bar supplied by the window decor
这个是我们的style设置问题,我们既然要自定义Toolbar就得先取消系统的actionbar, 为解决这个报错,我们把values-styles.xml修改如下,让AppTheme为NoActionBar:
-
<resources>
-
-
<!-- Base application theme. -->
-
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
-
<!-- Customize your theme here. -->
-
<item name="colorPrimary">@color/colorPrimary_pink</item>
-
<item name="colorPrimaryDark">@color/colorPrimary_pink</item>
-
<item name="colorAccent">@color/colorPrimary_pink</item>
-
</style>
-
-
</resources>
修改完后再次运行,正常了,效果如下:
哦,显示出来了!但是Button0不见了!!
我们想要滚动页面的内容整体在Toolbar之下的位置开始显示,要实现这样的位置关系我们可以给MyScrollView设置paddingTop为Toolbar的高度,这样MyScrollView就实现了内容最顶端从Toolbar下方位置开始显示了。有人说你为什么不给MyScrollView设置layout_below属性呢,这样不是也能让MyScrollView的内容从Toolbar下方位置开始显示吗?我们不这样做的原因是我们还想让MyScrollView的内容在上拉滚动时(滚动条Y轴不断向下,内容往下翻)的情况下MyScrollView能让上拉上去的内容占用Toolbar的位置同时让Toolbar逐渐透明以充分利用整个屏幕的高度来显示滚动页,如果设置了layout_below属性那么MyScrollView就彻底只能在Toolbar下方了。MyScrollView的padding设置如下:
-
<com.example.administrator.scrolltoolba.MyScrollView
-
android:id="@+id/scrollView"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:paddingTop="?attr/actionBarSize"
-
>
-
......
然后我们再运行一下,效果如下图:
这下好了,我们可以专心来实现 上拉滚动页面(滚动条Y轴不断向下,内容不断下翻)的时候,随着向上拉动的距离逐渐改变Toolbar的透明度从1-0(1表示不透明,0彻底透明)直到彻底透明。从1-0可以看作从100%到%0, 我们需要一个百分比来衡量,我们定义向上拉动的距离或者说滚动条Y轴向下滚动的距离 为 m, 定义屏幕高度为H,我们可以让m/H 来形成一个比例,1-m/H 来形成一个1-0的透明度值。也就是说,当滚动条向下滚动一个屏幕的高度时,让Toolbar彻底透明为0彻底透明,在未达到一个屏幕的高度时应该是逐渐半透明的效果,也就是说透明度在(0-1)之间,如果没有任何滚动,则Toolbar的 透明度为1是正常显示的。在这里我们感觉H太长了,我们可以把分母变为H/3,也就是说只需要滑动H/3的距离就能让Toolbar过渡到彻底透明,此时透明度计算公式变为 1- m/(H/3)。
那现在我们问题的关键就在于如何获取滚动条Y轴向下滚动的距离,这时我们可以重写Scrollview的onScrollChanged函数来监听滚动的距离(也就是手指上拉的距离),我们自定义一个MyScrollview,代码如下:
-
package com.example.administrator.scrolltoolba;
-
-
import android.content.Context;
-
import android.util.AttributeSet;
-
import android.widget.ScrollView;
-
-
public class MyScrollView extends ScrollView {
-
-
-
-
public MyScrollView(Context context, AttributeSet attrs) {
-
super(context, attrs);
-
// TODO Auto-generated constructor stub
-
}
-
-
@Override
-
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
-
super.onScrollChanged(l, t, oldl, oldt);
-
Log.i("onScrollChanged","l="+l+",t="+t+",oldl="+oldl+",oldt="+oldt+",getScrollY="+getScrollY());
-
}
-
}
-
-
}
从上述代码中可以看到我们重新实现了onScrollChanged函数用以监听滚动的距离,它在手指滚动时回调,onScrollChanged函数有4个参数,到底哪个是我们要的滚动条向下滚动的距离呢(Y轴从滚动控件 顶部算起,一直向下滚动到某一位置的总长度),我们用Log.i打印了5个值,4个参数,一个getScrollY()函数的值。打印日志如下:
-
2018-11-22 22:57:04.246 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=4,oldl=0,oldt=0,getScrollY=4
-
2018-11-22 22:57:04.263 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=11,oldl=0,oldt=4,getScrollY=11
-
2018-11-22 22:57:04.282 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=16,oldl=0,oldt=11,getScrollY=16
-
2018-11-22 22:57:04.297 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=21,oldl=0,oldt=16,getScrollY=21
-
2018-11-22 22:57:04.315 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=26,oldl=0,oldt=21,getScrollY=26
-
2018-11-22 22:57:04.332 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=31,oldl=0,oldt=26,getScrollY=31
-
2018-11-22 22:57:04.352 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=35,oldl=0,oldt=31,getScrollY=35
-
2018-11-22 22:57:04.363 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=40,oldl=0,oldt=35,getScrollY=40
-
2018-11-22 22:57:04.382 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=43,oldl=0,oldt=40,getScrollY=43
-
2018-11-22 22:57:04.400 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=47,oldl=0,oldt=43,getScrollY=47
-
2018-11-22 22:57:04.415 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=52,oldl=0,oldt=47,getScrollY=52
-
2018-11-22 22:57:04.431 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=54,oldl=0,oldt=52,getScrollY=54
-
2018-11-22 22:57:04.446 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=56,oldl=0,oldt=54,getScrollY=56
-
2018-11-22 22:57:04.465 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=60,oldl=0,oldt=56,getScrollY=60
-
2018-11-22 22:57:04.498 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=61,oldl=0,oldt=60,getScrollY=61
-
2018-11-22 22:57:04.630 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=67,oldl=0,oldt=61,getScrollY=67
-
2018-11-22 22:57:04.647 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=70,oldl=0,oldt=67,getScrollY=70
-
2018-11-22 22:57:04.665 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=74,oldl=0,oldt=70,getScrollY=74
-
2018-11-22 22:57:04.681 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=77,oldl=0,oldt=74,getScrollY=77
-
2018-11-22 22:57:04.696 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=79,oldl=0,oldt=77,getScrollY=79
-
2018-11-22 22:57:05.448 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=81,oldl=0,oldt=79,getScrollY=81
-
2018-11-22 22:57:05.448 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=81,oldl=0,oldt=79,getScrollY=81
-
2018-11-22 22:57:05.482 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=82,oldl=0,oldt=81,getScrollY=82
-
2018-11-22 22:57:05.482 8171-8171/com.example.administrator.scrolltoolba I/onScrollChanged: l=0,t=82,oldl=0,oldt=81,getScrollY=82
从日志中我们可以分析出 4个参数的含义分别如下:
l (left)表示滚动到某一个位置时的 最新X轴方向滚动的距离(从滚动页面最左端算起,所以称为left) ,因为我们没有水平滚动,所以滚动页的横向滚动距离一直是0,getScrollX() = 0.
t (top)表示滚动到某一个位置时的 最新Y轴, 它与getScrollY()函数的值一样,都表示滚动条向下滚动到某一位置时的距离(从顶部算起,这也是参数命名为top的原因),它就是我们想要的那个滚动距离 !
oldl 表示 滚动条当前位置的上一个位置的getScrollX()的值,也就是说滚动条在上一个位置点时,滚动页面的沿X轴横向滚动的距离(从滚动页面最左端算起,所以称为old left ),因为没有水平滚动所以值是0。
oldt表示 滚动条当前位置的上一个位置的getScrollY()的值,也就是说滚动条在上一个位置点时,滚动页面沿Y轴纵向滚动的距离(从顶部算起,这也是参数命名为 old top的原因)。
从以上4个参数的含义可以知道第二个参数 t 是我们需要的 那个竖直滚动距离,也就是前述透明度计算公式1- m/ (H/3) 中的m。
也可以知道 Y轴方向滚动,当前位置点 与 上一个位置点 的距离差 为 (t - oldt),例如上次滚动的位置 oldt = 70,当前位置点的Y轴距离为 t = 74, 则两次滚动的距离差为4.
从以上分析得出,我们Toolbar的透明度值 将是 1- t / ( H / 3); 知道了这个我们就可以在onScrollChanged函数里来改变Toolbar的透明度了,这时MyScrollview的代码如下:
-
package com.example.administrator.scrolltoolba;
-
-
import android.content.Context;
-
import android.util.AttributeSet;
-
import android.util.Log;
-
import android.widget.ScrollView;
-
-
public class MyScrollView extends ScrollView {
-
-
private TranslucentListener listener;
-
-
-
public void setTranslucentListener(TranslucentListener listener) {
-
this.listener = listener;
-
}
-
-
public MyScrollView(Context context, AttributeSet attrs) {
-
super(context, attrs);
-
// TODO Auto-generated constructor stub
-
}
-
-
@Override
-
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
-
super.onScrollChanged(l, t, oldl, oldt);
-
Log.i("onScrollChanged","l="+l+",t="+t+",oldl="+oldl+",oldt="+oldt+",getScrollY="+getScrollY());
-
if(listener!=null){
-
int scrollY = getScrollY();
-
int screen_height = getContext().getResources().getDisplayMetrics().heightPixels;
-
if(scrollY<=screen_height/3f){
-
listener.onTranlucent(1-scrollY/(screen_height/3f));
-
}
-
}
-
}
-
-
}
其中 private TranslucentListener listener接口实例是为了回调到MainActivity来修改Toolbar的透明度。onScrollChanged函数中我们先计算出了屏幕高度screen_height, 然后当滚动距离 <= screen_height/3时逐渐修改Toolbar的透明度,透明度值为 1- scrollY/(screen_height/3), 得到了透明度值,然后调用接口listener的changeTranslucen函数将透明度值回传到MainActivity里修改Toolbar的透明度。现在MainActivity.java与TranslucentListener接口的定义如下:
MainActivity.java:
-
package com.example.administrator.scrolltoolba;
-
-
import android.support.v7.app.AppCompatActivity;
-
import android.os.Bundle;
-
import android.support.v7.widget.Toolbar;
-
import android.util.Log;
-
-
public class MainActivity extends AppCompatActivity implements TranslucentListener {
-
String TAG = "MainActivity";
-
Toolbar toolbar;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
toolbar = (Toolbar)findViewById(R.id.toolbar);
-
setSupportActionBar(toolbar);
-
MyScrollView myScrollView = this.findViewById(R.id.scrollView);
-
myScrollView.setTranslucentListener(this);
-
}
-
-
/**
-
* 改变透明度
-
* @param alpha 1-0
-
*/
-
@Override
-
public void changeTranslucen(float alpha) {
-
Log.i(TAG,"ALPHA="+alpha);
-
toolbar.setAlpha(alpha);
-
-
}
-
//这里为了丰富Toolbar给它加了几个菜单
-
@Override
-
public boolean onCreateOptionsMenu(Menu menu) {
-
// Inflate the menu; this adds items to the action bar if it is present.
-
getMenuInflater().inflate(R.menu.main, menu);
-
return true;
-
}
-
}
TranslucentListener.java:
-
package com.example.administrator.scrolltoolba;
-
-
public interface TranslucentListener {
-
-
public void changeTranslucen(float alpha);
-
-
}
运行效果如下:
我们发现,上拉时Toolbar确实由红色变为全透明的了,但是在滚动条之上总是有一个Toolbar高度的空白。这是因为我们之前设定了Scrollview的paddingTop为Toolbar的高度,让Scrollview内容顶部从Toolbar之下开始显示,没有设置Scrollview的layout_below="@+id/Toolbar"的原因是:
一旦设置了Scrollview layout_below于Toolbar,那么Scrollview将永远在Toolbar之下,我们设定paddingTop虽然Scrollview的内部内容显示在了Toolbar之下,但是我们的Scrollview将控件的顶部还是和Toolbar一样高的。
现在我们想要去掉盖在Scrollview上的空白Toolbar占位,只需要设置Scrollview两个属性:
-
<com.example.administrator.scrolltoolba.MyScrollView
-
android:id="@+id/scrollView"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:clipToPadding="false"
-
android:clipChildren="false"
-
android:paddingTop="?attr/actionBarSize"
-
>
这次运行效果如下:
最终依照惯例源码下载地址:https://download.csdn.net/download/gaoxiaoweiandy/10802702
文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/84349368
- 点赞
- 收藏
- 关注作者
评论(0)