Android 进阶 仿得到详情页滑动头部变色


1.依赖


    maven { url "https://jitpack.io" }
    
    //noinspection GradleCompatible
    implementation 'com.android.support:design:26.1.0'
    //RecyclerView 快速适配器
    compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'
    //沉浸式的依赖
    compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'

2.Style NoActionbar


3.使用NestScrollView 解决 RecyclerView 滑动卡动冲突 也是需要监听的关键

public class MyNestedScrollView extends NestedScrollView {
    //重写构造方法  这里让它都去使用第三中构造方法
    public MyNestedScrollView(Context context) {
        this(context, null);
    }

    public MyNestedScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    //每次都只会 调用这个方法
    public MyNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    }

    //覆写滑动监听方法 再做一个自己的接口
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollViewListenner != null) {
            mOnScrollViewListenner.onScrollChanged(this, l, t, oldl, oldt);
        }
    }

    //自定义接口
    public interface OnScrollViewListenner {
        //把方法放进去  做修改加入本类对象参数
        void onScrollChanged(MyNestedScrollView mMyScrollView, int l, int t, int oldl, int oldt);
    }

    //定义自己的接口变量
    private OnScrollViewListenner mOnScrollViewListenner;

    //设置Set方法
    public void setmOnScrollViewListenner(OnScrollViewListenner mOnScrollViewListenner) {
        this.mOnScrollViewListenner = mOnScrollViewListenner;
    }
}

4.MainAc整体布局

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.as.app2.MainActivity">

    <com.as.app2.MyNestedScrollView
        android:id="@+id/myNestScrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/topImageview"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:scaleType="fitXY"
                android:src="@drawable/topbg" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/myRecyclerView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </com.as.app2.MyNestedScrollView>

    <RelativeLayout
        android:id="@+id/relatv_change"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone">

        <!--这个View就是用来覆盖状态栏-->

        <View
            android:id="@+id/view_white"
            android:layout_width="match_parent"
            android:layout_height="25dp"
            android:background="#fff"
            android:visibility="gone" />

        <ImageView
            android:id="@+id/imageback"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginTop="25dp"
            android:padding="8dp"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:id="@+id/tvColorChange"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="25dp"
            android:gravity="center"
            android:text="XXX"
            android:textSize="16sp" />

        <!--底部一条线-->
        <View
            android:id="@+id/viewtiao"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="75dp"
            android:background="@color/colorGray" />
    </RelativeLayout>

</RelativeLayout>

5.设置状态栏的字体图案颜色  黑/白俩种模式


public class StatusBarUtil {
    /**
     * 修改状态栏为全透明 * @param activity
     */
    @TargetApi(19)
    public static void transparencyBar(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * 修改状态栏颜色,支持4.4以上版本 * @param activity * @param colorId
     */
    public static void setStatusBarColor(Activity activity, int colorId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(activity.getResources().getColor(colorId));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //使用SystemBarTint库使4.4版本状态栏变色,需要先将状态栏设置为透明
            transparencyBar(activity);
            SystemBarTintManager tintManager = new SystemBarTintManager(activity);
            tintManager.setStatusBarTintEnabled(true);
            tintManager.setStatusBarTintResource(colorId);
        }
    }

    /**
     * 状态栏亮色模式,设置状态栏黑色文字、图标, * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android * @param activity * @return 1:MIUUI 2:Flyme 3:android6.0
     */
    public static int StatusBarLightMode(Activity activity) {
        int result = 0;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (MIUISetStatusBarLightMode(activity, true)) {
                result = 1;
            } else if (FlymeSetStatusBarLightMode(activity.getWindow(), true)) {
                result = 2;
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                result = 3;
            }
        }
        return result;
    }

    /**
     * 已知系统类型时,设置状态栏黑色文字、图标。 * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android * @param activity * @param type 1:MIUUI 2:Flyme 3:android6.0
     */
    public static void StatusBarLightMode(Activity activity, int type) {
        if (type == 1) {
            MIUISetStatusBarLightMode(activity, true);
        } else if (type == 2) {
            FlymeSetStatusBarLightMode(activity.getWindow(), true);
        } else if (type == 3) {
            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        }
    }

    /**
     * 状态栏暗色模式,清除MIUI、flyme或6.0以上版本状态栏黑色文字、图标
     */
    public static void StatusBarDarkMode(Activity activity, int type) {
        if (type == 1) {
            MIUISetStatusBarLightMode(activity, false);
        } else if (type == 2) {
            FlymeSetStatusBarLightMode(activity.getWindow(), false);
        } else if (type == 3) {
            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
        }
    }

    /**
     * 设置状态栏图标为深色和魅族特定的文字风格 * 可以用来判断是否为Flyme用户 * @param window 需要设置的窗口 * @param dark 是否把状态栏文字及图标颜色设置为深色 * @return boolean 成功执行返回true *
     */
    public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {
            }
        }
        return result;
    }

    /**
     * 需要MIUIV6以上 * @param activity * @param dark 是否把状态栏文字及图标颜色设置为深色 * @return boolean 成功执行返回true *
     */
    public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
        boolean result = false;
        Window window = activity.getWindow();
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag); //状态栏透明且黑色字体

                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result = true;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
                    if (dark) {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    } else {
                        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
                    }
                }
            } catch (Exception e) {
            }
        }
        return result;
    }
}

6.自定义LayoutManager也是为了解决滑动卡顿的

public class CustomLinearLayoutManager extends LinearLayoutManager {
    private boolean isScrollEnabled = true;

    public CustomLinearLayoutManager(Context context) {
        super(context);
    }

    public void setScrollEnabled(boolean flag) {
        this.isScrollEnabled = flag;
    }

    public void setScrollHorizentalEnabled(boolean flag1) {
        this.isScrollEnabled = flag1;
    }

    @Override
    public boolean canScrollVertically() {
        //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
        return isScrollEnabled && super.canScrollVertically();
    }

    @Override
    public boolean canScrollHorizontally() {
        return isScrollEnabled && super.canScrollVertically();
    }
}

7.MainAc

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private RecyclerView myRecyclerView;
    private MyNestedScrollView myNestScrollView;
    private View view_white;
    private ImageView imageback;
    private TextView tvColorChange;
    private RelativeLayout relatv_change;
    private ImageView topImageview;
    private int height;// 实时变化的高度
    private View viewtiao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        initView();
        getHeighOfTopView();
        initRecyclerView();

        myNestScrollView.setmOnScrollViewListenner(new MyNestedScrollView.OnScrollViewListenner() {
            @Override
            public void onScrollChanged(MyNestedScrollView mMyScrollView, int l, int t, int oldl, int oldt) {

                //对T轴进行判断,就俩种状态1.消失没有了    2.随着滑动,颜色越来越深
                if (t <= 0) {//没有往下滑
                    StatusBarUtil.StatusBarDarkMode(MainActivity.this, 3);
                    //设置标题隐藏
                    view_white.setVisibility(View.GONE);
                    relatv_change.setVisibility(View.GONE);
                    //设置标题所在背景为透明
                    relatv_change.setBackgroundColor(Color.argb(0, 0, 0, 0));
                    viewtiao.setBackgroundColor(Color.argb(0, 0, 0, 0));
                }
                //大于0表示有位移 正在拖动中,发生颜色变化的同时不超过顶部图片的高度
                else if (t > 0 && t < height) {
                    view_white.setVisibility(View.VISIBLE);
                    StatusBarUtil.StatusBarLightMode(MainActivity.this);
                    //显示标题
                    relatv_change.setVisibility(View.VISIBLE);
                    //获取ScrollView向下滑动,图片消失部分的比例    注意在配置比例时  一定要强转float
                    float scale = (float) t / height;
                    //根据这个比例,让标题的颜色慢慢的由浅入深
                    float alpha = (255 * scale);
                    //设置标题的内容和颜色
                    tvColorChange.setText("我是标题");
                    tvColorChange.setTextColor(Color.argb((int) alpha, 0, 0, 0));
                    //设置标题布局颜色
                    relatv_change.setBackgroundColor(Color.argb((int) alpha, 255, 255, 255));
                    viewtiao.setBackgroundColor(Color.argb((int) alpha, 255, 255, 255));
                } else {
                    relatv_change.setBackgroundColor(getResources().getColor(R.color.white));
                    tvColorChange.setTextColor(getResources().getColor(R.color.black));
                    viewtiao.setBackgroundColor(getResources().getColor(R.color.colorGray));
                }
            }
        });
    }

    private void initRecyclerView() {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 60; i++) {
            list.add("第" + i + "条数据");
        }
        MyAdapter myAdapter = new MyAdapter(R.layout.item, list);
        CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(this);
        linearLayoutManager.setScrollEnabled(false);
        myRecyclerView.setAdapter(myAdapter);
        myRecyclerView.setLayoutManager(linearLayoutManager);
    }

    private void getHeighOfTopView() {
        //获取控件的试图观察者,以便通过试图观察者得到控件的宽高参数
        ViewTreeObserver viewTreeObserver = topImageview.getViewTreeObserver();
        //添加观察者监听
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                //回调监听后首先移除该监听 占资源
                topImageview.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                //得到高度
                height = topImageview.getHeight();
            }
        });

    }

    private void initView() {
        myRecyclerView = (RecyclerView) findViewById(R.id.myRecyclerView);
        myNestScrollView = (MyNestedScrollView) findViewById(R.id.myNestScrollView);
        view_white = (View) findViewById(R.id.view_white);
        imageback = (ImageView) findViewById(R.id.imageback);
        tvColorChange = (TextView) findViewById(R.id.tvColorChange);
        relatv_change = (RelativeLayout) findViewById(R.id.relatv_change);
        topImageview = (ImageView) findViewById(R.id.topImageview);
        imageback.setOnClickListener(this);
        viewtiao = (View) findViewById(R.id.viewtiao);
        viewtiao.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageback:
                Toast.makeText(this, "imageback", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }
}

至于RecyclerView Adapter 随意写了.

猜你喜欢

转载自blog.csdn.net/FlyPig_Vip/article/details/82705256