Android高级UI开发(十五)ToolBar随Scrollview滚动而逐渐透明

举报
yd_57386892 发表于 2020/12/29 00:47:27 2020/12/29
【摘要】 前几篇都讲了Toolbar自身的用法,今天讲一下Toolbar结合Scrollview常用的一个效果,效果图如下 1. 我们先实现布局,一个Toolbar,一个列表,布局文件如下: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://s...

前几篇都讲了Toolbar自身的用法,今天讲一下Toolbar结合Scrollview常用的一个效果,效果图如下

1. 我们先实现布局,一个Toolbar,一个列表,布局文件如下:


  
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:app="http://schemas.android.com/apk/res-auto"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. >
  7. <com.example.administrator.scrolltoolba.MyScrollView
  8. android:id="@+id/scrollView"
  9. android:layout_width="fill_parent"
  10. android:layout_height="fill_parent"
  11. >
  12. <android.support.v7.widget.LinearLayoutCompat
  13. android:layout_width="fill_parent"
  14. android:layout_height="fill_parent"
  15. android:orientation="vertical">
  16. <Button
  17. android:id="@+id/button1"
  18. style="?android:attr/buttonStyleSmall"
  19. android:layout_width="match_parent"
  20. android:layout_height="match_parent"
  21. android:text="Button0" />
  22. <Button
  23. style="?android:attr/buttonStyleSmall"
  24. android:layout_width="match_parent"
  25. android:layout_height="match_parent"
  26. android:text="Button1" />
  27. <Button
  28. style="?android:attr/buttonStyleSmall"
  29. android:layout_width="match_parent"
  30. android:layout_height="match_parent"
  31. android:text="Button2" />
  32. <Button
  33. style="?android:attr/buttonStyleSmall"
  34. android:layout_width="match_parent"
  35. android:layout_height="match_parent"
  36. android:text="Button3" />
  37. <Button
  38. style="?android:attr/buttonStyleSmall"
  39. android:layout_width="match_parent"
  40. android:layout_height="match_parent"
  41. android:text="Button4" />
  42. <Button
  43. style="?android:attr/buttonStyleSmall"
  44. android:layout_width="match_parent"
  45. android:layout_height="match_parent"
  46. android:text="Button" />
  47. <Button
  48. style="?android:attr/buttonStyleSmall"
  49. android:layout_width="match_parent"
  50. android:layout_height="match_parent"
  51. android:text="Button" />
  52. <Button
  53. style="?android:attr/buttonStyleSmall"
  54. android:layout_width="match_parent"
  55. android:layout_height="match_parent"
  56. android:text="Button" />
  57. <Button
  58. style="?android:attr/buttonStyleSmall"
  59. android:layout_width="match_parent"
  60. android:layout_height="match_parent"
  61. android:text="Button" />
  62. <Button
  63. style="?android:attr/buttonStyleSmall"
  64. android:layout_width="match_parent"
  65. android:layout_height="match_parent"
  66. android:text="Button" />
  67. <Button
  68. style="?android:attr/buttonStyleSmall"
  69. android:layout_width="match_parent"
  70. android:layout_height="match_parent"
  71. android:text="Button" />
  72. <Button
  73. style="?android:attr/buttonStyleSmall"
  74. android:layout_width="match_parent"
  75. android:layout_height="match_parent"
  76. android:text="Button" />
  77. <Button
  78. style="?android:attr/buttonStyleSmall"
  79. android:layout_width="match_parent"
  80. android:layout_height="match_parent"
  81. android:text="Button" />
  82. <Button
  83. style="?android:attr/buttonStyleSmall"
  84. android:layout_width="match_parent"
  85. android:layout_height="match_parent"
  86. android:text="Button" />
  87. <Button
  88. style="?android:attr/buttonStyleSmall"
  89. android:layout_width="match_parent"
  90. android:layout_height="match_parent"
  91. android:text="Button" />
  92. <Button
  93. style="?android:attr/buttonStyleSmall"
  94. android:layout_width="match_parent"
  95. android:layout_height="match_parent"
  96. android:text="Button" />
  97. </android.support.v7.widget.LinearLayoutCompat>
  98. </com.example.administrator.scrolltoolba.MyScrollView>
  99. <android.support.v7.widget.Toolbar
  100. android:id="@+id/toolbar"
  101. android:layout_width="match_parent"
  102. android:layout_height="?attr/actionBarSize"
  103. android:background="?attr/colorPrimary"
  104. app:title="Toolbar隐藏研究"></android.support.v7.widget.Toolbar>
  105. </RelativeLayout>

通过观察布局,RelativeLayout里先有MyScrollView(自定义Scrollview稍后讲解)后有Toolbar,这是为了能让Toolbar浮动在滚动页面之上,否则Toolbar就被盖在底下不可见了。然后我们用MainAcitivity加载这个布局


  
  1. package com.example.administrator.scrolltoolba;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.support.v7.widget.Toolbar;
  5. public class MainActivity extends AppCompatActivity {
  6. Toolbar toolbar;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main);
  11. toolbar = (Toolbar)findViewById(R.id.toolbar);
  12. setSupportActionBar(toolbar);
  13. }
  14. }

我们运行一下看看效果,结果报错了:This Activity already has an action bar supplied by the window decor

这个是我们的style设置问题,我们既然要自定义Toolbar就得先取消系统的actionbar,  为解决这个报错,我们把values-styles.xml修改如下,让AppTheme为NoActionBar:


  
  1. <resources>
  2. <!-- Base application theme. -->
  3. <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  4. <!-- Customize your theme here. -->
  5. <item name="colorPrimary">@color/colorPrimary_pink</item>
  6. <item name="colorPrimaryDark">@color/colorPrimary_pink</item>
  7. <item name="colorAccent">@color/colorPrimary_pink</item>
  8. </style>
  9. </resources>

修改完后再次运行,正常了,效果如下:

哦,显示出来了!但是Button0不见了!!

我们想要滚动页面的内容整体在Toolbar之下的位置开始显示,要实现这样的位置关系我们可以给MyScrollView设置paddingTop为Toolbar的高度,这样MyScrollView就实现了内容最顶端从Toolbar下方位置开始显示了。有人说你为什么不给MyScrollView设置layout_below属性呢,这样不是也能让MyScrollView的内容从Toolbar下方位置开始显示吗?我们不这样做的原因是我们还想让MyScrollView的内容在上拉滚动时(滚动条Y轴不断向下,内容往下翻)的情况下MyScrollView能让上拉上去的内容占用Toolbar的位置同时让Toolbar逐渐透明以充分利用整个屏幕的高度来显示滚动页,如果设置了layout_below属性那么MyScrollView就彻底只能在Toolbar下方了。MyScrollView的padding设置如下:


  
  1. <com.example.administrator.scrolltoolba.MyScrollView
  2. android:id="@+id/scrollView"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:paddingTop="?attr/actionBarSize"
  6. >
  7. ......

然后我们再运行一下,效果如下图:

 

           这下好了,我们可以专心来实现 上拉滚动页面(滚动条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,代码如下:


  
  1. package com.example.administrator.scrolltoolba;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.widget.ScrollView;
  5. public class MyScrollView extends ScrollView {
  6. public MyScrollView(Context context, AttributeSet attrs) {
  7. super(context, attrs);
  8. // TODO Auto-generated constructor stub
  9. }
  10. @Override
  11. protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  12. super.onScrollChanged(l, t, oldl, oldt);
  13. Log.i("onScrollChanged","l="+l+",t="+t+",oldl="+oldl+",oldt="+oldt+",getScrollY="+getScrollY());
  14. }
  15. }
  16. }

 

从上述代码中可以看到我们重新实现了onScrollChanged函数用以监听滚动的距离,它在手指滚动时回调,onScrollChanged函数有4个参数,到底哪个是我们要的滚动条向下滚动的距离呢(Y轴从滚动控件 顶部算起,一直向下滚动到某一位置的总长度),我们用Log.i打印了5个值,4个参数,一个getScrollY()函数的值。打印日志如下:


  
  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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个参数的含义分别如下:

(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的代码如下:


  
  1. package com.example.administrator.scrolltoolba;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.util.Log;
  5. import android.widget.ScrollView;
  6. public class MyScrollView extends ScrollView {
  7. private TranslucentListener listener;
  8. public void setTranslucentListener(TranslucentListener listener) {
  9. this.listener = listener;
  10. }
  11. public MyScrollView(Context context, AttributeSet attrs) {
  12. super(context, attrs);
  13. // TODO Auto-generated constructor stub
  14. }
  15. @Override
  16. protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  17. super.onScrollChanged(l, t, oldl, oldt);
  18. Log.i("onScrollChanged","l="+l+",t="+t+",oldl="+oldl+",oldt="+oldt+",getScrollY="+getScrollY());
  19. if(listener!=null){
  20. int scrollY = getScrollY();
  21. int screen_height = getContext().getResources().getDisplayMetrics().heightPixels;
  22. if(scrollY<=screen_height/3f){
  23. listener.onTranlucent(1-scrollY/(screen_height/3f));
  24. }
  25. }
  26. }
  27. }

其中 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:


  
  1. package com.example.administrator.scrolltoolba;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.support.v7.widget.Toolbar;
  5. import android.util.Log;
  6. public class MainActivity extends AppCompatActivity implements TranslucentListener {
  7. String TAG = "MainActivity";
  8. Toolbar toolbar;
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. toolbar = (Toolbar)findViewById(R.id.toolbar);
  14. setSupportActionBar(toolbar);
  15. MyScrollView myScrollView = this.findViewById(R.id.scrollView);
  16. myScrollView.setTranslucentListener(this);
  17. }
  18. /**
  19. * 改变透明度
  20. * @param alpha 1-0͸
  21. */
  22. @Override
  23. public void changeTranslucen(float alpha) {
  24. Log.i(TAG,"ALPHA="+alpha);
  25. toolbar.setAlpha(alpha);
  26. }
  27. //这里为了丰富Toolbar给它加了几个菜单
  28. @Override
  29. public boolean onCreateOptionsMenu(Menu menu) {
  30. // Inflate the menu; this adds items to the action bar if it is present.
  31. getMenuInflater().inflate(R.menu.main, menu);
  32. return true;
  33. }
  34. }

TranslucentListener.java:


  
  1. package com.example.administrator.scrolltoolba;
  2. public interface TranslucentListener {
  3. public void changeTranslucen(float alpha);
  4. }

运行效果如下:

我们发现,上拉时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两个属性:


  
  1. <com.example.administrator.scrolltoolba.MyScrollView
  2. android:id="@+id/scrollView"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:clipToPadding="false"
  6. android:clipChildren="false"
  7. android:paddingTop="?attr/actionBarSize"
  8. >

这次运行效果如下:

最终依照惯例源码下载地址:https://download.csdn.net/download/gaoxiaoweiandy/10802702

 

 

 

文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/84349368

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。