打造万能的EmptyLayout

前言

最近一直在做新项目,做的途中也一直在思考,如何让开发更加的方便,界面的实现更加的优雅,于是,就去github稍微搜索了一下好的例子,结果不尽人意,要么太臃肿,要么移植难,要么结构不清晰,于是,就打算自己来实现一个

效果图

代码使用

     LoadingLayout loadingLayout;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         loadingLayout = (LoadingLayout) findViewById(R.id.main_loading);
         loadingLayout.showLoadingView();
     }
     public void click(View v) {
         switch (v.getId()) {
             case R.id.main_content:
                 loadingLayout.showContentView();
                 break;
             case R.id.main_empty:
                 loadingLayout.showEmptyView();
                 break;
             case R.id.main_error:
                 loadingLayout.showErrorView();
                 break;
             case R.id.main_load:
                 loadingLayout.showLoadingView();
                 break;
             default:
         }
     }

那四个Button就不看了,只是来模拟加载的几种情况,主要来看一下主布局,一般主布局里面放的是一个RecyclerView,为了演示方便就放了一个TextView

    <com.codelang.loadinglayout.LoadingLayout
        android:id="@+id/main_loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="显示网络加载后的内容" />
    </com.codelang.loadinglayout.LoadingLayout>

这么写的好处是什么呢?

  • 再写不用在每个页面里面去include个空布局了
  • 将所有的处理都交给根布局,专注主布局,结构更加的清晰

实现

先来说说我的思路:

  • 挑选根布局: 挑选一个自己平常在写xml布局的时候用的最多的根布局,因为ConstraintLayout能基本满足所有布局的要求,所以,我打算让LoadingLayout继承ConstraintLayout
  • 添加布局: 将正在加载布局、加载错误布局、加载空布局addView到LoadingLayout
  • 如何去控制布局: 这个地方,我想到了一个办法,比如,当前我要显示一个空布局,遍历LoadingLayout的所有子View全部gone隐藏,然后只Visible空布局,正在加载布局和加载失败原理一样
  • 显示加载成功布局: 加载成功的布局和上面略有一点不同,因为我们已经加载成功了,辅助的三个布局也没有必要再存留在根布局,所以,我们先remove掉这个三个布局,然后遍历所有的子view去Visible

然后,来看下LoadingLayout的代码吧

/**
 * @author wangqi
 * @since 2017/12/11 14:04
 */
public class LoadingLayout extends ConstraintLayout {
    /**
     * 正在加载的布局
     */
    private View loadingView;
    /**
     * 错误布局
     */
    private View errorView;
    /**
     * 空布局
     */
    private View emptyView;
    public LoadingLayout(Context context) {
        this(context, null);
    }
    public LoadingLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public LoadingLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }
    /**
     * 初始化
     * 添加"空布局"、"错误布局"、"正在加载布局"
     *
     * @param context
     */
    private void initView(Context context) {
        LayoutInflater inflater = LayoutInflater.from(context);
        /*****  加载正在加载页面  *******/
        loadingView = inflater.inflate(R.layout.loading_load, this, false);
        addView(loadingView);
        /****  加载错误页面  *******/
        errorView = inflater.inflate(R.layout.loading_error, this, false);
        addView(errorView);
        /*****  加载空页面  *******/
        emptyView = inflater.inflate(R.layout.loading_empty, this, false);
        addView(emptyView);
        loadingView.setVisibility(View.GONE);
        errorView.setVisibility(View.GONE);
        emptyView.setVisibility(View.GONE);
    }
    /**
     * 显示主布局
     */
    public void showContentView() {
        removeView(errorView);
        removeView(emptyView);
        removeView(loadingView);
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            view.setVisibility(View.VISIBLE);
        }
    }
    /**
     * 显示加载错误布局
     */
    public void showErrorView() {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            view.setVisibility(View.GONE);
        }
        errorView.setVisibility(View.VISIBLE);
    }
    /**
     * 显示正在加载布局
     */
    public void showLoadingView() {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            view.setVisibility(View.GONE);
        }
        loadingView.setVisibility(View.VISIBLE);
    }
    /**
     * 显示空布局
     */
    public void showEmptyView() {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            view.setVisibility(View.GONE);
        }
        emptyView.setVisibility(View.VISIBLE);
    }
}

代码十分的简短,逻辑也特别的清晰,如果 想扩展的话,也可以直接在LoadingLayout里面直接处理,比如在showLoadingView的时候做一下网络判断处理,如果无网络的话,显示错误布局,告知用户打开网络,也有可能在显示错误布局的时候,会有点击再次加载功能,这时候,我们就需要在LoadingLayout里面增加接口回调功能,此处就不展示了,下载源码的链接https://github.com/MRwangqi/LoadingLayout

总结

编码前的思路整理是项目开发的重中之重,学会思考才能更好的编程

原文发布于微信公众号 - codelang(codelang)

原文发表时间:2017-12-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端知识分享

第87天:HTML5中新选择器querySelector的使用

1、document.querySelector("selector"); selector:根据CSS选择器返回第一个匹配到的元素,如果没有匹配到,则返回nu...

893
来自专栏微信公众号:Java团长

Java实现验证码功能实例

Java如何实现验证码验证功能呢?日常生活中,验证码随处可见,他可以在一定程度上保护账号安全,那么他是怎么实现的呢?

632
来自专栏阮一峰的网络日志

CSS 的空格处理

上面是一行 HTML 代码,文字的前部、内部和后部各有两个空格。为了便于识别,这里使用半圆形符号◡表示空格。

842
来自专栏web前端-

Jquery的属性操作和DOM操作

       3 val()    :     获取或设置表单内容    (原生JS使用value)

732
来自专栏進无尽的文章

编码篇-继承+通知看方法的实现和delloc方法的调用

UITableViewCell B继承自 UITableViewCell A, UITableViewCell A 注册了名为A的通知,通知绑定的方法为 方...

872
来自专栏HTML5学堂

JS设置标签的内容和样式

上一期堡堡给大家分享了操作符与数据类型转换。掌握JS操作符的目的是为了能够灵活的操作变量,以便完成JS的各种逻辑处理;掌握数据类型转换可以让我们避免一些不该发生...

3419
来自专栏郭霖

Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个朋友在评论中留言,希望我可以帮他将这个滑动菜单改成双向滑动的方式。当时也没想花太多时间,简...

2976
来自专栏强仔仔

JQuery之内置函数响应事件

今天给大家介绍一下on函数中events的种类和用法。 具体我把它分为:键盘事件,鼠标事件,input事件,还有一个是基础事件(例如:滚动,界面大小变化等等之类...

1756
来自专栏Android相关

Android的NestedScroll机制

这种事件传递的结果就会导致以下问题: 一个View把Touch事件消费之后,其他View就无法接收到该事件,也就无法根据这个事件完成与用户的交互

793
来自专栏练小习的专栏

当inline-block和text-indent遇到IE6,IE7

在实际应用中,考虑到seo,很多button,icon都要用到inline-block和text-indent来处理,例如: <a href="#" class...

1766

扫码关注云+社区