TableLayout+ViewPager+Fragment实现
2020-09-03 本文已影响0人
雷涛赛文
当前很多主流应用界面都是这样设计的,上面有许多tab,水平滑动会切换tab,tab下的页面也随之发生改变,典型的有今日头条,简书,知乎等。是如何实现的呢?前段时间研究了一下发现TabLayout可以完成这一职责,TabLayout提供了一个水平的布局用来展示Tabs,TabLayout一般都是配合Viewpager使用的,Viewpager里的Fragment随着顶部的Tab一起联动,将实现方式记录一下。
使用AndroidStudio4.0.1实现
1.在项目app下的Module中添加依赖
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.0'
2.布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tableLayout"
android:layout_width="412dp"
android:layout_height="76dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:tabMode="scrollable"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="395dp"
android:layout_height="644dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tableLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.主界面实现
public class MainActivity extends AppCompatActivity {
private TabLayout mTabLayout;
private ViewPager mViewPager;
private FragmentsAdapter mFragmentsAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mViewPager = findViewById(R.id.viewPager);
mTabLayout = findViewById(R.id.tableLayout);
//构造fragment adapter
mFragmentsAdapter = new FragmentsAdapter(getSupportFragmentManager());
//将adapter加载到viewpager里面
mViewPager.setAdapter(mFragmentsAdapter);
//设置预加载数量,提高显示效果体验
mViewPager.setOffscreenPageLimit(2);
//tablayout与viewpager联动
mTabLayout.setupWithViewPager(mViewPager);
}
}
3.1 FragmentPagerAdapter
//
//Source code recreated from a .class file by IntelliJ IDEA
//(powered by Fernflower decompiler)
//
public abstract class FragmentPagerAdapter extends PagerAdapter {
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurTransaction = null;
private Fragment mCurrentPrimaryItem = null;
protected FragmentPagerAdapter(FragmentManager fm) {
this.mFragmentManager = fm;
}
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
protected abstract Fragment getItem(int var1);
public void startUpdate(ViewGroup container) {
if (container.getId() == -1) {
throw new IllegalStateException("ViewPager with adapter " + this + " requires a view id");
}
}
@SuppressLint("CommitTransaction")
public Object instantiateItem(ViewGroup container, int position) {
if (this.mCurTransaction == null) {
this.mCurTransaction = this.mFragmentManager.beginTransaction();
}
long itemId = this.getItemId(position);
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = this.mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
this.mCurTransaction.attach(fragment);
} else {
fragment = this.getItem(position);
this.mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId));
}
if (fragment != this.mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
return fragment;
}
@SuppressLint("CommitTransaction")
public void destroyItem(ViewGroup container, int position, Object object) {
if (this.mCurTransaction == null) {
this.mCurTransaction = this.mFragmentManager.beginTransaction();
}
this.mCurTransaction.detach((Fragment) object);
}
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object;
if (fragment != this.mCurrentPrimaryItem) {
if (this.mCurrentPrimaryItem != null) {
this.mCurrentPrimaryItem.setMenuVisibility(false);
this.mCurrentPrimaryItem.setUserVisibleHint(false);
}
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
this.mCurrentPrimaryItem = fragment;
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
public void finishUpdate(ViewGroup container) {
if (this.mCurTransaction != null) {
this.mCurTransaction.commitNowAllowingStateLoss();
this.mCurTransaction = null;
}
}
public boolean isViewFromObject(View view, Object object) {
return ((Fragment) object).getView() == view;
}
public Parcelable saveState() {
return null;
}
public void restoreState(Parcelable state, ClassLoader loader) {
}
private long getItemId(int position) {
return (long) position;
}
}
3.2 FragmentAdapter 继承上述class,实现一些抽象方法
public class FragmentsAdapter extends FragmentPagerAdapter{
public FragmentsAdapter(FragmentManager fm) {
super(fm);
}
//返回tab对应的fragment
@Override
public Fragment getItem(int position) {
return FragmentsManager.getFragment(position);
}
//tab的数量
@Override
public int getCount() {
return FragmentsManager.getCount();
}
//tab对应的title,在setupWithViewPager(mViewPager)里面使用
/**for (int i = 0; i < adapterCount; i++) {
addTab(newTab().setText(pagerAdapter.getPageTitle(i)), false);
}*/
@Override
public CharSequence getPageTitle(int position) {
return FragmentsManager.getTitle(position);
}
}
3.3 FragmentsManager 管理fragment,供FragmentsAdapter调用
public class FragmentsManager {
//输入tab对应的title
private static List<String> DEFAULT_LIST = new ArrayList<>();
static {
DEFAULT_LIST.add("网格");
DEFAULT_LIST.add("网页");
DEFAULT_LIST.add("数据绑定");
DEFAULT_LIST.add("xml解析");
DEFAULT_LIST.add("画廊");
DEFAULT_LIST.add("自定义View");
DEFAULT_LIST.add("约束布局");
DEFAULT_LIST.add("JNI学习");
DEFAULT_LIST.add("Kotlin");
DEFAULT_LIST.add("Animator");
}
//tab对于的Fragment
public static Fragment getFragment(int position) {
switch (position) {
case 0:
return new MenuFragment();
case 1:
return new MouseFragment();
case 2:
return new KeyboardFragment();
case 3:
return new RemoteControlFragment();
case 4:
return new GalleryFragment();
case 5:
return new SelfDeterminedFragment();
case 6:
return new ConstraintFragment();
case 7:
return new JniFragment();
case 8:
return new KotlinFragment();
case 9:
return new AnimatorFragment();
default:
return null;
}
}
//tab的数量
public static int getCount() {
return DEFAULT_LIST.size();
}
@Override
public boolean equals(@Nullable Object obj) {
return super.equals(obj);
}
//tab的title
public static String getTitle(int index) {
return DEFAULT_LIST.get(index);
}
}
4.实现对应布局的Fragment,代码就不贴了
5.效果
![](https://img.haomeiwen.com/i24384115/4a7c2dbd77a31a8b.jpg)
![](https://img.haomeiwen.com/i24384115/c288693f8aafaa4b.jpg)