Android 滑动ScrollView 动态改变标题栏透明度及颜色

废话不多说,上图

项目需求是默认显示白色返回按钮,及白色文字栏为透明.滑动到第一屏看不到的时候将白色背景以渐变的形式显示.并且将文字及返回图标变为深色.

首先获取要开始进行渐变位置的高及滑动到某处标题完全显示的高并设置ScrollView滑动监听,(使用kotlin,java自行转换)

  titlHeight = DisplayUtil.dip2px(this, 60f)
  windowHeight = DisplayUtil.getDensityHeight(this) - titlHeight
  scrollHeight = DisplayUtil.getDensityHeight(this) - (titlHeight * 2)

因为我的需求是先显示一整屏,然后显示到两倍标题栏高度的时候开始渐变,到标题栏高度的时候完全显示.

 sv.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
            when {
                scrollHeight > scrollY -> {
                    //滑动小于开始渐变的位置  标题栏为透明  图标及文字为白色
                    setTitleViewAlpha(0f)
                }
                scrollY in scrollHeight..windowHeight -> {
                    //alpha 为控件的透明程度  0完全透明  1 不透明
                    var alpha = (scrollY - scrollHeight) * 1.0 / titlHeight
                    setTitleViewAlpha(alpha.toFloat())
                }
                else -> {
                     //滑动大于完全显示的位置  标题栏为白色  图标及文字为深色
                    setTitleViewAlpha(1f)
                }
            }
        })
private fun setTitleViewAlpha(alpha: Float) {
        when (alpha) {
            0f -> { //为0时 则白色文字及图标显示  父布局background为透明
                //设置控件的background的alpha 取值为0~255
                //设置控件的alpha 取值为0~1 
                ll_title.background.alpha = 0 
                ivLeft_white.alpha = 1f
                ivLeft.alpha = 0f
                tvTitleWhite.alpha = 1f
                tvTitle.alpha = 0f
                tvTitle.visibility = View.INVISIBLE
                tvTitleWhite.visibility = View.VISIBLE
                ivLeft.visibility = View.INVISIBLE
                ivLeft_white.visibility = View.VISIBLE
            }
            1f -> { //为1时 则深色文字及图标显示  父布局background为白色
                ll_title.background.alpha = 255
                ivLeft_white.alpha = 0f
                ivLeft.alpha = 1f
                tvTitleWhite.alpha = 0f
                tvTitle.alpha = 1f
                tvTitle.visibility = View.VISIBLE
                tvTitleWhite.visibility = View.GONE
                ivLeft.visibility = View.VISIBLE
                ivLeft_white.visibility = View.GONE
            }
            else -> { //其余则设置alpha即可   
                ll_title.background.alpha = (alpha * 255).toInt()
                ivLeft_white.alpha = 1f - alpha
                ivLeft.alpha = alpha
                tvTitleWhite.alpha = 1f - alpha
                tvTitle.alpha = alpha
                tvTitle.visibility = View.VISIBLE
                tvTitleWhite.visibility = View.VISIBLE
                ivLeft.visibility = View.VISIBLE
                ivLeft_white.visibility = View.VISIBLE
            }
        }
    }

布局中两个返回按钮 两个文本  一个白色一个深色,通过alpha来控制

补上工具类DisplayUtil

public class DisplayUtil {
	public static float getDensity(Context context) {
		Resources resources = context.getResources();
		DisplayMetrics dm = resources.getDisplayMetrics();
		return dm.density;
	}

	public static int getDensityWdith(Context context) {
		Resources resources = context.getResources();
		DisplayMetrics dm = resources.getDisplayMetrics();
		return dm.widthPixels;
	}

	public static int getDensityHeight(Context context) {
		Resources resources = context.getResources();
		DisplayMetrics dm = resources.getDisplayMetrics();
		return dm.heightPixels;
	}

	// 1.代码中设置setXXSize的都是px单位,都需要把布局中的dp,sp转成px才能使用
	/**
	 * 根据手机分辨率从 px(像素) 单位 转成 dp
	 */
	public static int px2dip(Context context, float pxValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (pxValue / scale + 0.5f);
	}

	/**
	 * 根据手机分辨率从 dp 单位 转成 px(像素)
	 */
	public static int dip2px(Context context, float dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue * scale + 0.5f);
	}

	/**
	 * 将px值转换为sp值,保证文字大小不变
	 * 
	 * @param pxValue
	 * @param
	 *            (DisplayMetrics类中属性scaledDensity)
	 * @return
	 */
	public static int px2sp(Context context, float pxValue) {
		final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
		return (int) (pxValue / fontScale + 0.5f);
	}

	/**
	 * 将sp值转换为px值,保证文字大小不变
	 * 
	 * @param spValue
	 * @param
	 *            (DisplayMetrics类中属性scaledDensity)
	 * @return
	 */
	public static int sp2px(Context context, float spValue) {
		final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
		return (int) (spValue * fontScale + 0.5f);
	}
}

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现这个效果可以采用两种方案: 1. 使用 CoordinatorLayout 实现 CoordinatorLayout 是一个非常强大的布局容器,它可以协调多个子 View 的交互行为。在这个场景下,我们可以将标题栏作为 CoordinatorLayout 的直接子 View,将 ScrollView 作为标题栏的兄弟 View,然后使用 app:layout_behavior 属性指定标题栏的行为为 AppBarLayout.ScrollingViewBehavior,这样当 ScrollView 滑动时,标题栏就会自动滑动。 示例代码如下: ```xml <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="My Title" /> </com.google.android.material.appbar.AppBarLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!-- Your content here --> </ScrollView> </androidx.coordinatorlayout.widget.CoordinatorLayout> ``` 需要注意的是,这种方案需要使用 AndroidX 库中的 CoordinatorLayout 和 Material Design 组件库中的 AppBarLayout 和 MaterialToolbar。 2. 使用自定义 Behavior 实现 如果你不想使用 CoordinatorLayout,或者你需要实现一些比较特殊的效果,那么可以考虑使用自定义 Behavior 实现。具体来说,我们可以定义一个 Behavior,继承自 AppBarLayout.ScrollingViewBehavior,并重写 onNestedPreScroll 方法,在 ScrollView 滑动之前处理标题栏滑动。 示例代码如下: ```java public class MyBehavior extends AppBarLayout.ScrollingViewBehavior { public MyBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { // 计算标题栏需要滑动的距离 int distance = Math.min(child.getHeight(), dy); // 滑动标题栏 child.setTranslationY(-distance); // 更新 consumed 数组,表示已经消耗了滑动距离 consumed[1] = distance; return true; } } ``` 然后在布局文件中将标题栏的 Behavior 设置为我们定义的 MyBehavior: ```xml <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_behavior=".MyBehavior"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="My Title" /> </com.google.android.material.appbar.AppBarLayout> ``` 需要注意的是,这种方案需要手动处理标题栏滑动,因此需要在 onNestedPreScroll 方法中计算标题栏需要滑动的距离,并使用 setTranslationY 方法滑动标题栏。同时,需要更新 consumed 数组,表示已经消耗了滑动距离,这样才能确保滑动事件正确地传递给 ScrollView

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值