直接贴代码
//获取collapsing_tool_bar_layout的collapsingTextHelper,由于不是public的,因此使用java的反射来获取 val field = collapsing_tool_bar_layout.javaClass.getDeclaredField("collapsingTextHelper") field.isAccessible = true val collapsingTextHelper = field.get(collapsing_tool_bar_layout) as CollapsingTextHelper //同理,获取collapsingTextHelper中的currentBounds val fieldCurrentBounds = collapsingTextHelper.javaClass.getDeclaredField("currentBounds") fieldCurrentBounds.isAccessible = true val currentRectF = fieldCurrentBounds.get(collapsingTextHelper) as RectF //自定义折叠Toolbar,使TextView随着AppBarLayout高度的变化而改变位置 //AppBarStateChangeListener是自定义继承自AppBarLayout.OnOffsetChangedListener的抽象类 app_bar_layout.addOnOffsetChangedListener(object : AppBarStateChangeListener() { override fun onExpandPercentChange(state: State, expandPercent: Float) { Log.d("CUSTOM_COLLAPSED_TITLE", "currentRectF:${JSON.toJSONString(currentRectF)}") val layoutParams = LinearLayout.LayoutParams(text_view_symbol.layoutParams) layoutParams.setMargins( currentRectF.left.toInt(), layoutParams.topMargin, layoutParams.rightMargin, (DensityUtils.dp2px(15f) * expandPercent).toInt() + //因为textview大小为18sp,与折叠ToolbarLayout的20sp不一致,为了在折叠后尽量保持在一条水平先上 (DensityUtils.dp2px(2.5f) * (1 - expandPercent)).toInt() ) // text_view_symbol.setTextSize(20-((20-18)*expandPercent)) text_view_symbol.layoutParams = layoutParams text_view_creator_info.alpha = expandPercent if (expandPercent > 0.8) { fab_add_record.show() } else { fab_add_record.hide() } } override fun onStateChanged(appBarLayout: AppBarLayout?, state: State?, i: Int) { when (state) { State.COLLAPSED -> { XLog.d("RecordListActivity, State.COLLAPSED") // fab_add_record.hide() } State.EXPANDED -> { XLog.d("RecordListActivity, State.EXPANDED") collapsing_tool_bar_layout?.title = null text_view_symbol.visibility = View.VISIBLE text_view_title.visibility = View.VISIBLE } State.SCROLLING -> { collapsing_tool_bar_layout?.title = " " + viewModel.recordType.title text_view_title.visibility = View.INVISIBLE } else -> { //ignore } } } })
附 AppBarStateChangeListener 代码
abstract class AppBarStateChangeListener : AppBarLayout.OnOffsetChangedListener { enum class State { EXPANDED, COLLAPSED, SCROLLING, IDLE } private var mCurrentState = State.IDLE override fun onOffsetChanged(appBarLayout: AppBarLayout?, i: Int) { val expandPercent = 1f + (i / (appBarLayout?.totalScrollRange ?: -i).toFloat()) when { i == 0 -> { if (mCurrentState != State.EXPANDED) { mCurrentState = State.EXPANDED onStateChanged(appBarLayout, mCurrentState, i) } } abs(i) >= appBarLayout!!.totalScrollRange -> { if (mCurrentState != State.COLLAPSED) { mCurrentState = State.COLLAPSED onStateChanged(appBarLayout, mCurrentState, i) } } else -> { mCurrentState = State.SCROLLING onStateChanged(appBarLayout, State.SCROLLING, i) } } Log.d("AppBarLayout.onOffsetChanged","$i/${appBarLayout?.totalScrollRange},${mCurrentState},${expandPercent}") onExpandPercentChange(mCurrentState, expandPercent) } abstract fun onExpandPercentChange(state: State, expandPercent: Float) abstract fun onStateChanged(appBarLayout: AppBarLayout?, state: State?, i: Int) }
问题解决过程
- 查看 CollapsingToolbarLayout 的源码,发现 CollapsingTextHelper,利用反射获取到 collapsingTextHelper
- 查看 CollapsingTextHelper 的源码,发现 currentBounds,再利用反射获取到 currentBounds
- 监听 AppBarLayout 高度变化,然后获取 currentBounds.left 等信息,然后实时更改 TextView 的位置