android简易封装出错时默认展示页

项目中有时候会经常遇到加载页面出错,加载页面没有数据,没有网络等等情况。这些情况需要一个特别的展示来告知用户,并且提供点击事件来重新加载等等情况。一般情况下我就直接在布局上面盖一层布局用来展示这种情况,如果只有一个页面或者极少页面需要这么做,也到简单。但是如果大量页面都需要,那我们的xml就难免会点的层级过多,不便于阅读。也有可能在preview的时候看不清我们真正需要展示的页面结构等等,基于此,本着大家一起学习的态度,我写了一个简单的代码用以封装这种情形。

其中的原理可以先阅读鸿洋大神的此篇博客 Android 源码解析 之 setContentView

private FrameLayout mFrameLayout; //此处即为android中我们setContentView时根布局的父布局
private View mDefaultView; //这是我们加载页面出错,或者没有网络时的默认布局
private View mContentView;//这是我们自己真正的业务逻辑的布局

@Override
public void setContentView(@LayoutRes int layoutResID) {
    mFrameLayout = (FrameLayout) findViewById(android.R.id.content);
        
    mDefaultView = LayoutInflater.from(activity).inflate(R.layout.default_layout, mFrameLayout, false);//这个defaul_layout是统一的错误页面展示布局
        
    mContentView = LayoutInflater.from(activity).inflate(layoutResID, mFrameLayout, false);//这个layoutResId就是我们需要的业务逻辑布局了
    
    //将出错页面和逻辑页面分别加载到mFramLayout中去,并隐藏出错页面
    mFrameLayout.addView(mContentView);
    mFrameLayout.addView(mDefaultView);
    mDefaultView.setVisibility(View.GONE);
}

/**
*
**
/
protected void showDefaultView() {
    mDefaultView.setVisibility(View.VISIBLE);
    mContentView.setVisibility(View.GONE);
}

protected void hideDefaultView() {
    mDefaultView.setVisibility(View.GONE);
    mContentView.setVisibility(View.VISIBLE);
}

R.layout.default_layout的布局文件如下

<?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:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/default_image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_luncher" />

    <TextView
        android:id="@+id/default_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这个地方空空如也" />

</LinearLayout>

那这个默认布局,我如果不一样了?比如网络加载出错的图片,和没有获取到内容的图片等等,我该如何修改呢?

    private ImageView defaultImage;
    private TextView defaultText;
    
    
    /**
     * @param drawableResID 需要更换的图标
     * @param text          需要更换的问题
     * @param listener      图标的点击事件
     *
     * 你可以只放一个drawableResID,那么此处的textView将会被隐藏,你可以选择将image和文字切成一张图,这样就简单多了。比较懒的方法
     */
    protected void initDefaultView(@DrawableRes int drawableResID, String text, View.OnClickListener listener) {
        defaultImage = (ImageView) findViewById(R.id.default_image_view);
        defaultText = (TextView) findViewById(R.id.default_text_view);

        if (drawableResID <= 0) {
            defaultImage.setVisibility(View.GONE);
        } else {
            defaultImage.setVisibility(View.VISIBLE);
            defaultImage.setImageResource(drawableResID);
        }

        if (TextUtils.isEmpty(text)) {
            defaultText.setVisibility(View.GONE);
        } else {
            defaultText.setVisibility(View.VISIBLE);
            defaultText.setText(text);
        }

        if (listener != null) {
            mDefaultView.setOnClickListener(listener);
        }
    }

如果项目中有的页面出错页面比较简单,有的比较复杂,或者布局样式根本就和默认的布局已经千差万别了,咋办?

那我们将上面的代码改一下,我们先定义一个方法,默认返回空

    protected View useCustomLayout() {
        return null;
    }
    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        mFrameLayout = (FrameLayout) findViewById(android.R.id.content);
        //此处我们先判断是否重写了useCustomLayout这个方法,如果重写了,那么就将defaultView赋值为重写返回的view即可
        if (useCustomLayout() == null) {
            mDefaultView = LayoutInflater.from(activity).inflate(R.layout.default_layout, mFrameLayout, false);
        } else {
            mDefaultView = useCustomLayout();
        }

        mContentView = LayoutInflater.from(activity).inflate(layoutResID, mFrameLayout, false);
      
        mFrameLayout.addView(mDefaultView);
        mFrameLayout.addView(mContentView);
        mDefaultView.setVisibility(View.GONE);
       
    }

完整代码如下

import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import minihou.net.library.R;

/**
 * Created by monking-macbook
 * on 2017/6/13
 * in MiniHouBaseCore
 * description: use a dialog to introduce this class
 */

public class MiniHouBaseActivity extends AppCompatActivity {

    protected Activity activity;

    private FrameLayout mFrameLayout;

    private View mDefaultView;
    private View mContentView;
    private ImageView defaultImage;
    private TextView defaultText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activity = this;
    }

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        mFrameLayout = (FrameLayout) findViewById(android.R.id.content);
        if (useCustomLayout() == null) {
            mDefaultView = LayoutInflater.from(activity).inflate(R.layout.default_layout, mFrameLayout, false);
        } else {
            mDefaultView = useCustomLayout();
        }

        mContentView = LayoutInflater.from(activity).inflate(layoutResID, mFrameLayout, false);
        mFrameLayout.addView(mDefaultView);
        mFrameLayout.addView(mContentView);
        mDefaultView.setVisibility(View.GONE);
    }

    protected View useCustomLayout() {
        return null;
    }


    /**
     * @param drawableResID 需要更换的图标
     * @param text          需要更换的问题
     * @param listener      图标的点击事件
     */
    protected void initDefaultView(@DrawableRes int drawableResID, String text, View.OnClickListener listener) {
        if (useCustomLayout() != null) {
                return;
        }
        defaultImage = (ImageView) findViewById(R.id.default_image_view);
        defaultText = (TextView) findViewById(R.id.default_text_view);

        if (drawableResID <= 0) {
            defaultImage.setVisibility(View.GONE);
        } else {
            defaultImage.setVisibility(View.VISIBLE);
            defaultImage.setImageResource(drawableResID);
        }

        if (TextUtils.isEmpty(text)) {
            defaultText.setVisibility(View.GONE);
        } else {
            defaultText.setVisibility(View.VISIBLE);
            defaultText.setText(text);
        }

        if (listener != null) {
            defaultImage.setOnClickListener(listener);
        }
    }

    /**
     * 如果加载出错show出这个默认布局并隐藏我们的业务逻辑布局
     */
    protected void showDefaultView() {
        mDefaultView.setVisibility(View.VISIBLE);
        mContentView.setVisibility(View.GONE);
    }

    /**
     * 如果没有出错,就展示我们的业务逻辑布局,并隐藏出错的布局。
     */
    protected void hideDefaultView() {
        mDefaultView.setVisibility(View.GONE);
        mContentView.setVisibility(View.VISIBLE);
    }

}

使用方法

首先创建Activity继承上述Activity,然后。。。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //千万注意得先调用setContentView
        if(true){//加载数据没出错,页面数据不为空等等
            hideDefaultView();
        }else{
            showDefaultView();
        }
    }

如果需要更改图标和文字,添加点击事件

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initDefaultView(R.drawable.new_icon, "此处空空如也", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "点击页面重试", Toast.LENGTH_SHORT).show();
            }
        });
    }       

如果需要自己定义布局

    @Override
    protected View useCustomLayout() {
        View view=LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_layout, null);
        return view;
    }

好了,有需要的同学可以去试试哦,如果有改进可以在下面留言给我。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,724评论 25 709
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 14,687评论 1 92
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,534评论 19 139
  • 很多小伙伴有在微博上私信问我蛮多问题,比如: 我的工作计划本一团乱,经常会有临时性的事情,而且也很琐碎,不知道怎么...
    手帐研究室阅读 13,526评论 64 489
  • 小时候 远方是山的那一边 江的那一头 长大后 远方是没有世故圆滑 没有城市喧嚣 到如今 蓦然才发现 远方也只不过是...
    微伊笑阅读 3,576评论 16 29