Skip to content
Aries Hoo²⁰¹⁹ edited this page Mar 26, 2019 · 22 revisions

概述

FastLib 是一个整合了常用主流开源项目的 Android 快速搭建UI库, 其中包含 RetrofitRxJavaRxAndroidRxLifecycle等三方库, 并且提供较多的基础ActivityFragment如快速搭建微信类tab+fragmentFastMainActivity、快速搭建包含TitleBar的FastTitleActivityFastTitleFragment、快速搭建列表刷新的FastRefreshLoadActivityFastRefreshLoadFragment;并提供快速配置Retrofit相关功能的FastRetrofit:解决添加统一请求header多url等常见功能。

FastLib 只是一个快速搭建UI及网络请求的库,是常用三方库的一个封装集合,本身不具备框架特性。可在此基础上做MVP、MVVM等框架的扩展

该wiki是基于FastLib 2.2.12Android Studio 3.3.1Gradle 4.10.1版本编写,后期重大变更会同步更新。

主要功能

  • 基于Retrofit2.xRxJava2.x的网络请求封装、网络请求与生命周期绑定、快速观察者、快速loading观察者、快速返回常用错误
  • 常用功能库二次封装方便调用:Glide加载图片封装GlideManagerTabLayout+ViewPager Fragment切换封装TabLayoutManagerLogger日志打印封装LoggerManager
  • 多种常用界面布局:标题+多状态+下拉刷新+列表标题+ViewPager等方便快速创建常用布局增加layout复用
  • Fragment 懒加载封装
  • 快速实现Activity滑动返回下拉刷新+自动加载更多沉浸式状态栏+导航栏
  • 解决一些老大难问题:Tab+Fragment 当Activity回收后Fragment 重叠-FastMainActivity软键盘无法弹起-KeyboardHelper状态栏文字转换-StatusBarUtil不同Fragment切换状态栏文字颜色变换-BasisFragment+StatusBarUtilAndroid 7.0 fileprovider-FastFileUtilAndroid 9.0 network security policy问题
  • 提供众多常用工具类:ToastUtil-统一样式吐司FastFormatUtil-快速格式化时间、内存字节单位、double类型小数点保留几位SizeUtil-尺寸转换屏幕宽高获取SPUtil-暂存数据

包结构

包结构

三方库一览

  1. RetrofitSquare出品的网络请求库,极大的减少了 Http 请求的代码和步骤
  2. RxJava 提供优雅的响应式 API 解决异步请求以及事件处理
  3. RxAndroid 为 Android 提供响应式 API
  4. Rxlifecycle,在 Android 上使用 RxJava 都知道的一个坑,就是生命周期的解除订阅,这个框架通过绑定 Activity 和 Fragment 的生命周期完美解决该问题
  5. Okhttp 同样 Square 出品,不多介绍,做 Android 的都应该知道
  6. GsonGoogle 官方的 Json Convert 框架
  7. ButterknifeJakeWharton 大神出品的 View 注入框架
  8. AndroidEventBus 是一个轻量级的 EventBus,提供TAG支持
  9. Loggerorhanobut 出品的 Log 框架,FastLib提供相关封装类LoggerManager
  10. GlideGoogle推荐的图片加载库,FastLib提供相关封装类GlideManager
  11. BaseRecyclerViewAdapterHelper陈宇明封装的RecyclerView 适配器帮助类
  12. SmartRefreshLayoutscwang90封装的刷新库,扩展性很强
  13. AgentWebJustson封装的原生WebView库,使用方便扩展性很强
  14. BGASwipeBackLayoutbingoogolapple-王浩封装的微信效果的Activity滑动返回库
  15. StatusLayoutManagerBakumon封装的多状态控制管理工具,方便实现加载中、加载失败、网络错误等状态
  16. TabLayoutAriesHoo forked from FlycoTabLayout并加以优化调整的主界面tab、滑动tab、分段选择器tab功能库
  17. UIWidgetAriesHoo 封装的常用UI库(TitleBarView、RadiusView、StatusViewHelper、NavigationViewHelper等)

一、开发准备

  • 1、开发者需要具有一定的 Android 开发能力,以及自我解决问题的能力
  • 2、开发者需对 Retrofit2.xRxJava2.x 有一定了解,至少项目中使用过
  • 3、本库建议直接使用 Gradle 远程依赖, 框架已经提供了很多用于扩展的接口, 足以满足日常需求
  • 4、多看注释FastLib注释还是很多的,每个类更新记录得也较详细
  • 5、注意解决Androidxsupport包不能共存问题-建议可以使用Android Studio 带的Refactor->Migrate to AndroidX功能
  • 6、本库是笔者业余时间开发、在自己项目中也在使用,会及时的更新和维护。如有使用过程BUG请先参看issus没有解决的提交新issue ,提交中一定要说明使用版本,能提交使用代码最佳

1.1 Gradle配置

FastLib本身以及FastLib使用的部分三方库是通过JitPack发布打包,故在gradle需进行相关设置,否则无法下载 compileSdkVersionandroix-原support 版本配置也放在gradle下边,网上也有单独设置config.gradle方式,这里不做限制看个人喜好

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.1'//以3.3.1为例
        //classpath 'com.android.tools.build:gradle:x.y.z' 
    }
}

allprojects {
    repositories {
        jcenter()
        google() //AndroidStudio v3.0 可以使用 google() 替代 maven { url "https://maven.google.com" }
        maven { url "https://jitpack.io" }//FastLib 及部分三方库通过JitPack发布需添加才可依赖
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

ext{
    compileSdkVersion = 28
    minSdkVersion = 21
    targetSdkVersion = 28
    supportVersion = "1.0.0"
    versionCode = 239
    versionName = "2.2.12"
}

1.2 导入FastLib 及三方库

FastLib部分库使用compileOnly模式引入,故项目需根据实际情况implementation 其它库如RxJavaRetrofitOkhttpRxLifecycleFastLib 直接以api 模式引入开发者无需再次引入

dependencies {
    implementation 'com.github.AriesHoo:FastLib:2.2.12'

   //以下库FastLib里使用compileOnly只是编译,使用时需根据项目选择相应版本
    implementation 'com.google.android.material:material:'.concat(supportVersion)
    implementation 'androidx.appcompat:appcompat:'.concat(supportVersion)
    implementation 'androidx.recyclerview:recyclerview:'.concat(supportVersion)
    //万能适配器--一般都需要吧
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.45-androidx'
    //webView库 继承FastWebActivity需要,不需要内置WebView可以不implementation
    implementation 'com.just.agentweb:agentweb:4.0.2'
    //webView提供下载功能
    implementation 'com.just.agentweb:download:4.0.2'
    //下拉刷新库注意刷新头SmartRefreshHeader版本最好对应尤其头版本不要低于SmartRefreshLayout版本
    implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.5.1'
    //Glide图片加载
    implementation 'com.github.bumptech.glide:glide:4.8.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
    //以上库library里使用compileOnly只是编译,使用时需根据项目选择相应版本
}

1.3 Lambda配置

Lambda支持需在 应用的gradle android节点下配置java版本否则使用Retrofit可能出现异常 Android Studio 3.0 (兼容 Java8, 默认支持 Lambda, 但需手动指定 targetCompatibility)

android {
    //其它配置
    defaultConfig {
       //默认配置
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
   //其它配置
}

Android Studio 3.0以下版本需要在项目根目录build.gradle 中依赖 Lambda插件

buildscript {
    dependencies {
        //classpath 'com.android.tools.build:gradle:x.y.z'//lambda
        classpath 'me.tatarka:gradle-retrolambda:3.7.0'
    }
}

appbuild.gradle 中引入 Lambda 插件

apply plugin: 'me.tatarka.retrolambda'

android {
    //其它配置
    defaultConfig {
       //默认配置
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
   //其它配置
}

二、初始化

FastLib默认实现了不少初始化工作,包括日志打印 LoggerManagerGlideManager等,但为了设置app的独特风格还是需要开发者做一些初始化动作

2.1 LoggerManager初始化

主要提供三个配置参数tagisDebugbuilder,分别设置log的标签、是否打印log、Logger的配置 PrettyFormatStrategy.Builder 一般在应用的Application类onCreate初始化即可

//初始化Logger日志打印
 LoggerManager.init(TAG, BuildConfig.DEBUG);

如需更细致配置即可调用传入PrettyFormatStrategy.Builder

 //初始化Logger日志打印
   LoggerManager.init(TAG, BuildConfig.DEBUG,
           PrettyFormatStrategy.newBuilder()
                   .methodOffset(0)
                   .showThreadInfo(true)
                   .methodCount(3));

当然其实开发者也是可以不用初始化的、在调用具体日志打印时会默认初始化,但TAG或设置成当前类名且始终打印日志,实际开发情况多半在debug开发模式时开启日志方便调试、正式打包release时关闭log,故还是建议开发者初始化下

2.2 FastManager初始化

FastManager主要初始化TitleBarView样式 、Toast样式、SwipeBack样式、Glide占位样式、Loading Dialog全局等待样式等UI相关;

2.2.1 最简初始化

 //最简单UI配置模式-必须进行初始化
  FastManager.init(this);
  • 1、开发者最简必须调用以上方法进行初始化,FastLib会内部实现默认效果、默认效果取自fast_colors.xmlfast_dimens.xmlfast_strings.xml 配置
  • 2、开发者可将fast_colors.xmlfast_dimens.xmlfast_strings.xml 复制进app的values下进行部分参数的修改以达到UI自定义效果

2.2.2 详细初始化

如开发者不喜欢修改fast_colors.xmlfast_dimens.xmlfast_strings.xml 参数配置 FastLib提供多个接口回调方法开发者统一处理 FastLib提供方式是注册监听、类似观察者模式,当程序执行到具体流程才会回调执行具体代码。故不要说什么 “Application 执行这么多代码,应用得不得卡,得不得ANR” 类似的

        //最简单UI配置模式-必须进行初始化
        FastManager.init(this);
        //以下为更丰富自定义方法
        //全局UI配置参数-按需求设置
        AppImpl impl = new AppImpl(mContext);
        ActivityControlImpl activityControl = new ActivityControlImpl();
        FastManager.getInstance()
                //设置Adapter加载更多视图--默认设置了FastLoadMoreView
                .setLoadMoreFoot(impl)
                //全局设置RecyclerView
                .setFastRecyclerViewControl(impl)
                //设置RecyclerView加载过程多布局属性
                .setMultiStatusView(impl)
                //设置全局网络请求等待Loading提示框如登录等待loading--观察者必须为FastLoadingObserver及其子类
                .setLoadingDialog(impl)
                //设置SmartRefreshLayout刷新头-自定加载使用BaseRecyclerViewAdapterHelper
                .setDefaultRefreshHeader(impl)
                //设置全局TitleBarView相关配置
                .setTitleBarViewControl(impl)
                //设置Activity滑动返回控制-默认开启滑动返回功能不需要设置透明主题
                .setSwipeBackControl(new SwipeBackControlImpl())
                //设置Activity/Fragment相关配置(横竖屏+背景+虚拟导航栏+状态栏+生命周期)
                .setActivityFragmentControl(activityControl)
                //设置BasisActivity 子类按键监听
                .setActivityKeyEventControl(activityControl)
                //配置BasisActivity 子类事件派发相关
                .setActivityDispatchEventControl(activityControl)
                //设置http请求结果全局控制
                .setHttpRequestControl(new HttpRequestControlImpl())
                //设置主页返回键控制-默认效果为2000 毫秒时延退出程序
                .setQuitAppControl(impl)
                //设置ToastUtil全局控制
                .setToastControl(impl);

2.2.3 Activity滑动返回SwipeBackLayout设置

  • 1、该功能依赖BGASwipeBackLayout-Android,可不用应用主题设置 true ,虽说加上属性效果更佳,但是会引起两个情况 (一)、targetSdk设置成27及以上如果Activity有设置屏幕横竖屏操作会造成应用崩溃 Only fullscreen activities can request orientation (二)、 快速点击跳转页面相关按钮一定概率显示系统桌面 ;开发者自行决定
  • 2、FastLib注册生命周期回调并在onActivityCreated回调进行相关设置,故可以对其它三方库里的Activity实现相同滑动返回效果
  • 3、回调中传递Activity对象,开发者也可通过该对象过滤掉你不想执行的操作
  • 4、如果整个应用不想使用滑动返回功能isSwipeBackEnable return false即可
   /**
     * 设置当前Activity是否支持滑动返回(用于控制是否添加一层{@link BGASwipeBackLayout})
     * 返回为true {@link #setSwipeBack(Activity, BGASwipeBackHelper)}才有设置的意义
     *
     * @param activity
     * @return
     */
    @Override
    public boolean isSwipeBackEnable(Activity activity) {
        return true;
    }

    /**
     * 设置Activity 全局滑动属性--包括三方库
     *
     * @param activity
     * @param swipeBackHelper BGASwipeBackHelper 控制详见{@link com.aries.library.fast.FastManager}
     */
    @Override
    public void setSwipeBack(Activity activity, BGASwipeBackHelper swipeBackHelper) {
        //以下为默认设置
        //需设置activity window背景为透明避免滑动过程中漏出背景也可减少背景层级降低过度绘制
        activity.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
        swipeBackHelper.setSwipeBackEnable(true)
                .setShadowResId(R.color.colorSwipeBackBackground)
                //底部导航条是否悬浮在内容上设置过NavigationViewHelper可以不用设置该属性
                .setIsNavigationBarOverlap(App.isControlNavigation());
    }

    /**
     * 正在滑动返回
     *
     * @param activity    滑动的Activity
     * @param slideOffset 滑动偏移量 0-1
     */
    @Override
    public void onSwipeBackLayoutSlide(Activity activity, float slideOffset) {

    }

    /**
     * 没达到滑动返回的阈值,取消滑动返回动作,回到默认状态
     *
     * @param activity 当前Activity
     */
    @Override
    public void onSwipeBackLayoutCancel(Activity activity) {

    }

     /**
     * 滑动返回执行完毕,销毁当前 Activity
     *
     * @param activity 当前activity
     */
    @Override
    public void onSwipeBackLayoutExecuted(Activity activity) {

    }

2.2.4 标题栏TitleBarView设置

  • 1、该功能依赖UIWidget:widget-core库,TitleBarView支持左、右文字图标、主副标题 跑马灯、自定义左、中、右View功能,默认支持沉浸式及状态栏文字颜色
  • 2、回调了TitleBarView对象及TitleBarView所在Class,可设置统一属性及根据Class做差异化
   /**
     * 控制全局TitleBarView
     *
     * @param titleBar
     * @return
     */
    @Override
    public boolean createTitleBarViewControl(TitleBarView titleBar, Class<?> cls) {
        //默认的MD风格返回箭头icon如使用该风格可以不用设置
        Drawable mDrawable = FastUtil.getTintDrawable(ContextCompat.getDrawable(mContext, R.drawable.fast_ic_back),
                ContextCompat.getColor(mContext, R.color.colorTitleText));
        //是否支持状态栏白色
        boolean isSupport = StatusBarUtil.isSupportStatusBarFontChange();
        boolean isActivity = Activity.class.isAssignableFrom(cls);
        Activity activity = FastStackUtil.getInstance().getActivity(cls);
        //设置TitleBarView 所有TextView颜色
        titleBar.setStatusBarLightMode(isSupport)
                //不支持黑字的设置白透明
                .setStatusAlpha(isSupport ? 0 : 102)
                .setLeftTextDrawable(isActivity ? mDrawable : null)
                .setDividerHeight(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? SizeUtil.dp2px(0.5f) : 0);
        if (activity != null) {
            titleBar.setTitleMainText(activity.getTitle());
        }
        ViewCompat.setElevation(titleBar, mContext.getResources().getDimension(R.dimen.dp_elevation));
        return false;
    }

2.2.5 下拉刷新头SmartRefreshLayout设置

  • 1、该功能依赖SmartRefreshLayout库,回调中携带SmartRefreshLayout对象,可以设置其它丰富属性
  • 2、SmartRefreshLayout库拥有多种官方刷新头,如需特殊定制,参看自定义Header
   /**
     * 下拉刷新头配置
     *
     * @param context
     * @param layout
     * @return
     */
    @NonNull
    @Override
    public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
        layout.setEnableHeaderTranslationContent(false)
                .setEnableOverScrollDrag(false);
        MaterialHeader materialHeader = new MaterialHeader(mContext);
        materialHeader.setColorSchemeColors(ContextCompat.getColor(mContext, R.color.colorTextBlack),
                ContextCompat.getColor(mContext, R.color.colorTextBlackLight));
        return materialHeader;
    }

2.2.6 Adapter 加载更多BaseQuickAdapter设置

  • 1、该功能依赖BaseRecyclerViewAdapterHelper库,回调中携带BaseQuickAdapter对象可以设置其它统一属性,如加载动画
  • 2、FastLib自定义FastLoadMoreView扩展原库LoadMoreView支持属性自定义
   /**
     * Adapter加载更多配置
     *
     * @param adapter
     * @return
     */
    @Nullable
    @Override
    public LoadMoreView createDefaultLoadMoreView(BaseQuickAdapter adapter) {
        if (adapter != null) {
            //设置动画是否一直开启
            adapter.isFirstOnly(false);
            //设置动画
            adapter.openLoadAnimation(BaseQuickAdapter.SCALEIN);
        }
        //方式一:设置FastLoadMoreView--可参考FastLoadMoreView.Builder相应set方法
        //默认配置请参考FastLoadMoreView.Builder(mContext)里初始化
        return new FastLoadMoreView.Builder(mContext)
                .setLoadingTextFakeBold(true)
                .setLoadingSize(SizeUtil.dp2px(20))
                                //.setLoadTextColor(Color.MAGENTA)
                                //设置Loading 颜色-5.0以上有效
                                //.setLoadingProgressColor(Color.MAGENTA)
                                //设置Loading drawable--会使Loading颜色失效
                                //.setLoadingProgressDrawable(R.drawable.dialog_loading_wei_bo)
                                //设置全局TextView颜色
                                //.setLoadTextColor(Color.MAGENTA)
                                //设置全局TextView文字字号
                                //.setLoadTextSize(SizeUtil.dp2px(14))
                                //.setLoadingText("努力加载中...")
                                //.setLoadingTextColor(Color.GREEN)
                                //.setLoadingTextSize(SizeUtil.dp2px(14))
                                //.setLoadEndText("我是有底线的")
                                //.setLoadEndTextColor(Color.GREEN)
                                //.setLoadEndTextSize(SizeUtil.dp2px(14))
                                //.setLoadFailText("哇哦!出错了")
                                //.setLoadFailTextColor(Color.RED)
                                //.setLoadFailTextSize(SizeUtil.dp2px(14))
                .build();
                      //方式二:使用adapter自带--其实我默认设置的和这个基本一致只是提供了相应设置方法
                       // return new SimpleLoadMoreView();
                      //方式三:参考SimpleLoadMoreView或FastLoadMoreView完全自定义自己的LoadMoreView
                      //return MyLoadMoreView();
    }

2.2.7 RecyclerView 设置

该功能主要针对通过FastRefreshLoadDelegate代理RecyclerView的Activity/Fragment,FastLibFastRefreshLoadActivityFastRefreshLoadFragment,为方便统一设置RecyclerView及一些特殊处理;其实在生命周期里通过findViewByIdFindViewUtil找到对应RecyclerView 作处理亦可

    @Override
    public void setRecyclerView(RecyclerView recyclerView, Class<?> cls) {
        recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
        recyclerView.setNestedScrollingEnabled(false);
    }

2.2.8 多状态布局MultiStatusView设置

该功能依赖StatusLayoutManager库,用于设置多状态各状态layout,如不设置则使用StatusLayoutManager默认布局

   /**
     * 设置全局多状态布局
     *
     * @param statusView
     * @param iFastRefreshLoadView
     */
    @Override
    public void setMultiStatusView(StatusLayoutManager.Builder statusView, IFastRefreshLoadView iFastRefreshLoadView) {
        statusView.setLoadingLayout(R.layout.layout_multi_loading)
                .setEmptyLayout(R.layout.layout_multi_empty)
                .setEmptyClickViewID(R.id.rtv_retryMultiEmpty)
                .setErrorLayout(R.layout.layout_multi_error)
                .setErrorClickViewID(R.id.rtv_retryMultiError)
                .setDefaultLayoutsBackgroundColor(Color.TRANSPARENT);
    }

2.2.9 网络请求成功/失败结果处理

  • 1、请求成功主要用于实现 IFastRefreshLoadView 接口通过 FastRefreshLoadDelegate 代理的 FastRefreshLoadActivityFastRefreshLoadFragment 用于列表数据加载成功后相关统一逻辑处理,并在成功回调 _onNext 调用 FastManager.getInstance().getHttpRequestControl().httpRequestSuccess(IHttpRequestControl httpRequestControl, List<?> list, OnHttpRequestListener listene); 方可全局处理;目前想到这种全局处理方式
  • 2、请求失败需在 RxJava subscribe使用 FastObserverFastLoadingObserver ,如列表请求如 FastRefreshLoadActivityFastRefreshLoadFragment 子类需传递 IHttpRequestControl 可处理多布局等
  • 3、如开发者自定自定义 subscribe ,只需参看 FastObserverFastLoadingObserveronErrorThrowable 调用 FastManager.getInstance().getHttpRequestControl().httpRequestError(mHttpRequestControl, e); 即可全局处理异常信息
 @Override
    public void httpRequestSuccess(IHttpRequestControl httpRequestControl, List<?> list, OnHttpRequestListener listener) {
        if (httpRequestControl == null) {
            return;
        }
        SmartRefreshLayout smartRefreshLayout = httpRequestControl.getRefreshLayout();
        BaseQuickAdapter adapter = httpRequestControl.getRecyclerAdapter();
        StatusLayoutManager statusLayoutManager = httpRequestControl.getStatusLayoutManager();
        int page = httpRequestControl.getCurrentPage();
        int size = httpRequestControl.getPageSize();

        LoggerManager.i(TAG, "smartRefreshLayout:" + smartRefreshLayout + ";adapter:" + adapter + ";status:" + ";page:" + page + ";class:" + httpRequestControl.getRequestClass());
        if (smartRefreshLayout != null) {
            smartRefreshLayout.finishRefresh();
        }
        if (adapter == null) {
            return;
        }
        adapter.loadMoreComplete();
        if (list == null || list.size() == 0) {
            //第一页没有
            if (page == 0) {
                adapter.setNewData(new ArrayList());
                statusLayoutManager.showEmptyLayout();
                if (listener != null) {
                    listener.onEmpty();
                }
            } else {
                adapter.loadMoreEnd();
                if (listener != null) {
                    listener.onNoMore();
                }
            }
            return;
        }
        statusLayoutManager.showSuccessLayout();
        if (smartRefreshLayout.isRefreshing() || page == 0) {
            adapter.setNewData(new ArrayList());
        }
        adapter.addData(list);
        if (listener != null) {
            listener.onNext();
        }
        if (list.size() < size) {
            adapter.loadMoreEnd();
            if (listener != null) {
                listener.onNoMore();
            }
        }
    }

    @Override
    public void httpRequestError(IHttpRequestControl httpRequestControl, Throwable e) {
        int reason = R.string.fast_exception_other_error;
//        int code = FastError.EXCEPTION_OTHER_ERROR;
        if (!NetworkUtil.isConnected(App.getContext())) {
            reason = R.string.fast_exception_network_not_connected;
        } else {
            //网络异常--继承于AccountsException
            if (e instanceof NetworkErrorException) {
                reason = R.string.fast_exception_network_error;
                //账户异常
            } else if (e instanceof AccountsException) {
                reason = R.string.fast_exception_accounts;
                //连接异常--继承于SocketException
            } else if (e instanceof ConnectException) {
                reason = R.string.fast_exception_connect;
                //socket异常
            } else if (e instanceof SocketException) {
                reason = R.string.fast_exception_socket;
                // http异常
            } else if (e instanceof HttpException) {
                reason = R.string.fast_exception_http;
                //DNS错误
            } else if (e instanceof UnknownHostException) {
                reason = R.string.fast_exception_unknown_host;
            } else if (e instanceof JsonSyntaxException
                    || e instanceof JsonIOException
                    || e instanceof JsonParseException) {
                //数据格式化错误
                reason = R.string.fast_exception_json_syntax;
            } else if (e instanceof SocketTimeoutException || e instanceof TimeoutException) {
                reason = R.string.fast_exception_time_out;
            } else if (e instanceof ClassCastException) {
                reason = R.string.fast_exception_class_cast;
            }
        }
        if (httpRequestControl == null || httpRequestControl.getStatusLayoutManager() == null) {
            ToastUtil.show(reason);
            return;
        }
        SmartRefreshLayout smartRefreshLayout = httpRequestControl.getRefreshLayout();
        BaseQuickAdapter adapter = httpRequestControl.getRecyclerAdapter();
        StatusLayoutManager statusLayoutManager = httpRequestControl.getStatusLayoutManager();
        int page = httpRequestControl.getCurrentPage();
        if (smartRefreshLayout != null) {
            smartRefreshLayout.finishRefresh(false);
        }
        if (adapter != null) {
            adapter.loadMoreComplete();
            if (statusLayoutManager == null) {
                return;
            }
            //初始页
            if (page == 0) {
                if (!NetworkUtil.isConnected(App.getContext())) {
                    //可自定义网络错误页面展示
                    statusLayoutManager.showCustomLayout(R.layout.layout_status_layout_manager_error);
                } else {
                    statusLayoutManager.showErrorLayout();
                }
                return;
            }
            //可根据不同错误展示不同错误布局  showCustomLayout(R.layout.xxx);
            statusLayoutManager.showErrorLayout();
        }
  • 列表网络请求示例
   @Override
    public void loadData(int page) {
        //接口最大支持单页100
        mDefaultPageSize = 15;
        ApiRepository.getInstance().getMovie(mUrl, page * mDefaultPage, mDefaultPageSize)
                .compose(bindUntilEvent(FragmentEvent.DESTROY))
                .subscribe(new FastObserver<BaseMovieEntity>(getIHttpRequestControl()) {
                    @Override
                    public void _onNext(BaseMovieEntity entity) {
                        LoggerManager.i("url:" + mUrl);
                        mStatusManager.showSuccessLayout();
                        FastManager.getInstance().getHttpRequestControl().httpRequestSuccess(getIHttpRequestControl(), entity == null || entity.subjects == null ? new ArrayList<>() : entity.subjects, null);
                    }
                });
    }
  • 非列表请求示例
 AccountRepository.getInstance().getUserInfo()
                .compose(bindUntilEvent(FragmentEvent.DESTROY))
                .subscribe(new FastObserver<UserEntity>() {
                    @Override
                    public void _onNext(UserEntity entity) {
                        //处理数据
                    }
                });

2.2.10 加载等待Dialog设置

  • 1、需RxJava subscribe使用 FastLoadingObserver方可全局使用统一加载等待Loading Dialog
  • 2、在LoadingDialog 返回 FastLoadDialog 并将开发者想要的Dialog设置即可全局使用
  • 3、常用效果Dialog 使用UIWidget:widget-core库中UIProgressDialog进行常用Dialog样式设置,如需个性化自定义即可
  @Nullable
    @Override
    public FastLoadDialog createLoadingDialog(@Nullable Activity activity) {
        Dialog dialog = new PictureDialog(activity);
        return new FastLoadDialog(activity, dialog)
                .setCancelable(true)
                .setCanceledOnTouchOutside(true);
    }
  • 网络请求示例
UserRepository.getInstance().loginPhone(account, password)
                .compose(activity.bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(new FastLoadingObserver<LoginEntity>(activity, R.string.login_ing) {
                    @Override
                    public void _onNext(@NonNull LoginEntity entity) {
                       //逻辑处理
                    }

                    @Override
                    public void _onError(Throwable e) {
                       //错误处理
                });

2.2.11 Activity/Fragment 生命周期设置-禁用系统截屏等

FastLib通过ApplicationregisterActivityLifecycleCallbacks监听Activity生命周期,并做一些全局设置如滑动返回-SwipeBack;通过FragmentManagerregisterFragmentLifecycleCallbacks监听Fragment生命周期,并通过ActivityFragmentControl回调给开发者处理即可,实现参看FastLifecycleCallbacks;开发者可处理如*友盟统计-这样不需单独设置Base也可对三方库里的Activity及Fragment进行统计

  • 全局设置Activity/Fragment背景色可Fragment不设置背景减少过渡重绘
    @Override
    public void setContentViewBackground(View contentView, Class<?> cls) {
        if (contentView == null) {
            return;
        }
        //避免背景色重复
        if (!Fragment.class.isAssignableFrom(cls)
                && contentView.getBackground() == null) {
            contentView.setBackgroundResource(R.color.colorBackground);
        }
    }
  • 全局控制横竖屏 注意:targetSDK设置27以上不能设置windowIsTranslucent=true,否则直接崩溃,错误: Only fullscreen activities can request orientation
    /**
     * 设置屏幕方向--注意targetSDK设置27以上不能设置windowIsTranslucent=true属性不然应用直接崩溃
     * 错误为 Only fullscreen activities can request orientation
     * 默认自动 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
     * 竖屏 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
     * 横屏 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
     * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}
     *
     * @param activity
     */
    @Override
    public void setRequestedOrientation(Activity activity) {
        //全局控制屏幕横竖屏
        //先判断xml没有设置屏幕模式避免将开发者本身想设置的覆盖掉
        if (activity.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
            try {
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } catch (Exception e) {
                e.printStackTrace();
                LoggerManager.e(TAG, "setRequestedOrientation:" + e.getMessage());
            }
        }
    }
  • 三方库状态栏沉浸设置,FastLib只进行了简单设置不能满足全部情况,开发者需根据自己引入三方库进行特殊处理以满足需求; 注意如需要设置三方库Activity状态栏控制,返回值必须为true,否则StatusViewHelper 不会执行
/**
     * 设置非FastLib且未实现Activity 状态栏功能的三方Activity 状态栏沉浸,
     *
     * @param activity
     * @param helper
     * @return
     */
    @Override
    public boolean setStatusBar(Activity activity, StatusViewHelper helper, View topView) {
        return true;
    }
  • 三方库虚拟导航栏控制,FastLib只进行了简单设置不能满足全部情况,开发者需根据自己引入三方库进行特殊处理以满足需求; 注意如需要设置三方库Activity导航栏控制返回值必须为true,否则NavigationViewHelper 不会执行
     /**
     * {@link FastLifecycleCallbacks#onActivityStarted(Activity)}
     *
     * @param activity
     * @param helper
     */
    @Override
    public boolean setNavigationBar(Activity activity, NavigationViewHelper helper, View bottomView) {
        return true;
    }
  • Activity生命周期设置,可进行友盟统计应用前后台监听禁用系统截图-银行/金融类App常用功能,可以使用FastLib提供的FastActivityLifecycleCallbacks重写开发者需要的生命周期监听即可,如不需监听return null即可
    /**
     * Activity 生命周期监听--可用于三方统计页面数据
     * 示例仅为参考如无需添加自己代码可回调null
     *
     * @return
     */
    @Override
    public Application.ActivityLifecycleCallbacks getActivityLifecycleCallbacks() {
        return new FastActivityLifecycleCallbacks() {
           @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                super.onActivityCreated(activity, savedInstanceState);
                //阻止系统截屏功能-银行金融类App常用功能
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
            }
            @Override
            public void onActivityStarted(Activity activity) {
                super.onActivityStarted(activity);
                mActivityStart++;
                if (mActivityStart == 1) {
                    LoggerManager.i(TAG, "XXX正在前台运行");
                }
            }
            @Override
            public void onActivityStopped(Activity activity) {
                mActivityStart--;
                if (mActivityStart == 0) {
                    LoggerManager.i(TAG, "XXX正在后台运行");
                }
            }
        };
    }
  • Fragment生命周期设置,Do what you want
/**
     * Fragment 生命周期回调
     *
     * @return
     */
    @Override
    public FragmentManager.FragmentLifecycleCallbacks getFragmentLifecycleCallbacks() {
        return new FragmentManager.FragmentLifecycleCallbacks() {
            @Override
            public void onFragmentResumed(FragmentManager fm, Fragment f) {
                super.onFragmentResumed(fm, f);
                //MobclickAgent.onPageStart(f.getClass().getSimpleName());
            }

            @Override
            public void onFragmentPaused(FragmentManager fm, Fragment f) {
                super.onFragmentPaused(fm, f);
                //MobclickAgent.onPageEnd(f.getClass().getSimpleName());
            }
        };
    }

2.2.12 Activity 按键监听-控制系统音量等

  • 1、FastLib默认支持BasisActivity,主要对Activity的onKeyXXX事件进行全局控制,可用于音量键监控

  • 2、如自定义Activity也想全局监控,参看BasisActivity代码,执行FastManager.getInstance().getActivityKeyEventControl().onKeyXXX即可

  • 按键监听onKeyDown-;可控制音量键不显示系统UI,如抖音,返回值表示是否消费该事件,与系统一致。

@Override
    public boolean onKeyDown(Activity activity, int keyCode, KeyEvent event) {
        //演示拦截系统音量键控制--类似抖音
        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_DOWN://音量增加
                volume(1, false);
                return true;
            case KeyEvent.KEYCODE_VOLUME_UP://音量减少
                volume(1, true);
                return true;
        }
        return false;
    }
  • 其它按键监听 onKeyUponKeyLongPressonKeyShortcutonKeyMultiple等暂未想到使用场景有需要的拦截即可

2.2.13 Activity事件派发-点击非EditText关闭软键盘等

  • 1、FastLib默认支持BasisActivity,主要对Activity的dispatchXXX事件派发进行全局控制,可用于点击非软键盘区域关闭软键盘功能

  • 2、如自定义Activity也想全局监控,参看BasisActivity代码,执行FastManager.getInstance().getActivityDispatchEventControl().dispatchXXX即可

  • 触摸事件派发 dispatchTouchEvent,可通过KeyboardHelper里方法实现点击非输入框区域关闭软键盘功能 注意:目前Android 该方式有个小瑕疵:点击EditTextA再点击EditTextB 会出现软键盘先关闭再弹起的现象,但是目前是相对最优的方式,笔者观察微信/QQ亦是--微信/QQ的账号密码登录页

    /**
     * @param activity
     * @param event
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(Activity activity, MotionEvent event) {
        //根据事件派发全局控制点击非EditText 关闭软键盘
        if (activity != null) {
            KeyboardHelper.handleAutoCloseKeyboard(true, activity.getCurrentFocus(), event, activity);
        }
        return false;
    }

2.2.14 Toast效果设置

  • 1、FastLib提供的ToastUtil仅提供所有系统统一效果设置及单例模式,并不解决系统权限关闭后Toast不弹出等老大难的问题,如开发者要解决权限问题 推荐DToastsmart-show(SmartToast部分)

  • 2、笔者发现华为某个系统版本自己实现了单例模式的Toast,如开发者频繁调用show()方法会造成Toast不显示问题。故ToastUtil内部过滤华为Rom,不进行Toast单例并提供回调ToastControl供开发者定义Toast

  • ToastUtil 初始化设置属性

        int padding = SizeUtil.dp2px(8);
        //初始化toast工具
        ToastUtil.init(mContext, true, ToastUtil.newBuilder()
                .setBackgroundColor()//设置背景
                .setRadius(SizeUtil.dp2px(4))//设置圆角
                .setPaddingLeft(padding * 2)//左边距
                .setPaddingTop(padding)//上边距
                .setPaddingRight(padding * 2)//右边距
                .setPaddingBottom(padding)//下边距
                .setGravityYOffset(getResources().getDimensionPixelSize(R.dimen.dp_title_height) + StatusBarUtil.getStatusBarHeight())//Y轴偏移量
                .setTextSize(SizeUtil.dp2px(14))//文字尺寸
                .setDuration(Toast.LENGTH_SHORT)//显示时长
                .setGravity(Gravity.TOP)//显示位置
  • ToastControl回调设置
   @Override
    public Toast getToast() {
        return null;
    }

    @Override
    public void setToast(Toast toast, RadiusTextView textView) {

    }

2.2.15 主页退出程序设置

BasisActivityquitApp方法进行了相关操作处理并通过FastManager.getInstance().getQuitAppControl().quipApp(boolean isFirst, Activity activity)方便开发者处理,只需在BasisActivity子类onBackPressed调用quitApp即可,可设置xxx毫秒执行下步操作也可立即进行退出程序或者返回系统桌面等操作。

  • 回调设置2s后退出程序/回到系统桌面
    /**
     * @param isFirst  是否首次提示
     * @param activity 操作的Activity
     * @return 延迟间隔--如不需要设置两次提示可设置0--最佳方式是直接在回调中执行你想要的操作
     */
    @Override
    public long quipApp(boolean isFirst, Activity activity) {
        //默认配置
        if (isFirst) {
            ToastUtil.show(R.string.fast_quit_app);
        } else {
            FastStackUtil.getInstance().exit(false);//退出程序不杀进程-杀进程不会进入Activity onDestroy生命周期
            //activity.moveTaskToBack(true);-回到桌面
        }
        return 2000;
    }
  • BasisActivity子类onBackPressed调用quitApp
    @Override
    public void onBackPressed() {
        quitApp();
    }

2.3 FastRetrofit初始化

  • 1、至少使用 FastRetrofit.getInstance().setBaseUrl(BuildConfig.BASE_URL) 设置全局网络请求BaseUrl
  • 2、其它参数如设置超时-setTimeout添加统一请求头addHeader设置日志打印-setLogEnable设置打印json格式化日志-setLogJsonEnable
  • 3、其它配置可通过getOkHttpClientBuilder获取OkHttpClient.Builder进行个性化定制如添加cookie拦截器

2.3.1 多BaseUrl 设置

FastRetrofit提供方法名-method模式特定header模式两种模式进行多BaseUrl设置,默认方法名-method模式优先,可通过FastRetrofit.getInstance().setHeaderPriorityEnable(true)设置特定header模式优先,开发者根据项目情况自行选择 原理都是在通过设置OkHttpClient.Builder添加拦截器,重定向请求Url达到效果 其中特定header模式参考文章解决Retrofit多BaseUrl及运行时动态改变BaseUrl?在此感谢

  • 方法名-method模式,通过Map 对象进行保存method与BaseUrl对应关系 method作为key
FastRetrofit.getInstance()
                .putBaseUrl(method,baseUrl);
  • 特定header模式,通过Service 设置特定header 给一类key的方法使用同一BaseUrl 1、Service 配置 @Headers({FastRetrofit.BASE_URL_NAME_HEADER +Key}) 其中 FastRetrofit.BASE_URL_NAME_HEADER 为固定,Key必须与FastRetrofit初始化配置一致,二者缺一不可
/**
     * 检查应用更新--同时设置了Method及Header模式重定向请求Url,默认Method优先;
     * 可通过{@link FastRetrofit#setHeaderPriorityEnable(boolean)}设置Header模式优先
     *
     * @param map
     * @return
     */
    @GET(ApiConstant.API_UPDATE_APP)
    @Headers({FastRetrofit.BASE_URL_NAME_HEADER + ApiConstant.API_UPDATE_APP_KEY})
    Observable<UpdateEntity> updateApp(@QueryMap Map<String, Object> map);
}

2、FastRetrofit初始化配置

FastRetrofit.getInstance()
                //设置Header模式优先-默认Method方式优先
                .setHeaderPriorityEnable(true)
                .putHeaderBaseUrl(ApiConstant.API_UPDATE_APP_KEY, BuildConfig.BASE__UPDATE_URL);

2.3.2 添加拦截器

获取FastRetrofit里的OkHttpClient.Builder对象并添加拦截器,可以实现拦截cookie等功能

  • 添加cookie拦截器
       
//添加登录Cookie拦截器
 FastRetrofit.getOkHttpClientBuilder()
             .addInterceptor(new CookieInterceptor());
/**
 * @Author: AriesHoo on 2018/11/22 17:58
 * @E-Mail: AriesHoo@126.com
 * @Function: 拦截登录返回的cookie信息
 * @Description:
 */
public class CookieInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);
        List<String> mCookieList = response.headers("Set-Cookie");
        //保存Cookie
        if (!mCookieList.isEmpty() && request.url().toString().endsWith(ApiConstant.API_USER_LOGIN)) {
            StringBuilder sb = new StringBuilder();
            for (String cookie : mCookieList) {
                //注意Cookie请求头字段中的每个Cookie之间用逗号或分号分隔
                sb.append(TextUtils.isEmpty(sb.toString()) ? cookie : "," + cookie);
            }
            UserHelper.setCookie(sb.toString());//保存cookie
            Log.e(CookieInterceptor.class.getSimpleName(), "intercept: url : " + request.url() + ";cookie:" + sb.toString());
        }
        return response;
    }
}
  • 添加cookie 到统一header
     /**
     * 将Cookie添加到网络请求header中
     */
    public static void addCookie() {
        String cookieStr = UserHelper.getCookie();
        if (!TextUtils.isEmpty(cookieStr)) {
            FastRetrofit.getInstance().addHeader("Cookie", cookieStr);
        }
    }

2.3.3 重试机制

该功能需配合RxJava操作符retryWhen实现,传入FastRetryWhen即可,可设置重试时间ms及重试次数,如果不满足需求可参考自己修改;建议在请求基类设置,这样就不用每个请求都添加

    protected <T> Observable<T> transform(Observable<BaseEntity<T>> observable) {
        return observable
                //其它处理
                .retryWhen(new FastRetryWhen())
                //其它处理
                ;
    }

2.3.4 带进度监听的文件下载-示例

该功能配合FastDownloadObserver以实现下载文件路径设置及进度监听; 该功能算是简单示例,仅供参考

 mDownloadObserver = new FastDownloadObserver(fileName, finalMProgressDialog, isRangeEnable) {
            @Override
            public void onSuccess(File file) {
                //FastFileUtil.installApk(file);//下载成功
            }

            @Override
            public void onFail(Throwable e) {
               //错误
            }

            @Override
            public void onProgress(float progress, long current, long total) {
               //下载进度
        };

    FastRetrofit.getInstance().downloadFile(entity.url, header)
                .compose(((RxAppCompatActivity) activity).bindUntilEvent(ActivityEvent.DESTROY))
                //可自定义保存路径默认//storage/emulated/0/Android/data/<package-name>/cache/xxx/
                .subscribe(mDownloadObserver);

2.3.5 带进度监听的文件上传

该功能配合FastUploadRequestBodyFastUploadRequestListener实现上传进度监听


private RequestBody getUploadRequestBody(File file, FastUploadRequestListener listener) {
        if (listener == null) {
            return RequestBody.create(MultipartBody.FORM, file);
        }
        return new FastUploadRequestBody(RequestBody.create(MultipartBody.FORM, file), listener);
    }

private void uploadFile(List<String> listFile) {
        if (listFile == null) {
            return;
        }
      //其它设置-如设置上传进度Dialog
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM)
                //额外参数
                .addFormDataPart("xxKey", "xxValue");
        //添加上传实体
        for (int i = 0; i < listFile.size(); i++) {
            File file = new File(listFile.get(i));
            int finalI = i;
            builder.addFormDataPart("uploadfiles", file.getName(), getUploadRequestBody(file, new FastUploadRequestListener() {
                @Override
                public void onProgress(float progress, long current, long total) {
                     //其它代码-可更新进度Dialog 
                     //进度监听
                    LoggerManager.i("uploadFile", ":i=" + finalI + ";progress:" + progress + ";current:" + current + ";total:" + total);
                }

                @Override
                public void onFail(Throwable e) {
                    LoggerManager.i("uploadFile", "error:" + e.getMessage());
                }
            }));
        }
        RequestBody requestBody = builder.build();
        //上传地址需自行设置-可添加header
        FastRetrofit.getInstance().uploadFile("http://XXXX/v1/ftp/upload-files", requestBody)
                .compose(FastTransformer.switchSchedulers())
                .subscribe(new FastLoadingObserver<ResponseBody>(new FastLoadDialog(mContext, 进度Dialog)) {
                    @Override
                    public void _onNext(ResponseBody entity) {
                     
                });
    }

三、快速搭建UI

FastLib 提供常用布局layoutActivityFragment,开发者可以快速实现部分常用UI效果

3.1 快速搭建主页面-Tab+Fragment

通过继承FastMainActivity 快速搭建UI。支持设置支付宝、QQ类似tab+Fragment 也支持 微信类似水平滚动切换Fragment

  • 通过修改fast_dimens.xml 默认dimes属性值修改tab 主要尺寸属性
    <!--主页tab高度-->
    <dimen name="dp_tab_height">48dp</dimen>
    <!--主页tab icon宽高-->
    <dimen name="dp_tab_icon">24dp</dimen>
    <!--主页tab 文字与icon边距-->
    <dimen name="dp_tab_margin">0dp</dimen>
    <!--主页tab文字字号-->
    <dimen name="dp_tab_text_size">11dp</dimen>
    <!--主页tab 上划线宽度-->
    <dimen name="dp_tab_underline">0.5dp</dimen>
  • 通过修改fast_colors.xml默认color值修改tab 主要颜色属性
    <!--主页tab背景色-->
    <color name="colorTabBackground">#FCFCFC</color>
    <!--主页上划线颜色-->
    <color name="colorTabUnderline">#d6d6d6</color>
    <!--主页tab文字默认颜色-->
    <color name="colorTabTextUnSelect">#909090</color>
    <!--主页tab文字选中颜色-->
    <color name="colorTabTextSelect">@color/colorTitleText</color>
  • 通过setTabLayout方法参数修改CommonTabLayout所有属性
    @Override
    public void setTabLayout(CommonTabLayout tabLayout) {
            tabLayout.getDelegate()
                .setXXX();
    }
  • 通过getTabList初始化tabFragment
   @Override
    public List<FastTabEntity> getTabList() {
        ArrayList<FastTabEntity> tabEntities = new ArrayList<>();
        tabEntities.add(new FastTabEntity(R.string.home, R.drawable.ic_home_normal, R.drawable.ic_home_selected, HomeFragment.newInstance()));
        tabEntities.add(new FastTabEntity(R.string.activity, R.drawable.ic_activity_normal, R.drawable.ic_activity_selected, ActivityFragment.newInstance()));
        tabEntities.add(new FastTabEntity(R.string.mine, R.drawable.ic_mine_normal, R.drawable.ic_mine_selected, MineFragment.newInstance()));
        return tabEntities;
    }
  • 通过isSwipeEnable配置是否支持水平滑动切换Fragment,return true表示支持滑动切换
    @Override
    public boolean isSwipeEnable() {
        return false;
    }
  • 通过重写onTabSelect方法回调tab选中的position
    @Override
    public void onTabSelect(int position) {
    }
  • 通过重写onTabReselect回调tab 选中position 又被点击;用于开发者实现刷新列表回到顶部功能
   @Override
    public void onTabReselect(int position) {

    }

3.2 快速搭建带TitleBar的Activity/Fragment

通过继承FastTitleActivity/FastTitleFragment快速实现带TitleBarViewActivity/Fragment

  • 继承FastTitleActivity/FastTitleFragment并通过 getContentLayout() 返回layout
   @Override
    public int getContentLayout() {
        return R.layout.activity_xxx;
    }
  • 复用fast_layout_title_bar.xml
<?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">

    <include layout="@layout/fast_layout_title_bar"/>

</LinearLayout>
  • 通过setTitleBar设置本Activity/Fragment 特殊处理;如全局TitleBarView 为白色背景,当前Activity/Fragment需要设置渐变色背景、全局返回箭头为深色、当前Activity/Fragment需要设置成白色等。
    @Override
    public void setTitleBar(TitleBarView titleBar) {
        titleBar.setLeftTextDrawable(R.drawable.ic_back_white)
                .setStatusBarLightMode(false)
                .setTitleMainTextColor(Color.WHITE)
                .setBgResource(R.drawable.shape_qq_bg);
    }
  • 2.2.13版本新增通过实现 IFastTitleBarView接口以实现全局TitleBarView设置功能-其它和继承 FastTitleActivity/FastTitleFragment 效果一致;xml仍需自己设置TitleBarView;按需使用

3.3 快速搭建带TitleBar+RecyclerView+下拉刷新的Activity/Fragment

通过继承FastTitleRefreshLoadFragment/FastRefreshLoadActivity快速搭建相关UI页面;不需TitleBarView 的Fragment继承FastRefreshLoadFragment即可/不需TitleBarView 的Activity layout不添加TitleBarView即可。

  • getContentLayout设置layout; 带TitleBarView可复用fast_layout_title_refresh_recycler.xml不带可复用fast_layout_refresh_recycler.xml

  • getAdapter 返回适配器

   @Override
    public BaseQuickAdapter<SubjectsEntity, BaseViewHolder> getAdapter() {
        mAdapter = new SubjectMovieAdapter(ApiConstant.API_MOVIE_TOP.equals(mUrl));
        return mAdapter;
    }
  • loadData(int page) 用于调用接口请求数据
    @Override
    public void loadData(int page) {
        //接口最大支持单页100
        mDefaultPageSize = 15;
        ApiRepository.getInstance().getMovie(mUrl, page * mDefaultPage, mDefaultPageSize)
                .compose(bindUntilEvent(FragmentEvent.DESTROY))
                .subscribe(new FastObserver<BaseMovieEntity>(getIHttpRequestControl()) {
                    @Override
                    public void _onNext(BaseMovieEntity entity) {
                        LoggerManager.i("url:" + mUrl);
                        mStatusManager.showSuccessLayout();
                        FastManager.getInstance().getHttpRequestControl().httpRequestSuccess(getIHttpRequestControl(), entity == null || entity.subjects == null ? new ArrayList<>() : entity.subjects, null);
                    }
                });
    }
  • 默认支持上拉刷新及自动加载下一页,会回调loadData(int page) 可通过isRefreshEnableisLoadMoreEnable禁用;
   @Override
    public boolean isRefreshEnable() {
        return false;
    }

    @Override
    public boolean isLoadMoreEnable() {
        return false;
    }
  • 列表默认竖直列表,如需更改通过getLayoutManager返回即可
    @Override
    public RecyclerView.LayoutManager getLayoutManager() {
        return new LinearLayoutManager(mContext,RecyclerView.HORIZONTAL,false);
    }
  • 刷新头和加载更多默认通过全局设置,可通过getRefreshHeadergetLoadMoreView个性化
    @Override
    public RefreshHeader getRefreshHeader() {
        return new ClassicsHeader(mContext);
    }

    @Override
    public LoadMoreView getLoadMoreView() {
        return new SimpleLoadMoreView();
    }
  • 可通过onItemClicked回调Item点击事件;可通过isItemClickEnable禁用 列表Item事件,当然禁用后不会有onItemClicked回调
    @Override
    public void onItemClicked(BaseQuickAdapter<SubjectsEntity, BaseViewHolder> adapter, View view, int position) {
        super.onItemClicked(adapter, view, position);
        WebViewActivity.start(mContext, adapter.getItem(position).alt);
    }

    @Override
    public boolean isItemClickEnable() {
        return super.isItemClickEnable();
    }

3.4 快速搭建应用内加载网页Activity

通过继承FastWebActivity快速实现应用内通过WebView打开网页Activity

  • 建议AndroidManifest添加configChanges如网页有视频横屏时Activity 不会销毁重建
       <!-- 应用内浏览器 -->
        <activity
            android:name=".module.WebViewActivity"
            android:configChanges="locale|layoutDirection|mcc|mnc|orientation|screenSize"
            android:hardwareAccelerated="true"
            android:label="@string/fast_loading"/>
  • 通过getProgressColor更改进度条颜色,默认为 R.color.colorTitleText ;通过getProgressHeight进度条高度,默认 3dp
    @Override
    protected int getProgressColor() {
        return super.getProgressColor();
    }

    @Override
    protected int getProgressHeight() {
        return super.getProgressHeight();
    }
  • 通过setAgentWeb(AgentWeb.CommonBuilder mAgentBuilder)设置,支持下载进度监听权限监听等。具体参考AgentWeb-官方文档 通过setAgentWeb(AgentWeb mAgentWeb),可获取 WebView 做类似 长按图片下载功能
    @Override
    protected void setAgentWeb(AgentWeb.CommonBuilder mAgentBuilder) {
        super.setAgentWeb(mAgentBuilder);
    }

   @Override
    protected void setAgentWeb(AgentWeb mAgentWeb) {
        super.setAgentWeb(mAgentWeb);
        WebView mWebView = mAgentWeb.getWebCreator().getWebView();
        mWebView.setOnLongClickListener(v -> {
            WebView.HitTestResult hitTestResult = mWebView.getHitTestResult();
            if (hitTestResult == null) {
                return false;
            }
           //处理长按事件-可做长按下载图片功能
            return true;
        });
    }

3.5 新增:快速实现下拉刷新Activity/Fragment

2.2.13 版本 抽离 IFastRefreshView 接口 Activity/Fragment 只需实现接口 IFastRefreshView ,用户只需在 onRefresh 回调进行相关操作即可

    /**
     * 获取下拉刷新头布局 建议通过{@link #setRefreshLayout(SmartRefreshLayout)} {@link SmartRefreshLayout#setRefreshHeader(RefreshHeader)}修改
     *
     * @return 下拉刷新头
     */
    @Deprecated
    default RefreshHeader getRefreshHeader() {
        return null;
    }

    /**
     * 需要下拉刷新的布局 --可以是Activity根布局、Fragment 不要传根布局(除非根布局为SmartRefreshLayout)
     *
     * @return
     */
    default View getContentView() {
        return null;
    }

    /**
     * 是否支持下拉刷新功能
     *
     * @return
     */
    default boolean isRefreshEnable() {
        return true;
    }

    /**
     * 回调设置的SmartRefreshLayout
     *
     * @param refreshLayout
     */
    default void setRefreshLayout(SmartRefreshLayout refreshLayout) {

    }

特别提醒 :因FastLib默认以 Activity/Fragment 根布局 进行查找 SmartRefreshLayout ,如查找不到会默认将根布局从通过 getParent() 获取父容器然后根布局移除然后新建 SmartRefreshLayout 作为根布局 将原始根布局作为 SmartRefreshLayout 的唯一子view以达到实现下拉刷新的目的;但是Fragment 根布局 获取不到父容器 getParent() 返回为null,故如在Fragment使用下拉刷新有两种方式 一、Fragment 根布局为 SmartRefreshLayout 二、Fragment 根布局不为 SmartRefreshLayout 需重写 IFastRefreshView View getContentView() 返回需包裹的View 对象,具体可参看 Demo MineFragmentActivity 无任何限制

四、工具类

此处介绍FastLibUIWidget:widget-core中常用工具类,其它少有使用的不做介绍

4.1 ToastUtil -系统toast工具

FastLib提供;系统Toast 工具单例模式封装,仍然存在权限关闭Toast无法弹出问题,如开发者要解决权限问题 推荐DToastsmart-show(SmartToast部分)

ToastUtil预览

  • show(int content) 普通
  • show(CharSequence content)
  • showSuccess(int msg) 成功
  • showSuccess(CharSequence msg)
  • showFailed(int msg) 失败
  • showFailed(CharSequence msg)
  • showWarning(int msg) 警告
  • showWarning(CharSequence msg)

4.2 SPUtil-SharedPreferences工具

FastLib提供;SharedPreferences 暂存数据工具类,getSharedPreferences 参数那么 默认为应用包名

SPUtil预览

  • put(Context context, String key, Object object) 存放数据
  • Object get(Context context, String key, Object def) 取数据
  • boolean remove(Context context, String key) 根据key清除数据
  • boolean clearAll(Context context) 清除所有暂存数据
  • boolean contains(Context context, String key) 检查是否存有key对应数据
  • Map<String, ?> getAll(Context context) 获取所有暂存数据

4.3 SizeUtil-尺寸转换工具

FastLib提供; 尺寸获取及转换工具,使用Resources.getSystem()无需传入Context

SizeUtil预览

  • int getScreenWidth() 获取屏幕宽度
  • int getScreenHeight() 获取屏幕高度
  • int px2dp(float pxValue) px转dp
  • int dp2px(float dpValue) dp转px
  • int px2sp(float pxValue) px转sp
  • int sp2px(float spValue) sp转px

4.4 FastFormatUtil-格式转换工具

FastLib提供;快速格式化工具,包括时间格式化内存单位格式化double保留几位小数等功能

FastFormatUtil预览

  • String formatTime(long time, String format) 格式化时间 yyyy-MM-dd HH:mm:ss
  • String formatTime(Date time, String format) 格式化时间 yyyy-MM-dd HH:mm:ss
  • String formatDataSize(long dataSize) 格式化内存单位四舍五入保留两位小数
  • String formatDataSize(long dataSize, String pattern) 格式化内存单位四舍五入 pattern格式 "###.00"
  • String formatDoubleSize(double value, int maxLength) 四舍五入保留 maxLength位小数
  • String formatDoubleSize(double value, int maxLength, int roundingMode) 保留 maxLength位小数 参看RoundingMode

4.5 SnackBarUtil-Snackbar工具

FastLib提供; Snackbar快速设置工具,链式调用

SnackBarUtil预览

  • SnackBarUtil with(@NonNull final View mParent) 依赖View
  • setMessage(@NonNull final CharSequence msg) 设置信息
  • setMessageColor(@ColorInt final int color) 设置信息颜色
  • setBgColor(@ColorInt final int color) 设置背景色
  • setDuration(@Duration final int duration) 设置显示时间 Duration#LENGTH_INDEFINITE 一直 Duration#LENGTH_INDEFINITE短时 Duration#LENGTH_LONG 长时
  • setAction(@NonNull final CharSequence text, @NonNull final View.OnClickListener listener) 设置按钮、点击事件
  • setAction(@NonNull final CharSequence text, @ColorInt final int color, @NonNull final View.OnClickListener listener) 设置按钮、文本颜色、点击事件
  • setBottomMargin(@IntRange(from = 1) final int bottomMargin) 设置底边距
  • show() 展示Snackbar
  • showSuccess() 展示预设成功Snackbar 会改变前面设置的文字、背景、按钮颜色
  • showWarning() 展示预设警告Snackbar 会改变前面设置的文字、背景、按钮颜色
  • showError() 展示预设错误Snackbar 会改变前面设置的文字、背景、按钮颜色
  • dismiss() 主动关闭Snackbar

4.6 FastUtil-app常用工具

FastLib提供;包含应用常用功能如:Activity跳转获取版本号

FastUtil预览

  • CharSequence getAppName(Context context) 获取应用名称
  • int getRandom(int max, int min) 获取 min - max的随机数
  • View getRootView(Activity activity) 获取Activity 根布局
  • String getVersionName(Context context) 获取版本名
  • int getVersionCode(Context context) 获取版本号
  • boolean isClassExist(String className) 获取某个Class是否存在 用于判断是否导入某个库
  • boolean isRunningForeground(Context context, String packageName) 是否某个应用前台运行
  • boolean isTablet(Context context) 是否平板设备
  • void jumpMarket(Context mContext, String packageName) 跳转应用市场某个应用详情页-用于评价
  • void setActivitySingleFlag(int flag) 设置只启动Activity 一个的flag
  • void startActivity(Context context, Class<? extends Activity> activity, Bundle bundle, boolean isSingle) 跳转Activity
  • void startShareText(Context context, String text, CharSequence title) 调用系统分享 文本
  • void copyToClipboard(Context context, String str) 拷贝到粘贴板

4.7 FastStackUtil-应用Activity堆栈管理工具

FastLib 提供;应用Activity堆栈工具类,通过监听Activity生命周期添加、移除故可管理应用所有Activity包括三方库;单例模式

FastStackUtil预览

  • Stack getStack() 获取堆栈
  • Activity getCurrent() 获取栈顶 Activity
  • Activity getPrevious() 获取前一个Activity
  • Activity getActivity(Class cls) 根据Class 获取Activity ,如果是
  • FastStackUtil push(Activity activity) 入栈
  • FastStackUtil pop(Activity activity, boolean isFinish) 出栈 isFinish true 调用finish方法
  • FastStackUtil popAll() 清空栈 如退出应用 重新登录
  • FastStackUtil popAllExceptCurrent(Class cls) 将堆栈里退回某个Activity为止
  • FastStackUtil popAllExceptCurrent() 只留下栈顶一个Activity
  • FastStackUtil exit(boolean kill) 退出应用 kill true 杀进程

4.8 GlideManager-Glide加载工具

FastLib提供;常用 Glide 加载图片方式

GlideManager预览

  • setPlaceholderColor(@ColorInt int placeholderColor) 设置默认占位ColorDrawable
  • setPlaceholderRoundRadius(float placeholderRoundRadius) 设置圆角弧度
  • setCirclePlaceholder(int circlePlaceholder) 设置圆形占位图资源id
  • setCirclePlaceholder(Drawable circlePlaceholder) 设置圆形占位图Drawable
  • setCommonPlaceholder(int commonPlaceholder) 设置普通占位图资源id
  • setCommonPlaceholder(Drawable commonPlaceholder) 设置普通占位图Drawable
  • setRoundPlaceholder(int roundPlaceholder) 设圆角占位图资源id
  • setRoundPlaceholder(Drawable roundPlaceholder) 设置圆角占位图Drawable
  • loadImg(Object obj, ImageView iv, Drawable placeholder) 加载普通图片并设置占位Drawable
  • loadImg(Object obj, ImageView iv, int placeholderResource) 加载普通图片并设置占位图资源id
  • loadImg(Object obj, ImageView iv) 加载普通图片使用全局设置默认占位图
  • loadRoundImg(Object obj, ImageView iv, float dp, Drawable placeholder, boolean isOfficial) 加载圆角图 设置圆角幅度、占位图Drawable 、设置是否官方圆角方式
  • loadRoundImg(Object obj, ImageView iv, float dp, boolean isOfficial) 加载圆角图 设置圆角幅度、默认占位图 、设置是否官方圆角方式
  • loadRoundImg(Object obj, ImageView iv, float dp) 加载圆角图 设置圆角幅度、默认占位图 、默认官方圆角方式
  • loadRoundImg(Object obj, ImageView iv, boolean isOfficial) 加载圆角图 默认幅度、默认占位图 、设置是否官方圆角方式
  • loadRoundImg(Object obj, ImageView iv) 加载圆角图 默认幅度、默认占位图、默认官方圆角方式
  • loadCircleImg(Object obj, ImageView iv, Drawable placeholder) 加载圆角图 设置占位图
  • loadCircleImg(Object obj, ImageView iv) 加载圆形图片、默认占位图

4.9 LoggerManager-Logger日志打印工具

FastLib提供;Logger 常用模式,通过3种init方式设置TAG是否打印扩展配置,全局TAG,支持设置单独TAG

LoggerManager预览

  • 具体方法同Logger这里不做方法罗列

4.10 TabLayoutManager-TabLayout使用工具

FastLib提供;TabLayoutManager 支持快速设置TabLayout三种layout SlidingTabLayoutCommonTabLayoutSegmentTabLayout 配合ViewPager实现水平滑动Fragment,减少重复代码量;快速实现主页滑动切换FragmentFastMainActivity亦是使用本工具类实现

TabLayoutManager预览

  • setCommonTabData(FragmentActivity activity, final CommonTabLayout tabLayout, final ViewPager viewPager, ArrayList tabs, List fragments, final OnTabSelectListener listener) 快速设置CommonTabLayout 滑动并支持position变化监听
  • setSlidingTabData(FragmentActivity activity, SlidingTabLayout tabLayout, ViewPager viewPager, List tittles, List fragments, OnTabSelectListener listener) 快速设置SlidingTabLayout 滑动并支持position变化监听
  • setSegmentTabData(Fragment fragment, final SegmentTabLayout tabLayout, final ViewPager viewPager, String[] titles, List fragments, final OnTabSelectListener listener) 快速设置SegmentTabLayout 滑动支持支持position变化监听

4.11 StatusBarUtil-状态栏工具

UIWidget:widget-core 提供;状态栏文字颜色处理相关工具

StatusBarUtil预览

  • int setStatusBarLightMode(Activity activity) 设置状态栏浅色模式(状态栏文字黑色)返回值 0-不支持;1-MIUI;2-FlyMe ;3-Android M
  • int setStatusBarDarkMode(Activity activity) 设置状态栏深色模式(状态栏文字白色)返回值 0-默认值本身就不支持黑白色变化默认白色文字;1-MIUI;2-FlyMe ;3-Android M
  • boolean isSupportStatusBarFontChange 判断是否支持状态栏文字颜色变换
  • int getStatusBarHeight() 获取状态栏高度

4.12 StatusViewHelper-状态栏沉浸帮助类

UIWidget:widget-core 提供;设置Activity 沉浸状态栏效果帮助类,链式调用;未做撤销方法建议一个Activity只做一次操作

StatusViewHelper预览

  • StatusViewHelper with(Activity activity) 传入目标Activity
  • setLogEnable(boolean logEnable) 设置是否打印内部日志
  • setControlEnable(boolean controlEnable) 是否控制状态栏沉浸--实际都是沉浸了,如果传入false 即增加一层黑色View 被状态栏遮住
  • setTransEnable(boolean transEnable) 是否全透明 半透明效果为5.0 MD效果 增加一个102 透明度的黑色Drawable
  • setPlusStatusViewEnable(boolean plusStatusViewEnable) 是否增加一个状态栏高度View 用于状态栏遮住 默认 增加view padding以避免被遮住
  • setStatusViewColor(int StatusViewColor) 状态栏View 颜色 用于设置半透明效果 setPlusStatusViewEnable为true才有效果
  • setStatusViewDrawable(Drawable drawable) 状态栏View 背景Drawable用于设置半透明效果 setStatusViewColor也是调用该方法设置ColorDrawable
  • setStatusLayoutColor(int StatusLayoutColor)状态栏View 父容器 颜色
  • setStatusLayoutDrawable(Drawable StatusLayoutDrawable) 状态栏View 父容器背景Drawable setStatusLayoutColor也是调用该方法设置ColorDrawable
  • setTopView(View view, boolean enable) 设置顶部View 状态栏下边View,第二个参数 是否设置marginTop 默认通过paddingTop 如地图顶部为EditText 可设置true
  • void init() 执行效果 ;以上设置参数最终需要调用init()方法才会支持最终操作

4.13 RomUtil-ROM判断工具

UIWidget:widget-core 提供;用于检测ROM厂商 国内ROM 主要通过 android.os.SystemProperties 判断

RomUtil预览

  • boolean isMIUI() 是否MIUI-小米ROM
  • String getMIUIVersion() 获取MIUI版本
  • int getMIUIVersionCode() 获取MIUI版本号 用于大小判断
  • boolean isEMUI() 是否EMUI -华为/荣耀 ROM
  • String getEMUIVersion() 获取EMUI版本
  • boolean isOPPO() 是否OPPO ROM
  • String getOPPOVersion() 获取OPPO版本
  • boolean isVIVO() 是否VIVO ROM
  • String getVIVOVersion() 获取VIVO 版本
  • boolean isSmartisan() 是否smartisanUI-锤子ROM
  • String getSmartisanVersion() 获取smartisan版本
  • boolean isFlyme() 是否Flyme UI -魅族ROM
  • String getFlymeVersion() 获取Flyme版本
  • int getFlymeVersionCode 获取Flyme版本号
  • boolean isQiKu() 是否奇酷UI-360ROM
  • String getQiKuVersion() 获取奇酷UI版本
  • String getSystemProperty(String key, String defaultValue) 扩展 通过获取android.os.SystemProperties值判断是否某个ROM
  • boolean isRom(String key) 通过getSystemProperty 判断是否为某个ROM

4.14 NavigationBarUtil-导航栏工具

UIWidget:widget-core 提供;导航栏相关值获取工具

NavigationBarUtil预览

  • boolean isOpenFullScreenGestures(Context context) 是否开启全面屏手势-支持小米 VIVO 华为 三星
  • boolean hasNavBar(Activity activity) 是否有导航栏 开启全面屏返回false
  • int getNavigationBarHeight(Activity activity) 获取导航栏高度 可设置导航栏不管是否开启都会获取到值'
  • boolean isFullScreenDevice(Context context) 通过手机纵横比判断是否全面屏 阈值为1.97f
  • float getAspectRatio(Context context) 获取手机纵横比

4.15 NavigationViewHelper-导航栏沉浸帮助类

UIWidget:widget-core 提供;虚拟导航栏沉浸帮助类配合NavigationBarUtil、配合KeyboardHelper 控制底部输入框,链式调用;未设置复位方式建议调用一次即可

NavigationViewHelper预览

  • NavigationViewHelper with(Activity activity) 传入需要控制的Activity
  • setLogEnable(boolean logEnable) 是否打印内部日志
  • setControlEnable(boolean controlEnable) 是否控制导航栏 -实际都是沉浸了的,通过设置黑色View 用于导航栏遮住
  • setTransEnable(boolean transEnable) 是否全透明 半透明效果为102透明的黑色
  • setPlusNavigationViewEnable(boolean plusNavigationViewEnable) 是否增加View 用于导航栏遮住
  • setControlBottomEditTextEnable(boolean controlBottomEditTextEnable) 是否控制底部输入框 -通过KeyboardHelper实现
  • setOnKeyboardVisibilityChangedListener(KeyboardHelper.OnKeyboardVisibilityChangedListener listener) 设置键盘开启关闭监听 setControlBottomEditTextEnable 为true才会有用
  • setNavigationViewColor(int navigationViewColor) 设置导航栏View 颜色 setPlusNavigationViewEnable 为true才有效果
  • setNavigationViewDrawableTop(Drawable drawable) 设置导航栏View 背景Drawable setNavigationViewColor 实际调用该方法传入ColorDrawable
  • setNavigationLayoutColor(int navigationLayoutColor) 设置导航栏View父容器背景颜色
  • setNavigationViewDrawable(Drawable drawable) 设置导航栏View父容器背景Drawable setNavigationLayoutColor实际调用该方法传入ColorDrawable
  • setBottomView(View view, boolean enable) 设置底部View 默认Activity根布局 第二参数为 是否设置marginTop 如底部是一个 Button 可设置true
  • void init() 执行效果;以上设置参数最终需要调用init()方法才会支持最终操作

4.16 KeyboardHelper-软键盘帮助类/工具

UIWidget:widget-core 提供;用于控制底部软件盘弹起-链式调用静态方法操作软键盘等功能帮助类;

KeyboardHelper预览

  • KeyboardHelper with(Activity activity) 传入控制Activity
  • setLogEnable(boolean logEnable) 设置是否打印内部日志
  • setOnKeyboardVisibilityChangedListener(OnKeyboardVisibilityChangedListener listener) 设置软键盘开启关闭监听
  • setEnable() 设置监听 通过 widow.setSoftInputMode WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE 控制软键盘模式--推荐使用
  • setEnable(int mode) 自定义传入键盘模式
  • setDisable 清除键盘模式并关闭View.getViewTreeObserver.removeOnGlobalLayoutListener监听

以下为静态方法用于软键盘常用操作

  • closeKeyboard(View view) 关闭软键盘
  • closeKeyboard(Activity activity) 关闭软键盘
  • closeKeyboard(Dialog dialog) 关闭软件盘
  • openKeyboard(final EditText editText, long delay) 延时打开软键盘
  • openKeyboard(EditText editText) 打开软键盘 默认300 ms
  • toggleKeyboard(Activity activity) 切换软键盘开启状态
  • handleAutoCloseKeyboard(boolean isAutoCloseKeyboard, View currentFocusView, MotionEvent motionEvent, Object dialogOrActivity) 处理点击非EditText 区域关闭软键盘方法一般在Activity dispatchTouchEvent 派发触摸事件中调用

4.17 FindViewUtil-查找子View工具

UIWidget:widget-core 提供;用于查找某个ViewGroupView 功能

FindViewUtil预览

  • T getTargetView(View rootView, Class<? extends View> targetClass, int id) 查询目标View 下某个id的某类View 根据目标Class查询
TitleBarView titleBar = FindViewUtil.getTargetView(rootView, TitleBarView.class, R.id.titleBar_headFastLib);
  • T getTargetView(View rootView, Class<? extends View> targetClass) 查询目标View下 第一个目标Class 的View
TitleBarView titleBar = FindViewUtil.getTargetView(rootView, TitleBarView.class);
  • T getTargetView(View rootView, int id) 查询目标View 下某个id View
TitleBarView titleBar = FindViewUtil.getTargetView(rootView, R.id.titleBar_headFastLib);

五、特殊情况处理

5.1 主页Tab-不同Fragment状态栏文字颜色切换

BasisFragment重新定义了对用户可见性回调,无需关心Fragment是否在ViewPager里,只需在onVisibleChanged执行相关代码即可 状态栏文字颜色通过StatusBarUtil对应方法实现切换

   @Override
    protected void onVisibleChanged(boolean isVisibleToUser) {
        super.onVisibleChanged(isVisibleToUser);
        if (isVisibleToUser) {
           StatusBarUtil.setStatusBarLightMode(activity);
        } 
    }

5.2 启动页图片沉浸导航栏及状态栏

严格说来该情况并非FastLib需要解决的问题,实际开发中大多也不会管导航栏问题。不过笔者开发中遇到过在此分享下,开发者按需使用即可

  • 将图片设置为Activity根布局背景;该方式适配性差容易出现图片拉伸变形问题
 mContentView.setBackgroundResource(R.drawable.img_bg_login);
  • 首先Activity根布局设置纯色布局、给ImageView设置 scaleType一个不会拉伸的模式如fitCenter然后getWindow().getDecorView().setSystemUiVisibility 最后 设置状态栏及导航全透明即可。建议在onWindowFocusChanged回调当获取焦点时执行
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
                decorView.setSystemUiVisibility(option);
                getWindow().setNavigationBarColor(Color.TRANSPARENT);
                getWindow().setStatusBarColor(Color.TRANSPARENT);
            }
        }
    }

结语

感谢FastLib所使用到的所有三方库的 Author, 以及所有为 Open Sourece 做无私贡献的 Developer 和 Organizations。 如果您认可 FastLib , 并使用FastLib 在实际开发中切实的提升了您的工作效率和开发能力, 请您点击右上角 Star 支持一下谢谢!

Clone this wiki locally