有一个
CoordinatorLayout
包含一个 AppBarLayout
和一个 NestedScrollView
,其中包含一个 TextView
。 TextView
有 Markdown 文本。我想滚动到锚点 (#header
)。下面的代码按预期工作,但是调用 NestedScrollView.scrollTo
后,CoordinatorLayout
不会触发滚动时隐藏 AppBarLayout
的行为。
需要做什么才能让
CoordinatorLayout
接收到代码触发的滚动事件?我尝试过使用smoothScrollTo
,scrollBy
,不起作用。当用户手动滚动时,AppBarLayout
按预期隐藏。
fun scrollToAnchor(view: View, anchor: String) {
val textView = view as TextView
textView.setTextIsSelectable(false)
val spanned = textView.text as Spanned
val spans = spanned.getSpans(0, spanned.length, AnchorSpan::class.java)
if (spans != null) {
for (span in spans) {
if (anchor == span.anchor) {
val start = spanned.getSpanStart(span)
val line = textView.layout.getLineForOffset(start)
val top = textView.layout.getLineTop(line)
val scrollToFunc = (view.parent as? NestedScrollView)?.let { it::scrollTo } ?: view::scrollTo
scrollToFunc.invoke(0, top)
break
}
}
}
textView.setTextIsSelectable(true)
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:id="@+id/doc_page_coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/doc_paga_top_app_bar"
style="@style/Widget.Material3.Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="0dp"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:menu="@menu/menu_only_close"
app:title="@string/docs_title" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?actionBarSize"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:id="@+id/markdown_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/view_indent_horizontal"
android:isScrollContainer="true"
android:scrollbarThumbVertical="@android:color/transparent"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
android:textColor="?attr/colorOnBackground"
android:textIsSelectable="true"
tools:text="Lorem ipsum dolor sit amet" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
当您以编程方式滚动 NestedScrollView 时,AppBarLayout 可能不会自动隐藏,因为 AppBarLayout 的滚动行为依赖于用户的滚动手势,而不是编程滚动。但是,当您以编程方式滚动时,您可以手动触发 AppBarLayout 的隐藏行为。
滚动后在 AppBarLayout 上使用 setExpanded(false, true) 。这将折叠应用程序栏并确保它在您滚动到指定标题时隐藏。 步骤:
给 app_bar 布局 id
setExpanded(false, true)
fun scrollToAnchor(view: View, anchor: String) {
val textView = view as TextView
textView.setTextIsSelectable(false)
val spanned = textView.text as Spanned
val spans = spanned.getSpans(0, spanned.length,
AnchorSpan::class.java)
if (spans != null) {
for (span in spans) {
if (anchor == span.anchor) {
val start = spanned.getSpanStart(span)
val line = textView.layout.getLineForOffset(start)
val top = textView.layout.getLineTop(line)
val appBarLayout = findViewById<AppBarLayout>(R.id.app_bar_layout)
appBarLayout.setExpanded(false, true)
val scrollToFunc = (view.parent as? NestedScrollView)?.let { it::scrollTo } ?: view::scrollTo
scrollToFunc.invoke(0, top)
break
}
}
} textView.setTextIsSelectable(true) }