Android中ScrollView和標題欄漸變

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章