打造万能的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 条评论
登录 后参与评论

相关文章

来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

38610
来自专栏魂祭心

原 canvas绘制clock

5124
来自专栏hbbliyong

WPF Trigger for IsSelected in a DataTemplate for ListBox items

<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}"> <vw:HeaderSlug...

4224
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2787
来自专栏菩提树下的杨过

Flash/Flex学习笔记(23):运动学原理

先写一个公用的小球类Ball: package{ import flash.display.Sprite; //小球 类 public class B...

27310
来自专栏张善友的专栏

Silverlight + Model-View-ViewModel (MVVM)

     早在2005年,John Gossman写了一篇关于Model-View-ViewModel模式的博文,这种模式被他所在的微软的项目组用来创建Expr...

3278
来自专栏跟着阿笨一起玩NET

c#实现打印功能

3722
来自专栏飞扬的花生

jsencrypt参数前端加密c#解密

      写程序时一般是通过form表单或者ajax方式将参数提交到服务器进行验证,如何防止提交的请求不被抓包后串改,虽然无法说绝对安全却给非法提交提高了难度...

4229
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

5238
来自专栏杨龙飞前端

scrollto 到指定位置

2954

扫码关注云+社区