标签: android-viewpager2

带有 Viewpager2 的关键 FragmentStateAdapter 不再存在 Fragment

我正在为我的项目使用 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

13
推荐指数
1
解决办法
4616
查看次数

FragmentStateAdapter 在notifyDataSetChanged 后不重新创建currentFragment

我有一个 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 android-fragments android-viewpager2

13
推荐指数
1
解决办法
2446
查看次数

如何禁用ViewPager2中的滑动?

是否可以在新的android viewpager2组件中启用-禁用刷卡功能?

android androidx android-viewpager2

12
推荐指数
5
解决办法
1746
查看次数

TabLayoutMediator 不保留 TabItem 属性

我使用带有预设 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

12
推荐指数
1
解决办法
1676
查看次数

ViewPager2 | View.ClickListener 未调用

我使用新的 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)

android android-viewpager2

11
推荐指数
1
解决办法
3247
查看次数

查看 Pager 的上一个和下一个项目的尺寸更小,无限滚动

想要创建与以下 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

11
推荐指数
3
解决办法
1万
查看次数

打开 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 也会滚动到最后一个位置。

android android-recyclerview android-viewpager2

11
推荐指数
1
解决办法
5682
查看次数

ViewPager2/Tabs 的 ViewModel 状态问题

我遵循 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

10
推荐指数
1
解决办法
1955
查看次数

Android:如何在 ViewPager2 中拦截触摸事件

当触摸事件来自嵌套视图(例如 Horizo​​ntalScrollView 等)时,如何防止在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 行长,而且它使用的类不是由包导出的。

我看过的其他类似问题:

android ontouchlistener swipe-gesture android-viewpager2

10
推荐指数
0
解决办法
1752
查看次数

如何让ViewPager2不那么敏感?

我在我的应用程序中使用 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 kotlin android-viewpager2

10
推荐指数
1
解决办法
4018
查看次数