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;
    }

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

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