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个参数的含义分别如下:

(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

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冉航--小虾米

希望得到您的鼓励和交流

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值