Android中像拉钩首页、QQ空间、淘宝详情页都有渐变的效果,看起来高逼格的样子,这里打算用ScrollView来实现类似效果,实现起来挺简单,不过也有挺多小问题出现。
拉钩首页首页渐变效果:
淘宝详情页渐变效果:
实现后的效果:
这里实现参考了 http://blog.csdn.net/qq_22393017/article/details/54602925中的思路,不过这位兄弟也有一些地方在我动手去做时遇到的问题。首先要实现标题栏和ScrollView有2种方式:
1、通过自定义View,让其包含ScrollView子控件;2、自定义一个ScrollView,重写onScrollChanged方法。
这里我也选择了第二种方法,重写onScrollChanged方法,继承ScrollView。
思路
向上移动:标题栏由透明渐变成不透明,头图像由不透明渐变成透明;向下移动:标题栏由不透明渐变成透明,头图像由透明渐变不透明。
我们都知道透明度取值范围是0--255(也就是渐变取值范围),当向上或向下移动时给标题栏和头图像设置透明度值就可以了,这个透明度值根据向上或向下移动的百分比乘以255就ok了。
高度(向上或向下移动的高度)percent(移动百分比) = -------------------------------------------------总高度(头图标高度-标题栏高度)
上面公式一定要理解(就除法嘛),有了上面的思路了,每当移动就给标题栏和头图像设置透明度(percent*255)就ok了。思路就是这么简单,实现起来也是,不够当中遇到点小问题,后面也会说并且决解。
重写onScrollChanged方法代码如下:
package com.bartest.view; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; /** * Created by tujingwu on 2017/6/16 * . */ public class MyScrollView extends ScrollView { //对外暴露的一个ScrollView监听的接口 public MyScrollViewListener myScrollViewListener = null; public MyScrollView(Context context) { super(context); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public void setOnMyScrollListener(MyScrollViewListener myScrollViewListener) { this.myScrollViewListener = myScrollViewListener; } //重写onScrollChanged的ScrollView监听 @Override protected void onScrollChanged(int x, int y, int oldx, int oldy) { super.onScrollChanged(x, y, oldx, oldy); /** * x: 当前横向滑动距离 * y: 当前纵向滑动距离 *oldx: 之前横向滑动距离 *oldy: 之前纵向滑动距离 */ if (myScrollViewListener != null) { //这里判断向上或向下滑动是因为后面要使用到 if (oldy < y)//向上滑动 myScrollViewListener.onMyScrollView(y, oldy, true); else if (oldy > y)//向下滑动 myScrollViewListener.onMyScrollView(y, oldy, false); } } public interface MyScrollViewListener { void onMyScrollView(int y, int oldy, boolean isUp); } }
activity_main布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.bartest.MainActivity"> <com.bartest.view.MyScrollView android:id="@+id/myScrollView" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/head_img" android:layout_width="match_parent" android:layout_height="@dimen/headHight" android:layout_gravity="center" android:scaleType="centerCrop" android:src="@drawable/head" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:lineSpacingExtra="10dp" android:text="@string/text" android:textSize="20sp" /> </LinearLayout> </com.bartest.view.MyScrollView> <include layout="@layout/top_layout" /> </RelativeLayout>
top_layout布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/titleLayout" android:layout_width="match_parent" android:layout_height="@dimen/titleHight" android:gravity="center" android:padding="10dp"> <ImageView android:id="@+id/top_img2" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginRight="10dp" android:layout_toLeftOf="@+id/top_img3" android:src="@mipmap/img2"/> <ImageView android:id="@+id/top_img3" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentRight="true" android:layout_centerInParent="true" android:layout_marginRight="10dp" android:src="@mipmap/img3" /> <ImageView android:id="@+id/top_img1" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignTop="@+id/top_img2" android:src="@mipmap/img1"/> </RelativeLayout>
MainActivity代码
package com.bartest; import android.graphics.Color; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.ImageView; import android.widget.RelativeLayout; import com.bartest.utils.DensityUtil; import com.bartest.view.MyScrollView; public class MainActivity extends AppCompatActivity { private ImageView mHeadImg; private MyScrollView mMyScrollView; private RelativeLayout titleLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initScrollView(); } private void initView() { mHeadImg = (ImageView) findViewById(R.id.head_img); mMyScrollView = (MyScrollView) findViewById(R.id.myScrollView); titleLayout = (RelativeLayout) this.findViewById(R.id.titleLayout); } private void initScrollView() { //获取标题和头部的高度 final float title_height = getResources().getDimension(R.dimen.titleHight); final float head_height = getResources().getDimension(R.dimen.headHight); //总高度(把dp转换成px,计算时单位肯定要一样) final float totalHight = DensityUtil.px2dip(MainActivity.this, head_height - title_height); //设置ScrollView监听 mMyScrollView.setOnMyScrollListener(new MyScrollView.MyScrollViewListener() { @Override public void onMyScrollView(int y, int oldy, boolean isUp) { int yIf = DensityUtil.px2dip(MainActivity.this, Math.abs(y)); if (yIf <= totalHight) { //根据滑动设置渐变透明度 setBgAlphaChange(yIf, totalHight); } else if (yIf > totalHight && isUp) {//防止快速滑动导致透明度问题 向上 //快速滑动就直接设置不透明 setBgAlphaChange((int) totalHight, totalHight); } } }); } //设置背景透明度 private void setBgAlphaChange(int oldy, float totalHight) { /** * 渐变取值范围0--255 * 高度(向上或向下移动的高度) * 渐变百分比: percent =-------------------------------------------- * 总高度(也就是head图片高度-标题栏高度) */ float percent = (float) Math.abs(oldy) / Math.abs(totalHight); int alpha = (int) (percent * 255); titleLayout.setBackgroundColor(Color.argb(alpha, 255, 255, 255)); int imgAlpha = 255 - alpha; mHeadImg.setAlpha(imgAlpha); } }
过程中遇到的问题:1、快速滑动透明度渐变问题(已经决解,如上);2、使用getBackground().setAlpha(alpha)方法设置布局背景没效果,不起作用(换成setBackgroundColor就可以决解)。
另外这里对icon没有做操作,想要icon也渐变,可以给icon背景设置透明度值就可以了,这是scrollview,就算是listview、gridview、recycleview都一样的道理,只要拿到垂直移动的Y值,都可以实现需要的效果