Android仿京东的上滑标题栏渐变效果
最近闲来无事,看到京东的的上滑标题栏渐变显示,下滑标题栏渐变消失的效果有些好奇,个人感觉这种效果很Butf,so自己尝试写了一下,先看一下京东的效果图:
先说一下整体思路吧
- 除了ToolBar(也就是上面的标题栏) 被一个ScrollView包起来。
- 监听活动距离
- 根据距离设置标题栏的透明度
好啦,整体思路说完我们就开始说实现吧
实现
- 布局文件编写:
首先是FrameLayout 作为大的父布局,然后是内容区域和A标题栏,内容区域使用ScrollView包起来,如果标题栏上有设置和消息的小图标就在写一个B标题栏 与A标题栏位置相同即可了(因为上滑的时候标题栏透明,而图标是要显示的,如果图标和A标题栏都写在一起会发现 如果标题栏透明则图标也会透明了,也就不显示了。)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.lnhx.sky.jdscrolltoobardemo.view.ScrollTopView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/colorAccent"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="1000dp"
android:background="@color/colorPrimary"
/>
</LinearLayout>
</com.lnhx.sky.jdscrolltoobardemo.view.ScrollTopView>
<RelativeLayout
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="#ffffff"
android:layout_gravity="top"
android:layout_height="50dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textColor="@color/colorAccent"
android:layout_centerInParent="true"
android:textSize="15sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<LinearLayout
android:layout_width="wrap_content"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
>
<ImageView
android:id="@+id/set"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/set_icon"
android:layout_marginRight="15dp"
/>
<ImageView
android:id="@+id/mes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/mes_icon"
/>
</LinearLayout>
</RelativeLayout>
</FrameLayout>
效果图如下
2.自定义ScrollView
创建类继承ScrollView,实现构造方法,重写onScrollChanged方法,定义OnScrollLLinserener接口,接口中只有一个方法 void scroll(ScrollTopView topView,int l, int t, int oldl, int oldt)。OnScrollLLinserener的set方法。
package com.lnhx.sky.wbsportgradedemo.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;
/**
* Created by Sky on 2017-5-22.
*/
public class ScrollTopView extends ScrollView {
private OnScrollLLinserener onScrollLLinserener;//回调接口标量
private float startY;//手指按下的Y
private float scrollY;//手指移动的Y
public ScrollTopView(Context context) {
super(context);
}
public ScrollTopView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollTopView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setOnScrollLLinserener(OnScrollLLinserener onScrollLLinserener)//初始化onScrollLLinserener
{
this.onScrollLLinserener = onScrollLLinserener;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (onScrollLLinserener!=null)
{
this.onScrollLLinserener.scroll( this, l, t, oldl, oldt);//根据OnScrollLLinserener判断如果不为空,则调用接口的scrolll函数,scroll函数会在Activity中实现
}
}
public interface OnScrollLLinserener{
/*
* 用于回调的接口
* */
void scroll(ScrollTopView topView,int l, int t, int oldl, int oldt);
}
}
**注意:如果你觉为什么要这么麻烦获取空间高度呢,直接用 getHeight()方法不行吗,楼主之前也曾被坑,后来度娘告诉我不行,如果直接用getHeight获取高度,则是0。再次附上参考链接http://www.cnblogs.com/yxwkf/p/5221684.html 不明白的去看看吧。
2.为我们自定义的ScrollView设置OnScrollLLinserener监听,并实现scroll方法
content = (ScrollTopView) findViewById(R.id.content);
content.setOnScrollLLinserener(new ScrollTopView.OnScrollLLinserener() {
@Override
public void scroll(ScrollTopView topView,int l, int t, int oldl, int oldt) {
}
});
重点内容
3.在scroll方法中根据startY、scrollY、和控件高度来实现效果吧
首先我们根据oldt获取互动距离因为我们是上滑实现。然后,我们根据屏幕高度的1/3和滑动距离比较,当toolbarhight >=scrollDis时,我们获取scrollDis与toolBarr比,(因为toolBar的渐变的透明度是与互动的距离相关的) 得到比例来设置toolBar的透明度。然后看代码吧,
content.setOnScrollLLinserener(new ScrollTopView.OnScrollLLinserener() {
@Override
public void scroll(ScrollTopView topView,int l, int t, int oldl, int oldt) {
scrollDis = oldt;
if ( (toolbarhight/3f) >= scrollDis) {
float alp = scrollDis / (toolbarhight/3f);
toolbar.setAlpha(alp);
}
}
});
但是,我们会看到也是我上文提到的,标题栏上有设置和消息的图标,他们是不透明的,而且会根据标题栏的出现改变颜色。所以我们这样做:
if (alp<=0.5){
set.setImageResource(R.drawable.set_icon);
mes.setImageResource(R.drawable.mes_icon);
}else{
set.setImageResource(R.drawable.set_icon_se);
mes.setImageResource(R.drawable.mes_icon_se);
}
现在大概讲清楚了:Activity的总体代码是这样的
public class MainActivity extends AppCompatActivity {
private RelativeLayout toolbar;
private ScrollTopView content;
private float toolbarhight;
private ImageView set,mes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
toolbar = (RelativeLayout) findViewById(R.id.toolbar);
set = (ImageView) findViewById(R.id.set);
mes = (ImageView) findViewById(R.id.mes);
toolbar.setAlpha(0);
content = (ScrollTopView) findViewById(R.id.content);
toolbarhight = getResources().getDisplayMetrics().heightPixels;
content.setOnScrollLLinserener(new ScrollTopView.OnScrollLLinserener() {
@Override
public void scroll(float startY, float scrollY) {
scrollDis = oldt;
if ( (toolbarhight/3f) >= scrollDis) {
float alp = scrollDis / (toolbarhight/3f);
toolbar.setAlpha(alp);
if (alp<=0.5)
{
set.setImageResource(R.drawable.set_icon);
mes.setImageResource(R.drawable.mes_icon);
}else
{
set.setImageResource(R.drawable.set_icon_se);
mes.setImageResource(R.drawable.mes_icon_se);
}
}
}
});
}
}