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

这篇具有很好参考价值的文章主要介绍了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:

android appbarlayout,android

appbarLayout的滑动flag:
android appbarlayout,android

我们可以通过两种方法设置这个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文章来源地址https://www.toymoban.com/news/detail-757891.html

到了这里,关于Android CoordinatorLayout+AppBarLayout顶部栏吸顶效果的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序第六篇:元素吸顶效果实现

     系列文章传送门: 微信小程序第一篇:自定义组件详解 微信小程序第二篇:七种主流通信方法详解 微信小程序第三篇:获取页面节点信息 微信小程序第四篇:生成图片并保存到手机相册 微信小程序第五篇:页面弹出效果及共享元素动画 话不多说,先看效果: 这种效果在

    2024年02月16日
    浏览(43)
  • 微信小程序 顶部搜索 吸顶 不随页面滚动而滚动

    主要用于商城类小程序: 微信小程序 搜索框 顶部吸顶 顶部购物车栏固定 不随页面滚动而滚动 示例: 可以看到分为三部分--头部搜索框--中间商品区域(可滚动)----底部购物车(固定底部) 头部搜索框 最大的盒子宽高100% 头部盒子需要有固定高度 flex布局 flex-flow: column; (为了中间

    2024年02月12日
    浏览(55)
  • 如何使用CSS实现一个平滑滚动到页面顶部的效果(回到顶部按钮)?

    前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一

    2024年02月11日
    浏览(46)
  • 微信小程序 顶部搜索框滑动伸缩效果的实现

    提示:实现搜索框跟随用户滑动页面,实现伸缩效果 微信小程序 顶部搜索框滑动伸缩动画的实现 提示:主要用到了微信小程序的view-scroll bindscroll 1:确定一个控制搜索框伸缩的范围。 2:通过bindscroll事件获取e.detail.scrollTop;即用户滑动的位置 3:计算当前位置占伸缩范围的

    2024年02月12日
    浏览(42)
  • css效果之吸顶效果

    一般我们使用 position:sticky 来进行实现 他相当于 relative 和 fixed 相结合 在页面滚动过程中,含有粘性定位的元素到父元素的距离达到一定要求的时候,他的属性就会由 relative 变为 fixed 请多写几行 你好 br 然后,运行 demo ,我们会发现头部固定了 当前代码的兼容性不太好 不会

    2024年02月07日
    浏览(32)
  • 实现对一个元素的滚动条进行平滑滚动至顶部的动画效果

    1.elementUI中的平滑滚动至顶部的动画效果代码 2.将上面的代码简化 3.继续简化代码 使用 Element.scrollTo 方法并使用 scroll-behavior: smooth 的简化代码示例: 首先,在你的CSS样式表中加入以下代码: 这会将平滑滚动的效果应用到整个页面。 然后,使用 scrollTo 方法在JavaScript中触发滚

    2024年02月11日
    浏览(40)
  • iOS 吸顶效果

    项目中,在列表向上滚动时,有时需要将某个控件置顶,这就是我们常见的吸顶效果。 UITableView 是自带吸顶效果,我们把需要置顶的控件设置为 SectionHeaderView ,这样在滚动时,该控件会自动置顶。 自定义 UKNestedTableView 效果如下 UITableView 的吸顶效果能满足部分的要求,但在

    2023年04月25日
    浏览(27)
  • Android 顶部标签栏及内容列表的设计与实现

    案例演示 1、主页面添加ViewPager控件 activity_main.xml 2、创建适配器继承FragmentPagerAdapter 在适配器类中创建构造方法,传入FragmentManager对象及放入ViewPager的Fragment对象集合 MyAdapter.java 3、为ViewPager对象设置适配器 准备Fragment集合 创建MyAdapter适配器 MainActivity.java 4、设置ViewPager监听

    2023年04月19日
    浏览(44)
  • IOS 类似直播的tableView 顶部透明度渐变效果

    IOS 类似直播的tableView 顶部透明度渐变效果 在工程中,需要类似直播的tableView 顶部透明度渐变效果。这个渐变的效果呢,而且不能有覆盖在背景图上的感觉。底部背景图在没有数据的情况下,没有遮罩效果。首先想到了CAGradientLayer。 CAGradientLayer主要属性 colors var colors: [AnyO

    2024年02月12日
    浏览(43)
  • uni-app小程序中做页面滚动底部或顶部加载效果

    在移动应用开发中,无限滚动加载是一个常见的功能,用户可以通过滑动屏幕来加载更多的内容,从而提高应用的用户体验。本文将介绍如何使用Uniapp实现无限滚动加载的功能。 概述 我们需要实现的无限滚动加载功能的具体效果如下: 当用户滑动到底部时,自动加载更多的

    2024年02月08日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包