嵌套的 viewpager:让外部滑动而不是内部滑动
nested viewpagers: letting the outer swipe but not the inner
简而言之:
我有一个 ViewPager
、vpOuter
显示的片段有另一个 ViewPager
、vpInner
。
用户应该能够在 vpOuter
的片段之间滑动,但显示为 vpInner
的片段只能以编程方式交换。
现在,在 vpInner
上滑动没有任何作用,而在 vpInner
外部滑动会在 vpOuter
的片段之间切换。
如何才能让在 vpInner
上滑动被识别为在 vpOuter
之间滑动?
(两个ViewPager
互不相识)
完整故事:
好的,所以我有一个 activity,它有一个包含三个片段的视图寻呼机。
我们称它们为 A、B 和 C。
现在用户可以在它们之间滑动或使用底部导航。
A
是我们的 "viewer fragment",如果有可显示的内容,它会显示一些内容;如果没有可显示的内容,则什么也不会显示,但它一次只会显示一个内容。
A
包含不可滑动的视图寻呼机。
其背后的原因是我们想要显示文本和图像以及谁知道什么,我们为要显示的每种媒体类型创建一个视图片段。所以当我们有东西要显示时,我们会检查它是什么,切换到相应的片段并用数据填充它。
因此,A 看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<[...].android.ui.widgets.NonswipableViewPager
android:id="@+id/view_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!--irrrelevant floating action button here-->
</android.support.design.widget.CoordinatorLayout>
哪里
/**A view pager that disables swiping to switch between pages.
* Switching must happen programmatically.*/
class NonswipableViewPager:ViewPager{
constructor(context:Context):super(context)
constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet)
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return false
}
override fun onTouchEvent(ev: MotionEvent?): Boolean {
return false
}
}
让我们假设只有我们想要显示的文本内容。
然后我们有两个片段:
class NoContentView : AbstractContentView() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val fragmentView = inflater.inflate(R.layout.fragment_A_component_text_view, container, false)
fragmentView.content.text = Html.fromHtml(getString(R.string.A_nothingToShow))
return fragmentView
}
//more irrelevant stuff here
}
当我们没有什么可展示的时候我们展示,
class TextContentView:AbstractContentView(){
@Volatile private var displayedData:String? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_A_component_text_view, container, false)
displayedData?.let { view.content.text = it }
return view
}
override fun display(c: IDisplayableContent) {
displayedData = String(c.data, Charsets.UTF_8)
content?.text = displayedData
}
}
他们都为这里的布局充气:
<?xml version="1.0" encoding="utf-8"?>
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_gravity="center"
android:fillViewport="true"
>
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:gravity="center"
tools:text="PLACEHOLDER" />
</ScrollView>
</android.widget.LinearLayout>
如果显示 TextContentView
,则一切正常,我可以在片段 A
、B
和 C
之间滑动而不会出现问题。
但是在显示NoContentView
的时候,我需要在滑动的时候有意识地避开文字内容,否则就什么也做不了。
如何让它始终表现得好像不存在不可滑动的视图寻呼机一样?
这里的问题是由于外部 ViewPager 感知到它有可以向同一方向滚动的可滚动内容,所以外部 ViewPager 拒绝向那个方向滚动。
这可以通过将内部 ViewPager 中的 canScrollHorizontally(int direction)
覆盖为 return false 来解决。
简而言之:
我有一个 ViewPager
、vpOuter
显示的片段有另一个 ViewPager
、vpInner
。
用户应该能够在 vpOuter
的片段之间滑动,但显示为 vpInner
的片段只能以编程方式交换。
现在,在 vpInner
上滑动没有任何作用,而在 vpInner
外部滑动会在 vpOuter
的片段之间切换。
如何才能让在 vpInner
上滑动被识别为在 vpOuter
之间滑动?
(两个ViewPager
互不相识)
完整故事:
好的,所以我有一个 activity,它有一个包含三个片段的视图寻呼机。
我们称它们为 A、B 和 C。
现在用户可以在它们之间滑动或使用底部导航。
A
是我们的 "viewer fragment",如果有可显示的内容,它会显示一些内容;如果没有可显示的内容,则什么也不会显示,但它一次只会显示一个内容。
A
包含不可滑动的视图寻呼机。
其背后的原因是我们想要显示文本和图像以及谁知道什么,我们为要显示的每种媒体类型创建一个视图片段。所以当我们有东西要显示时,我们会检查它是什么,切换到相应的片段并用数据填充它。
因此,A 看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<[...].android.ui.widgets.NonswipableViewPager
android:id="@+id/view_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!--irrrelevant floating action button here-->
</android.support.design.widget.CoordinatorLayout>
哪里
/**A view pager that disables swiping to switch between pages.
* Switching must happen programmatically.*/
class NonswipableViewPager:ViewPager{
constructor(context:Context):super(context)
constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet)
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return false
}
override fun onTouchEvent(ev: MotionEvent?): Boolean {
return false
}
}
让我们假设只有我们想要显示的文本内容。
然后我们有两个片段:
class NoContentView : AbstractContentView() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val fragmentView = inflater.inflate(R.layout.fragment_A_component_text_view, container, false)
fragmentView.content.text = Html.fromHtml(getString(R.string.A_nothingToShow))
return fragmentView
}
//more irrelevant stuff here
}
当我们没有什么可展示的时候我们展示,
class TextContentView:AbstractContentView(){
@Volatile private var displayedData:String? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_A_component_text_view, container, false)
displayedData?.let { view.content.text = it }
return view
}
override fun display(c: IDisplayableContent) {
displayedData = String(c.data, Charsets.UTF_8)
content?.text = displayedData
}
}
他们都为这里的布局充气:
<?xml version="1.0" encoding="utf-8"?>
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_gravity="center"
android:fillViewport="true"
>
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:gravity="center"
tools:text="PLACEHOLDER" />
</ScrollView>
</android.widget.LinearLayout>
如果显示 TextContentView
,则一切正常,我可以在片段 A
、B
和 C
之间滑动而不会出现问题。
但是在显示NoContentView
的时候,我需要在滑动的时候有意识地避开文字内容,否则就什么也做不了。
如何让它始终表现得好像不存在不可滑动的视图寻呼机一样?
这里的问题是由于外部 ViewPager 感知到它有可以向同一方向滚动的可滚动内容,所以外部 ViewPager 拒绝向那个方向滚动。
这可以通过将内部 ViewPager 中的 canScrollHorizontally(int direction)
覆盖为 return false 来解决。