描述
Tabbar:就是每个app下方的那个东西。

实现
直接用三方Tab框架来弄Tabbar效果
添加依赖
1 2 3
|
implementation 'io.github.h07000223:flycoTabLayout:3.0.0'
|
xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" tools:context=".MainActivity">
<androidx.viewpager.widget.ViewPager android:id="@+id/list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" />
<include layout="@layout/divider_small" />
<com.flyco.tablayout.CommonTabLayout android:id="@+id/indicator" android:layout_width="match_parent" android:layout_height="@dimen/d55" android:background="?attr/colorTabBar" app:tl_iconHeight="@dimen/d20" app:tl_iconWidth="@dimen/d20" app:tl_indicator_color="?attr/colorPrimary" app:tl_indicator_height="0dp" app:tl_textSelectColor="?attr/colorPrimary" app:tl_textUnselectColor="?attr/colorOnSurface" app:tl_textsize="@dimen/s12" app:tl_underline_color="#DDDDDD" app:tl_underline_height="0dp" /> </LinearLayout>
|
分割线:
1 2 3 4 5 6 7 8
| <?xml version="1.0" encoding="utf-8"?> <View xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/divider_small" android:layout_width="match_parent" android:layout_height="@dimen/d0_5" android:background="?attr/colorDivider">
</View>
|
?attr/colorTabBar : 就是新建一个attr专门做属性值。
就像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="colorLightWhite" format="color" />
<attr name="colorDivider" format="color" />
<attr name="colorTabBar" format="color" />
<attr name="colorToolbar" format="color" />
<attr name="colorSlideBackground" format="color" />
<attr name="colorSurfaceClick" format="color" /> </resources>
|
但是这里没有值,值在对应的theme文件中。
这样处理的好处是:适配深色模式。
theme文件就不贴了,自己去项目里看
初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class MainActivity extends BaseViewModelActivity<ActivityMainBinding> { private static final int[] indicatorTitles = new int[]{R.string.discovery, R.string.video,R.string.feed,R.string.me}; private static final int[] indicatorIcons = new int[]{R.drawable.discovery, R.drawable.video,R.drawable.feed,R.drawable.me}; private static final int[] indicatorSelectedIcons = new int[]{R.drawable.discovery_selected, R.drawable.video_selected,R.drawable.feed_selected,R.drawable.me_selected};
@Override protected void initViews() { super.initViews(); SuperStatusBarUtil.myStatusBar(getHostActivity());
binding.list.setOffscreenPageLimit(4);
ArrayList<CustomTabEntity> indicatorTabs = new ArrayList<>(); for (int i = 0; i < indicatorTitles.length; i++) { indicatorTabs.add( new TabEntity( getString(indicatorTitles[i]), indicatorSelectedIcons[i], indicatorIcons[i] ) ); } binding.indicator.setTabData(indicatorTabs);
binding.indicator.showMsg(3,100); } @Override protected void initDatum() { super.initDatum(); ......
adapter = new MainAdapter(getHostActivity(), getSupportFragmentManager()); binding.list.setAdapter(adapter);
adapter.setDatum(Arrays.asList(0, 1, 2, 3));
} }
|
这里的TabEntity要自己建立一下,其实就是TabBar哪里的演示布局是怎样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import com.flyco.tablayout.listener.CustomTabEntity;
public class TabEntity implements CustomTabEntity {
public String title;
public int selectedIcon;
public int unSelectedIcon;
public TabEntity(String title, int selectedIcon, int unSelectedIcon) { this.title = title; this.selectedIcon = selectedIcon; this.unSelectedIcon = unSelectedIcon; }
@Override public String getTabTitle() { return title; }
@Override public int getTabSelectedIcon() { return selectedIcon; }
@Override public int getTabUnselectedIcon() { return unSelectedIcon; } }
|
这个时候就是下面的那个TabBar就出来了。但是我们的TabBar是为了和ViewModel配合使用的。
Fragments
DiscoveryFragment,VideoFragment,MeFragment,FeedFragment
自己创建出来,然后重写newInstance方法。
继承BaseViewModelFragment其实就两行代码。
ViewPage适配器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import android.content.Context;
import androidx.annotation.NonNull; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter;
import java.util.ArrayList; import java.util.List;
public abstract class BaseFragmentStatePagerAdapter<T> extends FragmentStatePagerAdapter { protected final Context context; protected List<T> datum = new ArrayList<>();
public BaseFragmentStatePagerAdapter(Context context, @NonNull FragmentManager fm) { super(fm); this.context = context; }
@Override public int getCount() { return datum.size(); }
public T getData(int position) { return datum.get(position); }
public void setDatum(List<T> datum) { if (datum != null && datum.size() > 0) { this.datum.clear(); this.datum.addAll(datum);
notifyDataSetChanged(); } } }
|
MainAdapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import android.content.Context;
import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager;
import com.example.testandroid.adapter.BaseFragmentStatePagerAdapter; import com.example.testandroid.component.main.fragment.DiscoveryFragment; import com.example.testandroid.component.main.fragment.FeedFragment; import com.example.testandroid.component.main.fragment.MeFragment; import com.example.testandroid.component.main.fragment.VideoFragment;
import io.reactivex.rxjava3.annotations.NonNull;
public class MainAdapter extends BaseFragmentStatePagerAdapter<Integer> {
public MainAdapter(Context context, @NonNull FragmentManager fm) { super(context, fm); }
@NonNull @Override public Fragment getItem(int position) { switch (position) { case 1: return VideoFragment.newInstance(); case 2: return FeedFragment.newInstance(); case 3: return MeFragment.newInstance(); default: return DiscoveryFragment.newInstance(); } } }
|
这里的getItem就是返回对应的ViewPage里面的Fragment。记住别把顺序搞乱了。
indicator和ViewPage配合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Override protected void initListeners() { super.initListeners(); binding.indicator.setOnTabSelectListener(new OnTabSelectListener() { @Override public void onTabSelect(int position) { binding.list.setCurrentItem(position); }
@Override public void onTabReselect(int position) {
} });
binding.list.addOnPageChangeListener(new onPageChangeListenerAdapter(){ @Override public void onPageSelected(int position) { super.onPageSelected(position); binding.indicator.setCurrentTab(position); } }); }
|
这个地方的 onPageChangeListenerAdapter 我们包了一层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import androidx.viewpager.widget.ViewPager;
public class onPageChangeListenerAdapter implements ViewPager.OnPageChangeListener { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override public void onPageSelected(int position) {
}
@Override public void onPageScrollStateChanged(int state) {
} }
|
不然我们是直接继承 Viewpager.OnPageChangeListener
这样包一层的好处是:就不用四个方法哪怕不用也要写出来。
MainActivity 就更加的简洁。
其实那个指示器也可以包:OnTabSelectListener
但是ViewPage这个适用面大我们包。指示器不多就不包了。
总结