我最近遇到了一个非常奇怪的问题。我的布局中有一个地图视图,它使用数据绑定进行了膨胀。在我将 ViewPager2 添加到我的布局后,我遇到了这个问题:
java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class androidx.recyclerview.widget.RecyclerView$SavedState instead. This usually happens when two views of different type have the same id in the same hierarchy. This view's id is id/0x1. Make sure other views do not use the same id.
Run Code Online (Sandbox Code Playgroud)
但是只有当您首先打开第一个片段并转到下一个片段,然后按返回时才会发生这种情况。
似乎它与视图状态有关,但是我可以做些什么来解决这个问题?
这是一个示例片段代码:
class TestFragment(override val layoutRes: Int = R.layout.fragment_test) : BaseFragment() {
lateinit var binding: FragmentTestBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? …Run Code Online (Sandbox Code Playgroud) android android-mapview android-databinding android-viewpager2
该应用程序使用 android viewpager2 (androidx.viewpager2:viewpager2:1.0.0-beta04) 来显示幻灯片。每张幻灯片的上半部分都有视频,下半部分有文字。每张幻灯片都是使用相同的片段类构建的(代码如下)
演讲活动
myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
myViewPager2.setAdapter(myAdapter);
myViewPager2.setOffscreenPageLimit(3);
myViewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (mLoadedFragment != null) {
mLoadedFragment.pauseMedia();
}
}
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
try {
rvSlideIndex.invalidate();
adapterSlideIndex.updateSelectedSlide(position);
//setTitle(mSlides.get(position).getTitle());
setScreenTitle(mSlides.get(position).getTitle());
mLoadedFragment = ((PresentationSlideFragment) myAdapter.createFragment(position));
mLoadedFragment.startVideo();
} catch (Exception e) {
}
}
@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
if (mLoadedFragment != null && state == ViewPager2.SCROLL_STATE_SETTLING) {
mLoadedFragment.clearMediaPlayer();
}
} …Run Code Online (Sandbox Code Playgroud) 我正在使用最新版本的 ViewPager2 'androidx.viewpager2:viewpager2:1.0.0-beta04'
我有 10 页,每一页都是 Fragment。
如果我设置,viewpager2.offscreenPageLimit = 1
我必须滚动到第 5 页以使第一页销毁。
发生了什么???,当我滚动到第 3 页时,第一页应该被破坏了吧??
然后我尝试另一种方式使它正确
(viewpager2.getChildAt(0) as RecyclerView).layoutManager?.isItemPrefetchEnabled = false
(viewpager2.getChildAt(0) as RecyclerView).setItemViewCacheSize(1)
Run Code Online (Sandbox Code Playgroud)
这样,当我滚动到第 3 页时,第一页将被破坏,它现在正在工作
任何人都可以向我解释这两个属性之间的区别吗?
非常感谢
我使用的是ViewPager2版本 1.0.0-beta05,带有 RecyclerView.Adapter 和ZoomOutPageTransformer,我发现当我们调用 notifyDataSetChanged 时,ViewPager 视图会爆炸。
在 1.0.0-alpha01 版本中,他们说 notifyDataSetChanged 功能齐全(解决了 VP1 错误)
pagerAdapter?.clickListener = this
with(pager) {
clipToPadding = false
clipChildren = false
offscreenPageLimit = 3
}
pager.adapter = pagerAdapter
pager.setPageTransformer(ZoomOutPageTransformer())
GlobalScope.launch(Dispatchers.Main) {
// launch a new coroutine in background and continue
repeat(15) {
delay(5000L) // non-blocking delay for 1 second (default time unit is ms)
Log.e("hello", "notify")
pagerAdapter?.notifyDataSetChanged()
}
}
Run Code Online (Sandbox Code Playgroud)
我没有改变数据源,我只是做了这个小测试,问题仍然存在,每次调用notifyDataSetChanged后,视图都会被随机调整为丑陋的。
android kotlin android-pagetransformer android-recyclerview android-viewpager2
ViewPager2 PageChangeListener 不像普通的 ViewPager 那样工作。?
我正在使用ViewPager2与FragmentStateAdapter. 基本 3 片段 (ABC)。这意味着,您可以从 A 滚动到 B,从 B 滚动到 C
我想做的事?
从片段 B 开始子片段 D
(A-B-C)
|
D
从片段B开始片段D,当用户单击“后退箭头”(顶部栏)时,片段D将被销毁并且用户将回到B。(我不想使用activity)
我尝试了什么?
val ft: FragmentTransaction = requireActivity().supportFragmentManager.beginTransaction()
ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
ft.replace(android.R.id.content, DetailsFragment())
ft.addToBackStack(null)
ft.commit();
Run Code Online (Sandbox Code Playgroud)
对于上面的代码,我有两个问题。
编辑:将片段管理器传递给ViewPager2onCreate() 方法中的 main_activity
pagerAdapter = PagerAdapter(supportFragmentManager, lifecycle)
binding.mainViewPager.adapter = pagerAdapter
Run Code Online (Sandbox Code Playgroud)
PagerAdapter 是一个简单的类:
class PagerAdapter(fm: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fm, lifecycle)
我有 ViewPager2 回调设置,但需要检测用户启动的页面更改何时完成。回调不会区分用户启动和代码启动。这是我现在所拥有的:
ViewPager2.OnPageChangeCallback swipeListener = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
//I want to run code only if user initiated this page change
//but this runs whether user initiated or code initiated
}
}
Run Code Online (Sandbox Code Playgroud)
通过代码完成的页面更改:
viewPager.setCurrentItem(targetSlide);
Run Code Online (Sandbox Code Playgroud)
ViewPager2 的文档显示了一种isUserInputEnabled()方法,可以告诉您用户是否“可以”手动更改页面,但我需要检测用户是否“确实”启动了页面更改。
我正在使用ViewPager2withTabLayout和FragmentStateAdapter在选项卡中显示片段。我发现,当我在较慢的设备(即 Nexus 5X)上运行它时,或者当我在createFragment()方法中放置断点时,在我更改为带有片段的稍后选项卡(尚未创建)后,会显示最后一个位置的片段。
例如我有 20 个项目。我选择位置 15 上的选项卡。位置 15、14、16、17、18、19 和 20 上的片段被创建(createFragment()称为)。我预计只会创建 14、15、16 个。在慢速设备上或在createFragment()方法内部停止调试器时,会显示位置 20 上的片段。
在未减速的设备上不会发生此问题。
主要活动:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViewPager2WithFragments()
}
private fun initViewPager2WithFragments() {
val viewPager2: ViewPager2 = findViewById(R.id.viewpager)
val adapter = ExampleStateAdapter(supportFragmentManager, lifecycle)
viewPager2.adapter = adapter
val tablayout: TabLayout = findViewById(R.id.tablayout)
val names: Array<String> = arrayOf(
"Fragment A",
"Fragment B",
"Fragment C",
"Fragment D",
"Fragment …Run Code Online (Sandbox Code Playgroud) 我正在将 aViewPager2与 a 一起使用FragmentStateAdapter。
public class MyAdapter extends FragmentStateAdapter {
public MyAdapter(@NonNull Fragment fragment) {
super(fragment);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return MyFragment.newInstance(MyClass.func(position));
}
@Override
public int getItemCount() {
return MyClass.NUM;
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,调用notifyDataSetChanged()适配器根本没有任何效果。(打电话notifyItemChanged(position)效果很好。)
我该如何解决这个问题?