Android CoordinatorLayout+AppBarLayout顶部栏吸顶效果的实现

1.控件简介。

CoordinatorLayout遵循Material 风格,包含在 support Library中,结合AppbarLayout, CollapsingToolbarLayout等 可 产生各种炫酷的折叠悬浮效果。

    作为最上层的View
    作为一个容器与一个或者多个子View进行交互

    CoordinatorLayout is intended for two primary use cases: As a top-level application decor or chrome layout; As a container for a specific interaction with one or more child views.

常见结合体-AppBarLayout:

它是继承与LinearLayout的,默认的方向是Vertical:

appbarLayout的滑动flag:

我们可以通过两种方法设置这个Flag:

    方法一:setScrollFlags(int)
    方法二:app:layout_scrollFlags="scroll|enterAlways"

AppBarLayout必须作为CoordinatorLayout的直接子View,否则它的大部分功能将不会生效,如layout_scrollFlags等。
 

2.效果图。

画面収録 2023-05-26 20.10.41

3.所用到的依赖。

//控件用到的依赖
api "androidx.appcompat:appcompat:1.4.0"

//沉浸式状态栏框架导入
// 基础依赖包,必须要依赖
api "com.geyifeng.immersionbar:immersionbar:3.2.2"
// kotlin扩展(可选)
api "com.geyifeng.immersionbar:immersionbar-ktx:3.2.2"

//刷新和加载Layout导入,核心必须依赖
api "com.scwang.smart:refresh-layout-kernel:2.0.1"
api "com.scwang.smart:refresh-header-classics:2.0.1"    //经典刷新头
api "com.scwang.smart:refresh-header-material:2.0.1"    //谷歌刷新头

api 'com.github.hackware1993:MagicIndicator:1.7.0'

4.布局代码。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".mounting.MountingActivity">

    <data>

        <import type="android.view.View" />

    </data>


    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.scwang.smart.refresh.layout.SmartRefreshLayout
            android:id="@+id/refresh_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <com.scwang.smart.refresh.header.MaterialHeader
                android:id="@+id/refresh_header"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="?attr/actionBarSize" />

            <androidx.coordinatorlayout.widget.CoordinatorLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipToPadding="true">

                <com.google.android.material.appbar.AppBarLayout
                    android:id="@+id/app_bar_layout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <com.google.android.material.appbar.CollapsingToolbarLayout
                        android:id="@+id/collapsing_toolbar_layout"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:layout_scrollFlags="scroll|exitUntilCollapsed">

                        <ImageView
                            android:id="@+id/imv_banner"
                            android:layout_width="match_parent"
                            android:layout_height="@dimen/dp_270"
                            android:scaleType="centerCrop"
                            android:src="@mipmap/picture_manami_enosawa2"
                            tools:ignore="ContentDescription" />

                        <androidx.appcompat.widget.Toolbar
                            android:layout_width="match_parent"
                            android:layout_height="@dimen/dp_73"
                            app:contentInsetStart="0dp"
                            app:layout_collapseMode="pin" />

                    </com.google.android.material.appbar.CollapsingToolbarLayout>

                    <FrameLayout
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dp_50"
                        android:orientation="vertical"
                        tools:ignore="UselessLeaf">

                        <net.lucode.hackware.magicindicator.MagicIndicator
                            android:id="@+id/magic_indicator"
                            android:layout_width="wrap_content"
                            android:layout_height="@dimen/dp_40"
                            android:layout_gravity="center" />

                    </FrameLayout>

                </com.google.android.material.appbar.AppBarLayout>

                <androidx.viewpager.widget.ViewPager
                    android:id="@+id/view_pager"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

            </androidx.coordinatorlayout.widget.CoordinatorLayout>

        </com.scwang.smart.refresh.layout.SmartRefreshLayout>


        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_73"
            android:background="@color/color_transparent"
            app:contentInsetStart="0dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <View
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_25" />

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_48"
                    tools:ignore="UselessLeaf">

                    <FrameLayout
                        android:id="@+id/layout_back"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent">

                        <ImageView
                            android:id="@+id/imv_back"
                            android:layout_width="@dimen/dp_9"
                            android:layout_height="@dimen/dp_16"
                            android:layout_gravity="center_vertical"
                            android:layout_marginStart="@dimen/dp_12"
                            android:layout_marginEnd="@dimen/dp_12"
                            android:src="@mipmap/icon_arrowhead_left"
                            android:visibility="visible"
                            tools:ignore="ContentDescription" />

                    </FrameLayout>

                    <TextView
                        android:id="@+id/tev_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="@string/mounting"
                        android:textColor="@color/color_808080"
                        android:textSize="@dimen/sp_18" />

                </FrameLayout>

            </LinearLayout>

        </androidx.appcompat.widget.Toolbar>

    </FrameLayout>

</layout>

注意一点:那个可滑动的 View 不能是 ListView,ScrollView 这种旧包下的控件,否则也是不起作用的。

app:layout_scrollFlags="scroll|enterAlways,前面已经说到app:layout_scrollFlags=scroll的时候,这个View会跟着滚动事件响应,app:layout_scrollFlags=“enterAlways”的时候这个View会响应下拉事件。所以呈现出来的结果应该是我们在上拉的时候toolBar会隐藏,下拉的时候toolBar会出来;如果当我们的toolBar等于app:layout_scrollFlags="scroll|snap"的时候 ,app:layout_scrollFlags=scroll的时候,这个View会跟着滚动事件响应,app:layout_scrollFlags=“snap”的时候在Scroll滑动事件结束以前 ,如果这个View部分可见,那么这个View会停在最接近当前View的位置。具体就自己研究了。

再说我这个需求的效果:标题栏常驻,有两个Toolbar,第一个Toolbar实际上是一个占位View,第二个Toolbar才是真正的常驻标题栏,上滑的时候沉浸式标题栏渐变,上滑到二级标题与标题栏吸顶,app:layout_scrollFlags="scroll|exitUntilCollapsed",上拉的时候,这个View会跟着滑动直到折叠成第一个Toolbar大小,下方的ViewPager设置app:layout_behavior="@string/appbar_scrolling_view_behavior"属性才可以与Toolbar进行吸顶,这样就与第二个Toolbar正常吸顶了。

5.BaseActivtiy的代码。

package com.phone.library_common.base

import android.app.ActivityManager
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.os.Looper
import android.os.Process
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import com.gyf.immersionbar.ImmersionBar
import com.phone.library_common.BaseApplication
import com.phone.library_common.R
import com.phone.library_common.manager.ActivityPageManager
import com.phone.library_common.manager.CrashHandlerManager
import com.phone.library_common.manager.LogManager
import com.phone.library_common.manager.ResourcesManager
import com.phone.library_common.manager.ToolbarManager
import com.phone.library_common.manager.ToolbarManager.Companion.assistActivity
import com.qmuiteam.qmui.widget.QMUILoadingView
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity

abstract class BaseBindingRxAppActivity<DB : ViewDataBinding> : RxAppCompatActivity(), IBaseView {

    private val TAG = BaseBindingRxAppActivity::class.java.simpleName
    protected lateinit var loadView: QMUILoadingView
    protected lateinit var layoutParams: FrameLayout.LayoutParams

    //该类绑定的ViewDataBinding
    protected lateinit var mDatabind: DB
    protected lateinit var mRxAppCompatActivity: RxAppCompatActivity
    protected lateinit var mBaseApplication: BaseApplication
    private var mActivityPageManager: ActivityPageManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mRxAppCompatActivity = this
        mBaseApplication = application as BaseApplication
        mActivityPageManager = ActivityPageManager.get()
        mActivityPageManager?.addActivity(this)

        mDatabind = DataBindingUtil.setContentView(this, initLayoutId())
        mDatabind.lifecycleOwner = mRxAppCompatActivity
        initData()
        initViews()
        loadView = QMUILoadingView(this)
        loadView.also {
            it.visibility = View.GONE
            it.setSize(100)
            it.setColor(ResourcesManager.getColor(R.color.color_333333))
        }
        layoutParams = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
        )
        layoutParams.gravity = Gravity.CENTER
        addContentView(loadView, layoutParams)
        initLoadData()
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        //非默认值
        if (newConfig.fontScale != 1f) {
            resources
        }
        super.onConfigurationChanged(newConfig)
    }

    override fun getResources(): Resources? { //还原字体大小
        val res = super.getResources()
        //非默认值
        if (res.configuration.fontScale != 1f) {
            val newConfig = Configuration()
            newConfig.setToDefaults() //设置默认
            res.updateConfiguration(newConfig, res.displayMetrics)
        }
        return res
    }

    protected abstract fun initLayoutId(): Int

    protected open fun setToolbar(isDarkFont: Boolean) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FFFFFFFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FF198CFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        }
        ToolbarManager.assistActivity(findViewById(android.R.id.content))
    }

    protected open fun setToolbar(isDarkFont: Boolean, isResizeChildOfContent: Boolean) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FFFFFFFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(R.color.color_FF198CFF) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        }
        if (isResizeChildOfContent) {
            ToolbarManager.assistActivity(findViewById(android.R.id.content))
        }
    }

    protected open fun setToolbar(isDarkFont: Boolean, color: Int) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        }
        ToolbarManager.assistActivity(findViewById(android.R.id.content))
    }

    protected open fun setToolbar(
        isDarkFont: Boolean,
        color: Int,
        isResizeChildOfContent: Boolean
    ) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(color) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .init()
        }
        if (isResizeChildOfContent) {
            ToolbarManager.assistActivity(findViewById(android.R.id.content))
        }
    }

    protected open fun setToolbar2(isDarkFont: Boolean, statusBarColor: Int) {
        if (isDarkFont) {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this)
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        }
    }

    /**
     * 顶部栏吸顶专用
     */
    protected open fun setToolbar2(
        isDarkFont: Boolean,
        statusBarColor: Int,
        isResizeChildOfContent: Boolean
    ) {
        if (isDarkFont) {
            val window = window
            window.clearFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            )
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
            //        window.setNavigationBarColor(Color.TRANSPARENT);
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
        } else {
            ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .statusBarDarkFont(isDarkFont)
                .statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
                //                    .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
                .keyboardEnable(true)
                .init()
            val window = window
            window.clearFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                        or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            )
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
            //        window.setNavigationBarColor(Color.TRANSPARENT);
        }
        if (isResizeChildOfContent) {
            assistActivity(findViewById(android.R.id.content))
        }
    }

    protected abstract fun initData()

    protected abstract fun initViews()

    protected abstract fun initLoadData()

    protected open fun showToast(message: String?, isLongToast: Boolean) {
        //        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
        if (!mRxAppCompatActivity.isFinishing) {
            val toast: Toast
            val duration: Int
            duration = if (isLongToast) {
                Toast.LENGTH_LONG
            } else {
                Toast.LENGTH_SHORT
            }
            toast = Toast.makeText(mRxAppCompatActivity, message, duration)
            toast.setGravity(Gravity.CENTER, 0, 0)
            toast.show()
        }
    }

    protected open fun showCustomToast(
        left: Int, right: Int,
        textSize: Int, textColor: Int,
        bgColor: Int, height: Int,
        roundRadius: Int, message: String?,
        isLongToast: Boolean
    ) {
        val frameLayout = FrameLayout(this)
        val layoutParams = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
        )
        frameLayout.layoutParams = layoutParams
        val textView = TextView(this)
        val layoutParams1 = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height)
        textView.layoutParams = layoutParams1
        textView.setPadding(left, 0, right, 0)
        textView.textSize = textSize.toFloat()
        textView.setTextColor(textColor)
        textView.gravity = Gravity.CENTER
        textView.includeFontPadding = false
        val gradientDrawable = GradientDrawable() //创建drawable
        gradientDrawable.setColor(bgColor)
        gradientDrawable.cornerRadius = roundRadius.toFloat()
        textView.background = gradientDrawable
        textView.text = message
        frameLayout.addView(textView)
        val toast = Toast(this)
        toast.setView(frameLayout)
        if (isLongToast) {
            toast.duration = Toast.LENGTH_LONG
        } else {
            toast.duration = Toast.LENGTH_SHORT
        }
        toast.show()
    }

    open fun isOnMainThread(): Boolean {
        return Looper.getMainLooper().thread.id == Thread.currentThread().id
    }

    protected open fun startActivity(cls: Class<*>?) {
        val intent = Intent(this, cls)
        startActivity(intent)
    }

    protected open fun startActivityForResult(cls: Class<*>?, requestCode: Int) {
        val intent = Intent(this, cls)
        startActivityForResult(intent, requestCode)
    }

    open fun getActivityPageManager(): ActivityPageManager? {
        return mActivityPageManager
    }

    private fun killAppProcess() {
        LogManager.i(TAG, "killAppProcess")
        val manager =
            mBaseApplication.getSystemService(ACTIVITY_SERVICE) as ActivityManager
        val processInfos = manager.runningAppProcesses
        // 先杀掉相关进程,最后再杀掉主进程
        for (runningAppProcessInfo in processInfos) {
            if (runningAppProcessInfo.pid != Process.myPid()) {
                Process.killProcess(runningAppProcessInfo.pid)
            }
        }
        LogManager.i(TAG, "执行killAppProcess,應用開始自殺")
        val crashHandlerManager = CrashHandlerManager.get()
        crashHandlerManager?.saveTrimMemoryInfoToFile("执行killAppProcess,應用開始自殺")
        try {
            Thread.sleep(1000)
        } catch (e: InterruptedException) {
            LogManager.i(TAG, "error")
        }
        Process.killProcess(Process.myPid())
        // 正常退出程序,也就是结束当前正在运行的 java 虚拟机
        System.exit(0)
    }

    override fun onDestroy() {
        if (mActivityPageManager?.mIsLastAliveActivity?.get() == true) {
            killAppProcess()
        }
        mActivityPageManager?.removeActivity(mRxAppCompatActivity)
        super.onDestroy()
    }

}

6.Activtiy的代码。

package com.phone.module_main.mounting;

import android.graphics.Color;

import androidx.fragment.app.Fragment;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.phone.library_common.adapter.TabFragmentStatePagerAdapter;
import com.phone.library_common.base.BaseBindingRxAppActivity;
import com.phone.library_common.manager.LogManager;
import com.phone.library_common.manager.ResourcesManager;
import com.phone.library_common.manager.ScreenManager;
import com.phone.module_main.R;
import com.phone.module_main.databinding.ActivityMountingBinding;
import com.phone.module_main.mounting.adapter.MineCommonNavigatorAdapter;
import com.phone.module_main.mounting.fragment.CommodityFragment;

import net.lucode.hackware.magicindicator.ViewPagerHelper;
import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator;

import java.util.ArrayList;
import java.util.List;

@Route(path = "/module_main/mounting")
public class MountingActivity extends BaseBindingRxAppActivity<ActivityMountingBinding> {

    private static final String TAG = MountingActivity.class.getSimpleName();
    private int imvBannerHeight;
    private int slideMaxHeight;

    @Override
    protected int initLayoutId() {
        return R.layout.activity_mounting;
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void initViews() {
        setToolbar2(false, R.color.color_transparent, false);
        setMounting();

        mDatabind.imvBack.setColorFilter(ResourcesManager.getColor(R.color.color_FFFFFFFF));
        mDatabind.layoutBack.setOnClickListener(v -> {
            finish();
        });
        mDatabind.refreshLayout.setOnRefreshListener(refreshLayout -> {
            setData();
            mDatabind.refreshLayout.finishRefresh(1000);
        });
        setData();
    }

    private void setMounting() {
        mDatabind.imvBanner.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
            if (mDatabind.imvBanner.getHeight() > 0) {
                imvBannerHeight = mDatabind.imvBanner.getHeight();
                slideMaxHeight = imvBannerHeight
                        - ScreenManager.getDimenPx(R.dimen.dp_73)
                        - ScreenManager.getDimenPx(R.dimen.dp_1);
            }
        });
        mDatabind.appBarLayout.addOnOffsetChangedListener((appBarLayout1, verticalOffset) -> {
            if (verticalOffset < 0) {
                setToolbar2(true, R.color.color_transparent, false);
                double slideHeight = Math.abs(verticalOffset);
                if (slideHeight < slideMaxHeight) {
                    int proportion = (int) ((slideHeight / slideMaxHeight) * 255);
                    LogManager.i(TAG, "proportion******" + proportion);
                    int color = Color.argb(proportion, 255, 255, 255);
                    mDatabind.toolbar.setBackgroundColor(color);
                } else {
                    mDatabind.toolbar.setBackgroundColor(ResourcesManager.getColor(R.color.color_FFFFFFFF));
                }
                mDatabind.tevTitle.setTextColor(ResourcesManager.getColor(R.color.color_99000000));
                mDatabind.imvBack.setColorFilter(ResourcesManager.getColor(R.color.color_99000000));
            } else {
                setToolbar2(false, R.color.color_transparent, false);
                mDatabind.toolbar.setBackgroundColor(ResourcesManager.getColor(R.color.color_transparent));
                mDatabind.tevTitle.setTextColor(ResourcesManager.getColor(R.color.color_FFFFFFFF));
                mDatabind.imvBack.setColorFilter(ResourcesManager.getColor(R.color.color_FFFFFFFF));
            }
        });
    }

    private void setData() {
        List<String> titleList = new ArrayList<>();
        titleList.add("苹果手机");
        titleList.add("口红");
        titleList.add("包包");
        //创建indicator适配器
        MineCommonNavigatorAdapter mineCommonNavigatorAdapter = new MineCommonNavigatorAdapter(titleList);
        CommonNavigator commonNavigator = new CommonNavigator(this);
        commonNavigator.setAdjustMode(true);//自我调节位置,实现自我平分
        commonNavigator.setAdapter(mineCommonNavigatorAdapter);
        mineCommonNavigatorAdapter.setOnIndicatorTapClickListener(position -> {
            mDatabind.viewPager.setCurrentItem(position);
        });
        mDatabind.magicIndicator.setNavigator(commonNavigator);
        List<Fragment> fragmentList = new ArrayList<>();
        for (int i = 0; i < titleList.size(); i++) {
            fragmentList.add(CommodityFragment.get(titleList.get(i)));
        }
        TabFragmentStatePagerAdapter tabFragmentStatePagerAdapter =
                new TabFragmentStatePagerAdapter(getSupportFragmentManager(), fragmentList);
        mDatabind.viewPager.setAdapter(tabFragmentStatePagerAdapter);
        ViewPagerHelper.bind(mDatabind.magicIndicator, mDatabind.viewPager);
    }

    @Override
    protected void initLoadData() {

    }

    @Override
    public void showLoading() {

    }

    @Override
    public void hideLoading() {

    }


}

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2 和Retrofit2 项目,使用Kotlin+RxJava2+Retrofit2+MVP架构+组件化/Kotlin+Retrofit2+协程+MVVM架构+组件化,添加自动管理token 功能,添加RxJava2 生命周期管理,集成极光推送、阿里云Oss对象存储和高德地图定位功能。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2

实现RecyclerView悬浮吸顶效果,可以使用以下步骤: 1. 创建一个布局文件,包含两个部分:一个用于悬浮显示的视图,一个用于RecyclerView。 2. 在Activity或Fragment中,找到RecyclerView并设置布局管理器和适配器。 3. 创建一个自定义的RecyclerView.ItemDecoration类,用于绘制悬浮视图。 4. 在自定义的ItemDecoration类中,重写getItemOffsets()方法,在该方法中计算悬浮视图的高度,并将其应用到RecyclerView的第一个可见项之上。 5. 在自定义的ItemDecoration类中,重写onDraw()方法,在该方法中绘制悬浮视图。 6. 在Activity或Fragment中,为RecyclerView添加ItemDecoration。 下面是一个简单的示例代码: 1. 创建布局文件(例如:activity_main.xml): ```xml <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"> <TextView android:id="@+id/floating_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Floating View" android:background="#FF0000" android:textColor="#FFFFFF" android:padding="16dp" android:visibility="gone" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/floating_view" /> </RelativeLayout> ``` 2. 在Activity或Fragment中,设置RecyclerView的布局管理器和适配器: ```java // 找到RecyclerView RecyclerView recyclerView = findViewById(R.id.recyclerview); // 设置布局管理器 recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 设置适配器 recyclerView.setAdapter(adapter); ``` 3. 创建一个自定义的ItemDecoration类(例如:FloatingHeaderDecoration.java): ```java public class FloatingHeaderDecoration extends RecyclerView.ItemDecoration { private View mFloatingView; public FloatingHeaderDecoration(View floatingView) { mFloatingView = floatingView; } @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (parent.getChildAdapterPosition(view) == 0) { outRect.top = mFloatingView.getHeight(); } } @Override public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDraw(canvas, parent, state); int top = parent.getPaddingTop(); int bottom = top + mFloatingView.getHeight(); int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); mFloatingView.setVisibility(View.VISIBLE); mFloatingView.layout(left, top, right, bottom); mFloatingView.draw(canvas); } } ``` 4. 在Activity或Fragment中,为RecyclerView添加ItemDecoration: ```java // 找到悬浮视图 View floatingView = findViewById(R.id.floating_view); // 创建自定义的ItemDecoration并添加到RecyclerView recyclerView.addItemDecoration(new FloatingHeaderDecoration(floatingView)); ``` 这样就实现了RecyclerView的悬浮吸顶效果。悬浮视图会在滚动时始终保持在顶部,并且不会被其他项覆盖。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值