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值,都可以實現需要的效果