ListView滑动使得标题栏背景渐变(透明-不透明)

先上效果图:
图1:
这里写图片描述

图2:
这里写图片描述

图3:
这里写图片描述

图4:
这里写图片描述

我用的是小米Note手机,状态栏高度是55px,后面会提到,这里先做个说明:
这里写图片描述

下面的内容包含了所有代码和一些测试数据:

代码:
代码很简单,也做了注释,这里就不废话了。
先来布局文件:

activity的布局
activity_main_10

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/listvew"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <!--标题栏,这里简单写个textview-->
    <TextView
        android:id="@+id/title_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="5dp"
        android:textSize="30sp"/>

</RelativeLayout>

listView头布局
head_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <ImageView
        android:id="@+id/head_iv"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@mipmap/ch"/>


</LinearLayout>

listView的item布局
listview_item_layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp">

    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="15sp">

    </TextView>

</FrameLayout>

功能代码:
MainActivity10


import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;

public class MainActivity10 extends Activity {

    private TextView title_tv;

    private ListView listvew;

    //listView的头
    private View headView;

    //listView头中包含的布局。这里仅仅是一个ImageView
    private ImageView head_iv;

    private ArrayList<String> dataList;

    private MyAdapter myAdapter;

    //listview的头部(这里是ImageView)顶部距离屏幕顶部(包含状态栏)的距离
    //注:这个高度,是头布局在屏幕里才会计算的,出了屏幕,就不会变了
    private int height;

    //listView的头部的真实高度。头布局的整体高度,因为这个demo只简单写了个ImageView作为头部,所以ImageView的高度,就是头部的高度
    private int headViewHeight;

    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_10);

        context = this;

        title_tv = (TextView) findViewById(R.id.title_tv);

        listvew = (ListView) findViewById(R.id.listvew);

        headView = LayoutInflater.from(this).inflate(R.layout.head_layout, null);

        head_iv = (ImageView) headView.findViewById(R.id.head_iv);

        //添加listView的头布局
        listvew.addHeaderView(headView);

        dataList = new ArrayList<>();

        for (int i = 0; i < 50; i++) {
            dataList.add("==" + i + "==");
        }

        myAdapter = new MyAdapter();

        listvew.setAdapter(myAdapter);

        listvew.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

                int location[] = new int[2];

                /**
                 * public void getLocationInWindow(@Size(2) int[] location)
                 *
                 * <p>Computes 计算 the coordinates 坐标 of this view in its window. The argument 参数
                 * must be an array of two integers. After the method returns, the array
                 * contains 包含 the x and y location in that order.</p>
                 *
                 * @param location an array of two integers in which to hold the coordinates
                 */
                head_iv.getLocationInWindow(location);

                //listview的头部(这里是ImageView)顶部距离屏幕顶部(包含状态栏)的距离
                height = location[1];
                headViewHeight = head_iv.getHeight();

                Utils.printLogData("==location==0==" + location[0]);
                Utils.printLogData("==location==1==" + location[1]);
                Utils.printLogData("==height==" + height);
                Utils.printLogData("==headViewHeight==" + headViewHeight);

                //在head_layout.xml中,固定设置了150dp的高度,用于和上面测量的对比
                Utils.printLogData("==setHeigth==" + dip2px(150));

                handleTitleBarColorEvaluate();

            }
        });

    }

    // 处理标题栏颜色渐变
    private void handleTitleBarColorEvaluate() {
        //比例
        float fraction;
        if (height > 0) {

            fraction = 1f - height * 1f / 60;
            if (fraction < 0f) {
                fraction = 0f;
            }
            title_tv.setAlpha(fraction);
            return;
        }

        //高度值是负数,但是负号仅仅是表示方向,取绝对值
        float space = Math.abs(height) * 1f;
        // 标题栏的高度
        fraction = space / headViewHeight;
        if (fraction < 0f)
            fraction = 0f;
        if (fraction > 1f)
            fraction = 1f;
        title_tv.setAlpha(1f);

        if (fraction >= 1f) {
            title_tv.setBackgroundColor(0xffec434b);
        } else {
            //根据比例,生成一个按比例的颜色值
            title_tv.setBackgroundColor(ChenColorUtils.getNewColorByStartEndColor(context, fraction, R.color.transparent, R.color.red));
        }

        if (fraction >= 0.8f) {
            title_tv.setTextColor(ChenColorUtils.getNewColorByStartEndColor(context, fraction, R.color.transparent, R.color.black));
            title_tv.setText("标题栏");
        } else {
            title_tv.setText("");
        }
    }


    private class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return dataList.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = LayoutInflater.from(context).inflate(R.layout.listview_item_layout, null);
                holder = new ViewHolder();

                holder.item_tv = (TextView) convertView.findViewById(R.id.item_tv);

                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.item_tv.setText(dataList.get(position));


            return convertView;
        }

        private class ViewHolder {
            private TextView item_tv;
        }

    }


    /**
     * dip转换px
     */
    public int dip2px(int dip) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dip * scale + 0.5f);
    }


}

颜色:
colors.xml中添加

    <color name="red">#ec434b</color>
    <color name="transparent">#00000000</color>
    <color name="black">#FF000000</color>

工具类代码:
打印日志工具:

import android.util.Log;

public class Utils {

    public static void printLogData(String data) {
        Log.e("chen", data);
    }

}

颜色工具:


import android.content.Context;

public class ChenColorUtils {

    // 成新的颜色值
    public static int getNewColorByStartEndColor(Context context, float fraction, int startValue, int endValue) {
        return evaluate(fraction, context.getResources().getColor(startValue), context.getResources().getColor(endValue));
    }
    /**
     * 成新的颜色值
     * @param fraction 颜色取值的级别 (0.0f ~ 1.0f)
     * @param startValue 开始显示的颜色
     * @param endValue 结束显示的颜色
     * @return 返回生成新的颜色值
     */
    public static int evaluate(float fraction, int startValue, int endValue) {
        int startA = (startValue >> 24) & 0xff;
        int startR = (startValue >> 16) & 0xff;
        int startG = (startValue >> 8) & 0xff;
        int startB = startValue & 0xff;

        int endA = (endValue >> 24) & 0xff;
        int endR = (endValue >> 16) & 0xff;
        int endG = (endValue >> 8) & 0xff;
        int endB = endValue & 0xff;

        return ((startA + (int) (fraction * (endA - startA))) << 24) |
                ((startR + (int) (fraction * (endR - startR))) << 16) |
                ((startG + (int) (fraction * (endG - startG))) << 8) |
                ((startB + (int) (fraction * (endB - startB))));
    }

}

测试数据:

界面刚启动

05-18 16:19:25.386 18718-18718/com.chen E/chen: ==location==0==0
05-18 16:19:25.387 18718-18718/com.chen E/chen: ==location==1==0
05-18 16:19:25.387 18718-18718/com.chen E/chen: ==height==0
05-18 16:19:25.387 18718-18718/com.chen E/chen: ==headViewHeight==0
05-18 16:19:25.387 18718-18718/com.chen E/chen: ==setHeigth==413

从时间上看,启动约150毫秒(0.15秒)后

05-18 16:19:25.531 18718-18718/com.chen E/chen: ==location==0==0
05-18 16:19:25.531 18718-18718/com.chen E/chen: ==location==1==55
05-18 16:19:25.531 18718-18718/com.chen E/chen: ==height==55
05-18 16:19:25.531 18718-18718/com.chen E/chen: ==headViewHeight==413
05-18 16:19:25.531 18718-18718/com.chen E/chen: ==setHeigth==413

小米note,状态栏高度是55像素。所以,一开始的时候,图片距离屏幕顶部的高度就是55


向上滑动,当头布局完全出到屏幕外面后,继续滑动,打印数据不会变。
即:头布局顶部距离屏幕顶部的高度(距离)不变。因为这个高度,只会在view在屏幕中才能获取到。
详见注释

05-18 17:01:02.151 16873-16873/com.chen E/chen: ==height==-412
05-18 17:01:02.167 16873-16873/com.chen E/chen: ==height==-412
05-18 17:01:02.200 16873-16873/com.chen E/chen: ==height==-412
05-18 17:01:02.233 16873-16873/com.chen E/chen: ==height==-412
05-18 17:01:02.316 16873-16873/com.chen E/chen: ==height==-412
05-18 17:01:02.332 16873-16873/com.chen E/chen: ==height==-412
05-18 17:01:02.349 16873-16873/com.chen E/chen: ==height==-412

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值