Android Compose实现伸缩ToolBar的思路详解

目录
  • ScrollableAppBar
    • 效果图
    • 主要思路
      • 布局预览
      • 实现过程

ScrollableAppBar

效果图

  • 当列表向上移动时,会先带动ToolBar向上位移,等ToolBar向上移动到最大位移量时列表向上滑动
  • 当列表向下移动时,会先带动ToolBar向下位移,等ToolBar向下移动到最大位移量时列表向下滑动

主要思路

布局预览

伸缩前布局:

伸缩后布局:

实现过程

布局实现

首先我们要定义两个尺寸变量

// 应用栏高度
private val toolBarHeight = 56.dp
// 导航图标大小
private val navigationIconSize = 50.dp

我们采用Box作为根布局,里面主要包含三个部分,背景图片,顶部的TooBar以及下面的Title部分,其实现如下

//整体布局实现
Box(modifier = Modifier
        .height(scrollableAppBarHeight) //scrollableAppBarHeight 为高度参数,为外部获取
        .fillMaxWidth()
) {
    Image(painter = painterResource(id = backgroundImageId), contentDescription = "background", contentScale = ContentScale.FillBounds)

    // 自定义应用栏
    Row(
        modifier = modifier
            .height(toolBarHeight) //设置高度为toolBarHeight
            .fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically //设置垂直方向为居中对齐
    ) {
        // 导航图标
        Box(modifier = Modifier.size(navigationIconSize),contentAlignment = Alignment.Center) {
            navigationIcon()
        }
    }

    // title定义
    Box(
        modifier = Modifier
            .height(toolBarHeight) //和ToolBar同高
            .fillMaxWidth()
            .align(Alignment.BottomStart),
        contentAlignment = Alignment.CenterStart
    ) {
        Text(text = title,
            color = Color.White,
            modifier = Modifier.padding(start = 20.dp).matchParentSize(), // 使用 matchParentSize 修饰符保证不影响父 Box尺寸
            fontSize = 20.sp
        )
    }
}

我们主要讲解title部分

// title定义
Box(
    modifier = Modifier
        .height(toolBarHeight) //和ToolBar同高
        .fillMaxWidth()
        .align(Alignment.BottomStart),
    contentAlignment = Alignment.CenterStart
) {
    Text(text = title,
            color = Color.White,
            modifier = Modifier.padding(start = 20.dp).matchParentSize(), // 使用 matchParentSize 修饰符保证不影响父 Box尺寸
            fontSize = 20.sp
        )
}

首先为了保证title部分在完全收缩后高度和toolBar部分一致,我们设置Box布局高度为toolBarHeight

modifier = Modifier
        .height(toolBarHeight) //和ToolBar同高
        .fillMaxWidth()

然后定义Box在根布局里面的对齐方式为Alignment.BottomStart

modifier = Modifier
        .height(toolBarHeight) //和ToolBar同高
        .fillMaxWidth()
        .align(Alignment.BottomStart)

之所以这样设置,是因为我们通过观察伸缩前和伸缩后的预览图可以知道如果保证此部分是底部左边对齐,那么在根布局向上移动的过程中我们便可以只关心此部分在水平方向的位移即可

接着设置文本部分的对齐方式,保证title是居中靠左对齐的

contentAlignment = Alignment.CenterStart

位移实现

首先,我们要明确ScrollableAppBar最大向上偏移量等于其定义的高度收缩后的高度,即toolBarHeight的差值,即:

// 应用栏最大向上偏移量
val maxOffsetHeightPx = with(LocalDensity.current) { scrollableAppBarHeight.roundToPx().toFloat() - toolBarHeight.roundToPx().toFloat() }

其次,title部分在水平方向的位移距离其实就是导航图标的宽度,即:

// Title 偏移量参考值
val titleOffsetWidthReferenceValue = with(LocalDensity.current) { navigationIconSize.roundToPx().toFloat() }

同时需要定义从外部获取到的偏移量

val toolbarOffsetHeightPx: MutableState<Float> //向上偏移量

最外层布局位移定义

为根布局添加垂直方向上的位移

@Composable
fun ScrollableAppBar(
    modifier: Modifier = Modifier,
    title: String = stringResource(id = R.string.app_name), //默认为应用名
    navigationIcon: @Composable () -> Unit, //导航图标
    @DrawableRes backgroundImageId: Int, // 背景图片
    scrollableAppBarHeight: Dp, //定义的ScrollableAppBar高度
    toolbarOffsetHeightPx: MutableState<Float> //向上偏移量
) {
    Box(modifier = Modifier
        .height(scrollableAppBarHeight)
        .offset {
            IntOffset(
              x = 0,
              y = toolbarOffsetHeightPx.value.roundToInt() //设置偏移量
            )
        }
        .fillMaxWidth()
    ) {
        .... // 背景图等内容
    }
}

toolBar垂直方向位置不变的实现

设置和父布局相反的位移量保证toolBar处于原位置,即:

// 自定义应用栏
Row(
    modifier = modifier
        .offset {
            IntOffset(
                x = 0,
                y = -toolbarOffsetHeightPx.value.roundToInt() //保证应用栏是始终不动的
            )
        }
        .height(toolBarHeight)
        .fillMaxWidth(),
    verticalAlignment = Alignment.CenterVertically
) {
    ... // 导航图标
}

title水平位移的实现

为了保证title均匀向右位移,用根布局此时向上位移量和最大位移量的商再乘以水平方向上的总位移即可:

x = -((toolbarOffsetHeightPx.value / maxOffsetHeightPx) * titleOffsetWidthReferenceValue).roundToInt()

完整实现

// title部分
Box(
    modifier = Modifier
        .height(toolBarHeight) //和ToolBar同高
        .fillMaxWidth()
        .align(Alignment.BottomStart)
        .offset {
            IntOffset(
                x = -((toolbarOffsetHeightPx.value / maxOffsetHeightPx) * titleOffsetWidthReferenceValue).roundToInt(), //水平方向位移
                y = 0
            )
        },
    contentAlignment = Alignment.CenterStart
) {
    ... //title部分
}

项目地址

ScrollableAppBar如果项目对你有所帮助,如果有改进意见还可以提交 issue

到此这篇关于Android Compose实现伸缩ToolBar的思路详解的文章就介绍到这了,更多相关Android 伸缩ToolBar内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android中ActionBar和ToolBar添加返回箭头的实例代码

     1.ActionBar添加返回箭头 //onCreate方法中 ActionBar actionBar = this.getSupportActionBar(); actionBar.setTitle("搜索功能"); actionBar.setDisplayHomeAsUpEnabled(true); //activity类中的方法 @Override public boolean onOptionsItemSelected(MenuItem item) { if(item.get

  • Android ToolBar控件详解及实例

    ToolBar控件详解 在Activity中添加ToolBar 1.添加库 dependencies { ... compile "com.android.support:appcompat-v7:18.0.+" } 2.Activity要继承AppCompatActivity 3.设置主题 使用ToolBar,要将系统默认的ActionBar隐藏掉 <application android:theme="@style/Theme.AppCompat.Light.NoA

  • Android Toolbar自定义标题标题居中的实例代码

    自定义Toolbar,实现方式如下: 1.布局文件,在activity_main.xml  文件中写入Toolbar <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q

  • Android ToolBar 修改边距的实现方法

    Android ToolBar 修改边距的实现方法 效果图: 实现方式: <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/menuToolbar" android:l

  • Android顶部(toolbar)搜索框实现的实例详解

    Android顶部(toolbar)搜索框实现的实例详解 本文介绍两种SearchView的使用情况,一种是输入框和搜索结果不在一个activity中,另一种是在一个activity中. 首先编写toolbar的布局文件 toolbar中图标在menu文件下定义一个布局文件实现 示例代码: <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.

  • Android Compose实现伸缩ToolBar的思路详解

    目录 ScrollableAppBar 效果图 主要思路 布局预览 实现过程 ScrollableAppBar 效果图 当列表向上移动时,会先带动ToolBar向上位移,等ToolBar向上移动到最大位移量时列表向上滑动 当列表向下移动时,会先带动ToolBar向下位移,等ToolBar向下移动到最大位移量时列表向下滑动 主要思路 布局预览 伸缩前布局: 伸缩后布局: 实现过程 布局实现 首先我们要定义两个尺寸变量 // 应用栏高度 private val toolBarHeight = 56.

  • Android Compose状态改变动画animateXxxAsState使用详解

    目录 前言 animateXxxAsState 基础使用 动画监听 使用示例 animateFloatAsState animateIntAsState animateColorAsState animateSizeAsState/animateIntSizeAsState animateOffsetAsState/animateIntOffsetAsState animateRectAsState 实战 最后 前言 上一篇文章我们探索了 Compose 中属性动画的使用,发现属性动画确实是可以

  • Android开发之无痕过渡下拉刷新控件的实现思路详解

    相信大家已经对下拉刷新熟悉得不能再熟悉了,市面上的下拉刷新琳琅满目,然而有很多在我看来略有缺陷,接下来我将说明一下存在的缺陷问题,然后提供一种思路来解决这一缺陷,废话不多说!往下看嘞! 1.市面一些下拉刷新控件普遍缺陷演示 以直播吧APP为例: 第1种情况: 滑动控件在初始的0位置时,手势往下滑动然后再往上滑动,可以看到滑动到初始位置时滑动控件不能滑动. 原因: 下拉刷新控件响应了触摸事件,后续的一系列事件都由它来处理,当滑动控件到顶端的时候,滑动事件都被下拉刷新控件消费掉了,传递不到它的子控件

  • Android仿京东淘宝自动无限循环轮播控件思路详解

    在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于RelativeLayout,首先要考虑的就是自定义的控件需要扩展那些属性,把这些属性列出来.在这里是要实现类似于京东淘宝的无限轮播广告栏,那么首先想到的就是轮播的时长.轮播指示器的样式等等.我在这里列举了一些并且结合到了代码中. 1.扩展属性 (1)是否开启自动轮播的功能. (2)指示器的图形样式,一

  • Android仿知乎客户端关注和取消关注的按钮点击特效实现思路详解

    先说明一下,项目代码已上传至github,不想看长篇大论的也可以先去下代码,对照代码,哪里不懂点哪里. 代码在这https://github.com/zgzczzw/ZHFollowButton 前几天发现知乎关注的点击效果确实赞,查了一下实现方式,刚好看到这个问题,花了一天时间终于把这个效果实现了,现在来回答一下,很不幸,楼上各位的答案都不全对,且听我一一道来. 首先,我先详细观察了一些知乎的效果,其中有一个很神奇的地方,如图: 注意看第二张图,这个圆形在扩散的时候,圆形底下的字还在,而且新的

  • Android 实现锚点定位思路详解

    相信做前端的都做过页面锚点定位的功能,通过<a href="#head" rel="external nofollow" > 去设置页面内锚点定位跳转. 本篇文章就使用tablayout.scrollview来实现android锚点定位的功能. 效果图: 实现思路 1.监听scrollview滑动到的位置,tablayout切换到对应标签 2.tablayout各标签点击,scrollview可滑动到对应区域 自定义scrollview 因为我们需要监听

  • 基于Android studio3.6的JNI教程之helloworld思路详解

    jdk环境变量配置: path中增加下面2个路径,也就是android studio的路径,android有自带的jdk. E:\Android\Android Studio\jre\bin E:\Android\Android Studio\bin 新建工程: 一定要选择Native c++类型,最后要选c++11支持. SDK设置: File->Settings File->Project Structure 首先确定工程的目录结构,然后尝试运行一下工程,使用模拟器,确保工程没问题, 在M

  • Android 实现抖音小游戏潜艇大挑战的思路详解

    <潜水艇大挑战>是抖音上的一款小游戏,以面部识别来驱动潜艇通过障碍物,最近特别火爆,相信很多人都玩过. 一时兴起自己用Android自定义View也撸了一个,发现只要有好的创意,不用高深的技术照样可以开发出好玩的应用.开发过程现拿出来与大家分享一下. 项目地址: https://github.com/vitaviva/ugame 基本思路 整个游戏视图可以分成三层: camera(相机):处理相机的preview以及人脸识别 background(后景):处理障碍物相关逻辑 foregroun

  • Android EditText输入框实现下拉且保存最近5个历史记录思路详解

    文章结构: 后面又添加了清空历史记录的标签,就是在每一次添加更新后台数组后,数组的下一个标签为清空历史记录. s_btnDown.setOnClickListener(this); //对其进行焦点监听 case R.id.btnDown: showListPopulWindow(); //调用显示PopuWindow 函数 break; 点击后触发PopuWindow函数,也就是将其下拉框,绑定到TextBox标签的下面. private void showListPopulWindow()

随机推荐