先看效果
简单分析一下,顶部是一个RadioGroup,主要是用来切换当前显示的数据类型,可以点击“列表”、“表格”两个RadioButton实现切换类型,也可以通过左右滑动页面,再加上本来两个Fragment中展示的RecyclerView,构成了本文中将要讲解的UI效果,文末附带demo源码
1.gradle文件中引用Viewpagger2
implementation 'androidx.viewpager2:viewpager2:1.0.0'
2.代码结构,如下图
1)adapter包中为抽象出来的一个公共适配器,后续代码中会展示相关使用;
2)DataBean为列表中展示的数据实体,只有一个string对象,如下;
public class DataBean {
public String index;
public DataBean(String index) {
this.index = index;
}
}
3)MainActivity为主界面、ListFragment与GridFragment分别为两个fragment;
4)布局文件顾名思义,item_list与item_grid分别为列表和网格列表的子项布局;
关键代码展示:
1.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rbList"
style="@style/RadioButtonCheckText"
android:text="列表" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#ababab" />
<RadioButton
android:id="@+id/rbGrid"
style="@style/RadioButtonCheckText"
android:text="表格" />
</RadioGroup>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#ababab" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPagger"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
2.fragment_list、fragment_grid页面的布局是类似的,只展示一个
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3.item_list、item_grid的布局也类似,只展示一个
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="80dp" android:focusable="true" android:orientation="vertical"> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="80dp" android:gravity="center" android:text="表格1" android:textColor="@drawable/item_click_text_color_selector" /> </LinearLayout>
注:item_click_text_color_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#4ba2ff" android:state_pressed="true" />
<item android:color="#333333" android:state_pressed="false" />
</selector>
4.ListFragment、GridFragment代码相似,只展示一个
public class ListFragment extends Fragment {
private FragmentListBinding binding;
private CommonAdapter<DataBean> commonAdapter;
private List<DataBean> lists = new ArrayList<>();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentListBinding.inflate(LayoutInflater.from(getActivity()));
lists.clear();
for (int i = 0; i < 20; i++) {
lists.add(new DataBean("列表" + i));
}
initAdapter();
return binding.getRoot();
}
private void initAdapter() {
binding.recycler.setLayoutManager(new LinearLayoutManager(getActivity()));
commonAdapter = new CommonAdapter<DataBean>(getActivity(),
R.layout.item_list, lists) {
@Override
public void convert(CommonViewHolder holder, DataBean bean, int position) {
holder.setText(R.id.text, bean.index);
holder.setOnClickListener(R.id.text, view -> {
Toast.makeText(getActivity(), "点击了:" + bean.index, Toast.LENGTH_SHORT).show();
});
}
@Override
public void footConvert(CommonViewHolder holder, int size) {
}
};
binding.recycler.setAdapter(commonAdapter);
binding.recycler.setItemAnimator(new DefaultItemAnimator());
}
}
5.MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private FragmentStateAdapter mFragmentAdapter;
private ViewPager2.OnPageChangeCallback mOnPageChangeCallback = new MyOnPageChangeCallback();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mFragmentAdapter = new PageAdapter(this);
binding.viewPagger.setAdapter(mFragmentAdapter);
binding.radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.rbList) {
binding.viewPagger.setCurrentItem(0);
} else if (checkedId == R.id.rbGrid) {
binding.viewPagger.setCurrentItem(1);
}
});
binding.radioGroup.check(R.id.rbList);
}
@Override
protected void onStart() {
super.onStart();
binding.viewPagger.registerOnPageChangeCallback(mOnPageChangeCallback);
}
@Override
protected void onStop() {
super.onStop();
binding.viewPagger.unregisterOnPageChangeCallback(mOnPageChangeCallback);
}
class PageAdapter extends FragmentStateAdapter {
public PageAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull
@Override
public Fragment createFragment(int position) {
Fragment listFragment = new ListFragment();
Fragment gridFragment = new GridFragment();
if (0 == position) {
return listFragment;
} else {
return gridFragment;
}
}
@Override
public int getItemCount() {
return 2;
}
}
class MyOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
@Override
public void onPageSelected(int position) {
switch (position) {
case 0:
binding.radioGroup.check(R.id.rbList);
break;
case 1:
binding.radioGroup.check(R.id.rbGrid);
break;
default:
break;
}
}
}
}
关键代码:
class PageAdapter extends FragmentStateAdapter { public PageAdapter(@NonNull FragmentActivity fragmentActivity) { super(fragmentActivity); } @NonNull @Override public Fragment createFragment(int position) { Fragment listFragment = new ListFragment(); Fragment gridFragment = new GridFragment(); if (0 == position) { return listFragment; } else { return gridFragment; } } @Override public int getItemCount() { return 2; } }
Viewpagger与fragment通过继承FragmentStateAdapter来实现,通过重写createFragment方法,将对应的Fragment引用返回给Viewpagger。