ViewPager2 不能正常处理 Fragments 和点击事件
ViewPager2 not working properly with Fragments and click events
我只是想知道我是否做错了什么,因为我对这一切有点陌生。
如果您希望我添加任何其他内容,请告诉我。
如果您想查看所有代码,This 是我尝试实现 ViewPager 的 repo 分支。
上下文
所以我有 4 个类别,用 Fragments
表示,每个类别都有一个 ArrayList
个项目,每个项目都有一个 onItemClickListener
应该重现一些音频。
我正在尝试使用 ViewPager 显示 Fragments
,但 问题是当我从 Fragment
滚动到另一个时,然后返回到已创建的 Fragment
,它没有注册触摸事件,没有任何反应,甚至没有错误或异常。
如果我转到新创建的 Fragment
,触摸效果很好。
此外,在切换回已创建的 Fragment
之后,如果我稍微滚动到另一个 Fragment
并返回或通过 ArrayList
Fragment
由于某种原因,它再次开始识别 ArrayList
项中的触摸。
没有真正帮助的类似问题
- Android ViewPager2 with fragment containing a recyclerview not scrolling
我试过的
- 我尝试用
coordinatorlayout
包装 ViewPager2
但没有区别
- 我一直在阅读一些用 Kotlin 编写的官方 viewPager2 示例,但其中 none 似乎有类似的情况(我也很难阅读 Kotlin 代码)
代码片段
word_list.xml:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/tan_background" />
activity_main.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"/>
</FrameLayout>
这是其中一个Fragments,其他三个基本一样,只是arrayList中的items发生了变化,还有一些其他的小东西:
// ...Skipped some irrelevant code...
public class NumbersFragment extends Fragment {
private ArrayList<Word> mWords;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.word_list, container, false);
mWords = new ArrayList<>();
// ...Add all the items to the list...
// Make the adapter for the word items
WordAdapter adapter = new WordAdapter(getActivity(), mWords, R.color.category_numbers);
// Find the root view of the list
ListView listView = rootView.findViewById(R.id.root_list_view);
// Add adapter to the root list view
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("NumbersFragment", "CLICKED");
}
}
});
return rootView;
}
@Override
public void onPause() {
super.onPause();
Log.d("NumbersFragment", "Fragment paused");
}
}
这是类别适配器,它管理片段:
public class CategoryAdapter extends FragmentStateAdapter {
private static final int NUM_CATEGORIES = 4;
// Required public constructor
public CategoryAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull
@Override
public Fragment createFragment(int position) {
// Depending on which page the user is in,
// create a fragment of the corresponding category
switch (position) {
case 0:
return new NumbersFragment();
case 1:
return new FamilyFragment();
case 2:
return new ColorsFragment();
default:
return new PhrasesFragment();
}
}
@Override
public int getItemCount() {
return NUM_CATEGORIES;
}
}
这是我的 MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_main);
// Find the view pager that will allow the user to swipe between fragments
ViewPager2 viewPager = findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
CategoryAdapter adapter = new CategoryAdapter(this);
//or CategoryAdapter adapter = new CategoryAdapter(getSupportFragmentManager(), getLifecycle());
// Set the adapter into the view pager
viewPager.setAdapter(adapter);
}
}
在创建 viewpager
后在 MainActivity viewPager.setOffscreenPageLimit(3);
中添加这个
因为ViewPager的默认离屏限制为1,而ViewPager2的默认离屏限制为0。
在 ViewPager2 中,当您切换标签时,上一个标签将自动刷新。
在 ViewPager 中,如果您有 3 个或更多选项卡,当您自动切换到第 3 个选项卡时,第一个选项卡将被销毁,当您转到第 1 个选项卡时,它将被重新创建。
viewPager.setOffscreenPageLimit(3);
从这一行开始,当您切换到一个标签时,将预加载前 3 个标签,并预加载接下来的 3 个标签,因此不会刷新任何内容。
我只是想知道我是否做错了什么,因为我对这一切有点陌生。
如果您希望我添加任何其他内容,请告诉我。
如果您想查看所有代码,This 是我尝试实现 ViewPager 的 repo 分支。
上下文
所以我有 4 个类别,用 Fragments
表示,每个类别都有一个 ArrayList
个项目,每个项目都有一个 onItemClickListener
应该重现一些音频。
我正在尝试使用 ViewPager 显示 Fragments
,但 问题是当我从 Fragment
滚动到另一个时,然后返回到已创建的 Fragment
,它没有注册触摸事件,没有任何反应,甚至没有错误或异常。
如果我转到新创建的 Fragment
,触摸效果很好。
此外,在切换回已创建的 Fragment
之后,如果我稍微滚动到另一个 Fragment
并返回或通过 ArrayList
Fragment
由于某种原因,它再次开始识别 ArrayList
项中的触摸。
没有真正帮助的类似问题
- Android ViewPager2 with fragment containing a recyclerview not scrolling
我试过的
- 我尝试用
coordinatorlayout
包装ViewPager2
但没有区别 - 我一直在阅读一些用 Kotlin 编写的官方 viewPager2 示例,但其中 none 似乎有类似的情况(我也很难阅读 Kotlin 代码)
代码片段
word_list.xml:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/tan_background" />
activity_main.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"/>
</FrameLayout>
这是其中一个Fragments,其他三个基本一样,只是arrayList中的items发生了变化,还有一些其他的小东西:
// ...Skipped some irrelevant code...
public class NumbersFragment extends Fragment {
private ArrayList<Word> mWords;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.word_list, container, false);
mWords = new ArrayList<>();
// ...Add all the items to the list...
// Make the adapter for the word items
WordAdapter adapter = new WordAdapter(getActivity(), mWords, R.color.category_numbers);
// Find the root view of the list
ListView listView = rootView.findViewById(R.id.root_list_view);
// Add adapter to the root list view
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("NumbersFragment", "CLICKED");
}
}
});
return rootView;
}
@Override
public void onPause() {
super.onPause();
Log.d("NumbersFragment", "Fragment paused");
}
}
这是类别适配器,它管理片段:
public class CategoryAdapter extends FragmentStateAdapter {
private static final int NUM_CATEGORIES = 4;
// Required public constructor
public CategoryAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull
@Override
public Fragment createFragment(int position) {
// Depending on which page the user is in,
// create a fragment of the corresponding category
switch (position) {
case 0:
return new NumbersFragment();
case 1:
return new FamilyFragment();
case 2:
return new ColorsFragment();
default:
return new PhrasesFragment();
}
}
@Override
public int getItemCount() {
return NUM_CATEGORIES;
}
}
这是我的 MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_main);
// Find the view pager that will allow the user to swipe between fragments
ViewPager2 viewPager = findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
CategoryAdapter adapter = new CategoryAdapter(this);
//or CategoryAdapter adapter = new CategoryAdapter(getSupportFragmentManager(), getLifecycle());
// Set the adapter into the view pager
viewPager.setAdapter(adapter);
}
}
在创建 viewpager
后在 MainActivityviewPager.setOffscreenPageLimit(3);
中添加这个
因为ViewPager的默认离屏限制为1,而ViewPager2的默认离屏限制为0。
在 ViewPager2 中,当您切换标签时,上一个标签将自动刷新。
在 ViewPager 中,如果您有 3 个或更多选项卡,当您自动切换到第 3 个选项卡时,第一个选项卡将被销毁,当您转到第 1 个选项卡时,它将被重新创建。
viewPager.setOffscreenPageLimit(3);
从这一行开始,当您切换到一个标签时,将预加载前 3 个标签,并预加载接下来的 3 个标签,因此不会刷新任何内容。