我正在为我的项目使用 ViewPager2。我需要在带有 viewpager2 的片段中使用嵌套片段。在我尝试在片段(不是嵌套片段)之间导航之前,它就像魅力一样。
第一次在片段之间导航后,应用程序崩溃并显示下面解释的错误。
包含嵌套片段 OnCreateView 方法的片段:
View view = inflater.inflate(R.layout.orders_fragment, null);
ViewPager2 viewPager = view.findViewById(R.id.childViewPager);
TabLayout tabs = view.findViewById(R.id.tabs);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager(),getLifecycle());
viewPager.setAdapter(sectionsPagerAdapter);
TabLayoutMediator.TabConfigurationStrategy tabConfigurationStrategy = (tab, position) -> {
String[] order_activity_tabs = getResources().getStringArray(R.array.situations);
for (int i=0; i<order_activity_tabs.length; i++) {
if(i==position)
tab.setText(order_activity_tabs[i]);
}
};
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabs, viewPager, tabConfigurationStrategy);
tabLayoutMediator.attach();
return view;
Run Code Online (Sandbox Code Playgroud)
当我返回包含嵌套片段的片段时,它会崩溃
java.lang.IllegalStateException: Fragment no longer exists for key f#0: unique id 4fbe17b8-5e22-4e07-a543-4a79445ad39c
at androidx.fragment.app.FragmentManagerImpl.getFragment(FragmentManagerImpl.java:365)
at androidx.viewpager2.adapter.FragmentStateAdapter.restoreState(FragmentStateAdapter.java:549)
at androidx.viewpager2.widget.ViewPager2.restorePendingState(ViewPager2.java:350)
at androidx.viewpager2.widget.ViewPager2.dispatchRestoreInstanceState(ViewPager2.java:375)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:4045) …Run Code Online (Sandbox Code Playgroud) android android-adapter android-fragments fragmentstatepageradapter android-viewpager2
我有一个 FragmentStateAdapter 作为 ViewPager2 的适配器。
class DefaultFragmentStateAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
var items = listOf<Fragment>()
set(value) {
field = value
notifyDateSetChanged()
}
override fun getItemCount(): Int = items.size
override fun createFragment(position: Int): Fragment = items[position]
}
Run Code Online (Sandbox Code Playgroud)
适配器项可以根据用户选择的日期进行更改,因此它需要是动态的。发生的情况是,在我调用adapter.items = {new_fragments}当前片段后没有重新加载,只有在我转到 ViewPager 中的最后一页并返回第一页后,我才能看到更新的片段。当前片段在notifyDataSetChanged被调用时不会更新。
我怎样才能更新当前显示的片段?
是否可以在新的android viewpager2组件中启用-禁用刷卡功能?
我使用带有预设 TabItems 的 ViewPager2 和 TabLayout 进行了简单设置:
...
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="0dp"
android:layout_height="64dp"
app:tabTextColor="@color/c0696D7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/palettesToggle"
app:layout_constraintTop_toTopOf="parent"
app:tabBackground="@color/cEEEEEE"
app:tabIndicatorColor="@color/cFFFFFF"
app:tabGravity="fill"
app:tabUnboundedRipple="true"
app:tabIconTint="@color/palettes_icon_tint"
app:tabIndicatorGravity="stretch"
app:tabMode="fixed">
<com.google.android.material.tabs.TabItem android:icon="@drawable/palettes_layers" />
<com.google.android.material.tabs.TabItem android:icon="@drawable/palettes_view" />
<com.google.android.material.tabs.TabItem android:icon="@drawable/palettes_properties" />
<com.google.android.material.tabs.TabItem android:icon="@drawable/palettes_blocks" />
<com.google.android.material.tabs.TabItem android:icon="@drawable/palettes_blocks" />
<com.google.android.material.tabs.TabItem android:icon="@drawable/palettes_settings" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabs" />
...
Run Code Online (Sandbox Code Playgroud)
以及以下接线代码:
TabLayoutMediator(tabs, viewPager) { tab, position ->
}.attach()
Run Code Online (Sandbox Code Playgroud)
以下设置忽略了TabItemicon 属性,我看到了空标签。似乎TabLayoutMediator完全覆盖了定义的 xml 属性,我必须将这些属性重置为TabConfigurationStrategy回调的一部分。我错过了什么吗?
android android-tablayout material-components-android android-viewpager2
我使用新的 android 小部件 ViewPager2 版本 1.0.0-alpha03,当我在它上面设置点击侦听器时,方法 onClick() 没有被调用。
我的活动课:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportFragmentManager.beginTransaction()
.add(R.id.fragmentContent, SecondFragment.newInstance(), SecondFragment.TAG)
.addToBackStack(SecondFragment.TAG)
.commit()
}
}
Run Code Online (Sandbox Code Playgroud)
我的片段:
class SecondFragment : Fragment() {
companion object {
val TAG = SecondFragment::class.java.canonicalName
fun newInstance(): SecondFragment = SecondFragment()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_second, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewPager2.setOnClickListener {
Log.d("logi", "click : ")
}
} …Run Code Online (Sandbox Code Playgroud) 想要创建与以下 UI 相同的视图寻呼机,应用了自定义转换器但不起作用。
ViewPager.java
public class MyViewPager extends ViewPager implements ViewPager.PageTransformer {
public static final String TAG = "MyViewPager";
private float MAX_SCALE = 0.0f;
private int mPageMargin;
private boolean animationEnabled=true;
private boolean fadeEnabled=false;
private float fadeFactor=0.5f;
public MyViewPager(Context context) {
this(context, null);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// clipping should be off on the pager for its children so that they can scale out of bounds.
setClipChildren(false);
setClipToPadding(false);
// to avoid fade effect at the end …Run Code Online (Sandbox Code Playgroud) android android-animation android-viewpager android-transitions android-viewpager2
我已经用一些视频(比如 10)实现了一个 recyclerview 。单击任何项目会打开一个viewpager2 which is on some other activity带有and单击的所有项目(来自recyclerview)的所有项目。之后,用户只能从那里滚动到其他项目。一切正常。
唯一的问题是当 recyclerview 项目单击打开 viewpager2 时的滚动。
Whenever any item is selected(10th). viewpager 首先打开,然后滚动到(第 10 个)位置。我想直接打开viewpager2的第10个位置而不滚动。任何帮助,将不胜感激。
我曾尝试将当前项目设置为
viewPagerReview.currentItem = recyclerviewItemSelectedPosition
Run Code Online (Sandbox Code Playgroud)
但是如果当前项目是 recyclerview 的最后一个位置,那么 viewpager 也会滚动到最后一个位置。
我遵循 MVVM 模式 - 这意味着我为每个 Fragment 都有一个 ViewModel。
我使用 ViewPager2添加了两个选项卡。
我的适配器看起来像这样:
@Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new MergedItemsFragment();
case 1:
return new ValidatedMergedItemsFragment();
}
return new MergedItemsFragment();
}
Run Code Online (Sandbox Code Playgroud)
选项卡正在工作。但是,我注意到我的 MergedItemsFragment 的 ViewModel 表现得很奇怪。在我添加标签之前,我像这样导航到 Fragment:
NavHostFragment.findNavController(this).navigate(R.id.action_roomFragment_to_itemsFragment);
Run Code Online (Sandbox Code Playgroud)
当我离开那个片段NavHostFragment.findNavController(this).popBackStack()然后返回到那个片段时,我会得到一个新的空 ViewModel。这是有意的。
使用新方法,我正在使用return new MergedItemsFragment(). 当我离开那个片段并稍后返回时,我得到一个包含旧数据的 ViewModel 。这是一个问题,因为旧数据不再相关,因为用户在另一个片段中选择了不同的数据。
更新 #1
我意识到他实际上将所有旧片段保存在内存中,因为多次调用相同的打印语句。它被调用的次数随着我离开并返回该屏幕的次数而增加。因此,如果我离开并返回 10 次并旋转我的设备,他实际上会执行一行 10 次。任何猜测如何以与 ViewModels 一起工作的方式使用导航组件实现 Tabs/ViewPagers?
更新 #2
我这样设置我的 ViewModel:
@Override
public …Run Code Online (Sandbox Code Playgroud) java android android-viewmodel android-architecture-navigation android-viewpager2
当触摸事件来自嵌套视图(例如 HorizontalScrollView 等)时,如何防止在androidx ViewPager2 中滑动?
我希望通过覆盖可以实现这一点,ViewPager2.onInterceptTouchEvent()但是由于 ViewPager2final不能被子类化。
现有的解决方案(见下表)处理与旧ViewPager它可以被继承。
正如我尝试过的其中一个答案中所建议的那样:
private ViewPager2 viewPager2;
...
HorizontalScrollView nestedScrollView = pagerView.findViewById(R.id.scrollview);
nestedScrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
viewPager2.requestDisallowInterceptTouchEvent(true);
return false;
}
});
// nestedScrollView - the HorizontalScrollView inside a ViewPager2 item
// viewPager2 - the ViewPager2 instance
Run Code Online (Sandbox Code Playgroud)
但这似乎没有任何效果。
ViewPager2 具有从 ViewGroup 继承的onInterceptTouchEvent()但我没有看到在最终类上覆盖它的方法。
重新实现整个 ViewPager2 似乎不是一个明智的解决方案——原始类有 1607 行长,而且它使用的类不是由包导出的。
我看过的其他类似问题:
我在我的应用程序中使用 ViewPager2,它有三个页面,每个页面显示不同的内容,问题是即使有人向下滚动并且错误地将手指向右移动一点,ViewPager 也会更改页面,这太明智了或离开。
那么我怎样才能让 ViewPager 不那么敏感呢?ViewPager2是在Activity中创建的
这是我初始化 ViewPager 的代码:
private lateinit var viewPager: ViewPager2
private lateinit var adapterView: ViewPagerAdapter
private fun initViewPager() {
adapterView.addFragment(ElencoFragment())
adapterView.addFragment(TestataFragment())
adapterView.addFragment(CorpoFragment())
adapterView.notifyDataSetChanged()
viewPager.adapter = adapterView
...
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewPager = findViewById(R.id.pager)
adapterView = ViewPagerAdapter(supportFragmentManager, lifecycle)
...
}
Run Code Online (Sandbox Code Playgroud)
我的适配器:
class ViewPagerAdapter
(manager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(manager, lifecycle) {
private var fragmentList: ArrayList<Fragment> = ArrayList()
override fun getItemCount(): Int {
return fragmentList.size
}
override fun createFragment(position: Int): Fragment {
return fragmentList[position] …Run Code Online (Sandbox Code Playgroud) android ×10
android-architecture-navigation ×1
androidx ×1
java ×1
kotlin ×1