这一篇我们完成沙发页和启动页,以及沉浸式状态栏 看下UI,主要就是两部分组成,上面是个 简单解释下,分别是选中字体大小,正常字体大小,选中字体颜色,正常字体颜色,选中第几个,位置,标签,然后我们定义一个对应的 我们之前解析 接着我们就改造下我们的 我们如果不配置启动页的话,我们的 然后给我们的 接着我们在 OK,最后我们看下效果
前言
实现沙发页
TabLayout
,下面是个ViewPager
我们在做首页底部Tab
的时候用的是json
配置的,我们这个上面的TabLayout
也用一个json
来配置{ "activeSize": 16, "normalSize": 14, "activeColor": "#ED7282", "normalColor": "#666666", "select": 0, "tabGravity": 0, "tabs": [ { "title": "图片", "index": 0, "tag": "pics", "enable": true }, { "title": "视频", "index": 1, "tag": "video", "enable": true }, { "title": "文本", "index": 1, "tag": "text", "enable": true } ] }
JavaBean
public class SofaTab { /** * activeSize : 16 * normalSize : 14 * activeColor : #ED7282 * normalColor : #666666 * select : 0 * tabGravity : 0 * tabs : [{"title":"图片","index":0,"tag":"pics","enable":true},{"title":"视频","index":1,"tag":"video","enable":true},{"title":"文本","index":1,"tag":"text","enable":true}] */ public int activeSize; public int normalSize; public String activeColor; public String normalColor; public int select; public int tabGravity; public List<Tabs> tabs; public static class Tabs { /** * title : 图片 * index : 0 * tag : pics * enable : true */ public String title; public int index; public String tag; public boolean enable; } }
BottomBar
是在AppConfig
中做的,我们这个也在这里面获取沙发相关的Tab
public static SofaTab getSofaTabConfig() { if (sSofaTab == null) { String content = parseFile("sofa_tabs_config.json"); sSofaTab = JSON.parseObject(content, SofaTab.class); Collections.sort(sSofaTab.tabs, new Comparator<SofaTab.Tabs>() { @Override public int compare(SofaTab.Tabs o1, SofaTab.Tabs o2) { return o1.index < o2.index ? -1 : 1; } }); } return sSofaTab; }
fragment_sofa
这个布局文件,里面应该是有两个控件的<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto"> <data> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="@dimen/dp_45" app:tabGravity="center" app:tabIndicatorColor="@color/color_theme" app:tabIndicatorFullWidth="false" app:tabIndicatorHeight="@dimen/dp_2" app:tabInlineLabel="true" app:tabMode="scrollable" app:tabSelectedTextColor="@color/color_theme" app:tabTextColor="@color/color_333" app:tabUnboundedRipple="true" /> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" /> </LinearLayout> </layout>
TabLayout
的用法这里就不在多说了,这里就稍微说下这个ViewPager2
,这个可以算是 ViewPager
的升级版,内部使用的是RecycleView
实现类似ViewPager
的效果,同时也解决了ViewPager
预加载的问题,使用起来也很简单 //限制页面预加载 viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT); //viewPager2默认只有一种类型的Adapter。FragmentStateAdapter //并且在页面切换的时候 不会调用子Fragment的setUserVisibleHint ,取而代之的是onPause(),onResume()、 viewPager2.setAdapter(new FragmentStateAdapter(getChildFragmentManager(), this.getLifecycle()) { @NonNull @Override public Fragment createFragment(int position) { //这里不需要自己保管了,FragmentStateAdapter内部自己会管理已实例化的fragment对象。 return getTabFragment(position); } @Override public int getItemCount() { return tabs.size(); } }); tabLayout.setTabGravity(tabConfig.tabGravity); //viewPager2 就不能和再用TabLayout.setUpWithViewPager()了 //取而代之的是TabLayoutMediator。我们可以在onConfigureTab()方法的回调里面 做tab标签的配置 //其中autoRefresh的意思是:如果viewPager2 中child的数量发生了变化,也即我们调用了adapter#notifyItemChanged()前后getItemCount不同。 //要不要 重新刷野tabLayout的tab标签。视情况而定,像咱们sofaFragment的tab数量一旦固定了是不会变的,传true/false 都问题不大 mediator = new TabLayoutMediator(tabLayout, viewPager2, true, new TabLayoutMediator.TabConfigurationStrategy() { @Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) { tab.setCustomView(makeTabView(position)); } }); mediator.attach(); viewPager2.registerOnPageChangeCallback(mPageChangeCallback); //切换到默认选择项,那当然要等待初始化完成之后才有效 viewPager2.post(() -> viewPager2.setCurrentItem(tabConfig.select, false));
ViewPager2
里面默认的适配器只有一种FragmentStateAdapter
,相对于ViewPager
来说配合TabLayout
的使用方法有些不同,这里需要一个TabLayoutMediator
,对应的就是attach()
和detach()
方法,监听页面变化改为registerOnPageChangeCallback
,具体的详细使用可以参考下其他的文章,这里就不在赘述了public class SofaFragment extends Fragment { private FragmentSofaBinding binding; protected ViewPager2 viewPager2; protected TabLayout tabLayout; private SofaTab tabConfig; private ArrayList<SofaTab.Tabs> tabs; private TabLayoutMediator mediator; @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentSofaBinding.inflate(inflater, container, false); return binding.getRoot(); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { viewPager2 = binding.viewPager; tabLayout = binding.tabLayout; tabConfig = getTabConfig(); tabs = new ArrayList<>(); for (SofaTab.Tabs tab : tabConfig.tabs) { if (tab.enable) { tabs.add(tab); } } //限制页面预加载 viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT); //viewPager2默认只有一种类型的Adapter。FragmentStateAdapter //并且在页面切换的时候 不会调用子Fragment的setUserVisibleHint ,取而代之的是onPause(),onResume()、 viewPager2.setAdapter(new FragmentStateAdapter(getChildFragmentManager(), this.getLifecycle()) { @NonNull @Override public Fragment createFragment(int position) { //这里不需要自己保管了,FragmentStateAdapter内部自己会管理已实例化的fragment对象。 return getTabFragment(position); } @Override public int getItemCount() { return tabs.size(); } }); tabLayout.setTabGravity(tabConfig.tabGravity); //viewPager2 就不能和再用TabLayout.setUpWithViewPager()了 //取而代之的是TabLayoutMediator。我们可以在onConfigureTab()方法的回调里面 做tab标签的配置 //其中autoRefresh的意思是:如果viewPager2 中child的数量发生了变化,也即我们调用了adapter#notifyItemChanged()前后getItemCount不同。 //要不要 重新刷野tabLayout的tab标签。视情况而定,像咱们sofaFragment的tab数量一旦固定了是不会变的,传true/false 都问题不大 mediator = new TabLayoutMediator(tabLayout, viewPager2, true, new TabLayoutMediator.TabConfigurationStrategy() { @Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) { tab.setCustomView(makeTabView(position)); } }); mediator.attach(); viewPager2.registerOnPageChangeCallback(mPageChangeCallback); //切换到默认选择项,那当然要等待初始化完成之后才有效 viewPager2.post(() -> viewPager2.setCurrentItem(tabConfig.select, false)); } ViewPager2.OnPageChangeCallback mPageChangeCallback = new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { int tabCount = tabLayout.getTabCount(); for (int i = 0; i < tabCount; i++) { TabLayout.Tab tab = tabLayout.getTabAt(i); TextView customView = (TextView) tab.getCustomView(); if (tab.getPosition() == position) { customView.setTextSize(tabConfig.activeSize); customView.setTypeface(Typeface.DEFAULT_BOLD); } else { customView.setTextSize(tabConfig.normalSize); customView.setTypeface(Typeface.DEFAULT); } } } }; private View makeTabView(int position) { TextView tabView = new TextView(getContext()); int[][] states = new int[2][]; states[0] = new int[]{android.R.attr.state_selected}; states[1] = new int[]{}; int[] colors = new int[]{Color.parseColor(tabConfig.activeColor), Color.parseColor(tabConfig.normalColor)}; ColorStateList stateList = new ColorStateList(states, colors); tabView.setTextColor(stateList); tabView.setText(tabs.get(position).title); tabView.setTextSize(tabConfig.normalSize); return tabView; } public Fragment getTabFragment(int position) { return HomeFragment.newInstance(tabs.get(position).tag); } public SofaTab getTabConfig() { return AppConfig.getSofaTabConfig(); } @Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); List<Fragment> fragments = getChildFragmentManager().getFragments(); for (Fragment fragment : fragments) { if (fragment.isAdded() && fragment.isVisible()) { fragment.onHiddenChanged(hidden); break; } } } @Override public void onDestroy() { mediator.detach(); viewPager2.unregisterOnPageChangeCallback(mPageChangeCallback); super.onDestroy(); } }
实现启动页,消除白屏
App
启动的时候可能会有一会白屏,然后才会显示我们的内容,启动分冷启动
和热启动
,这种出现白屏一般都是冷启动
发生的,解决办法网上有很多,我们这里采用一种简单高效的方式
我们首先给我们的入口类Activity
配置一个特殊的主题,不使用默认的主题 <style name="launcher" parent="AppTheme"> <item name="android:windowFullscreen">true</item> <item name="android:windowBackground">@drawable/splash</item> </style>
MainActivity
设置主题 <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/launcher"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
MainActivity
的onCreate
方法中设置回正常的主题即可 @Override protected void onCreate(Bundle savedInstanceState) { //由于 启动时设置了 R.style.launcher 的windowBackground属性 //势必要在进入主页后,把窗口背景清理掉 setTheme(R.style.AppTheme); super.onCreate(savedInstanceState); ... }
实现沉浸式状态栏
public class StatusBar { /** * 6.0级以上的沉浸式布局 * * @param activity */ public static void fitSystemBar(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; Window window = activity.getWindow(); View decorView = window.getDecorView(); //View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN--能够使得我们的页面布局延伸到状态栏之下,但不会隐藏状态栏。也就相当于状态栏是遮盖在布局之上的 //View.SYSTEM_UI_FLAG_FULLSCREEN -- 能够使得我们的页面布局延伸到状态栏,但是会隐藏状态栏。 //WindowManager.LayoutParams.FLAG_FULLSCREEN decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.setStatusBarColor(Color.TRANSPARENT); } /** * 6.0及以上的状态栏色调 * * @param activity * @param light true:白底黑字,false:黑底白字 */ public static void lightStatusBar(Activity activity, boolean light) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; Window window = activity.getWindow(); View decorView = window.getDecorView(); int visibility = decorView.getSystemUiVisibility(); if (light) { visibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } else { visibility &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } decorView.setSystemUiVisibility(visibility); } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算