1. 程式人生 > >android 載入佈局狀態封裝

android 載入佈局狀態封裝

我們經常會碰見 正在載入中,加載出錯, “暫無商品”等一系列的相似的佈局,因為我們有很多請求網路資料的頁面,我們不可能每一個頁面都寫幾個“正在載入中”等佈局吧,這時候將這些狀態的佈局封裝在一起就很有必要了。我們可以將這些封裝為一個自定佈局,然後每次操作該自定義類的方法就行了。
首先一般來說,從伺服器拉去資料之前都是“正在載入”頁面, 載入成功之後“正在載入”頁面消失,展示資料;如果載入失敗,就展示“加載出錯”頁面,同樣的“z正在載入”消失; 同理 資料為null的話,也是這樣。如下圖所示:
這裡寫圖片描述
其實這只是一種程式碼設計模式,有這種思想就行,實現起來千變萬化的。

總體思想就是:自定義FrameLayout ,然後將這FrameLayout中有三個子view,分別是:展示資料的view,載入失敗的view, 正在載入的view,資料為null的view; 其實展示資料的view是一直VISIBLE的,切記:其他三個view都要設定為match_parent,然後父佈局都要設定color ;

比如資料為null的佈局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@android:color/white"
>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="30sp" android:text="暫無資料!"/> </LinearLayout>

父佈局是match——parent 然後也設定了顏色;

在宣告SynExceptionLayout 的XML中,要如下宣告:

<?xml version="1.0" encoding="utf-8"?>
<com.app.test.testerrorproject.SynExceptionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.app.test.testerrorproject.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="有資料" android:textSize="30sp" android:textColor="@color/colorAccent" /> </LinearLayout> </com.app.test.testerrorproject.SynExceptionLayout>

可以看到SynExceptionLayout 是在最外層的,而新增的第一個view就是LinearLayout。

看下原始碼吧

package com.app.test.testerrorproject;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

/**
 * Created by ${liumengqiang} on 2017/7/17.
 */

public class SynExceptionLayout extends FrameLayout {
    /**
     * 一般的執行順序是:網路訪問前 loadShow(), 然後載入成功之後,successShow();
     * 如果加載出錯的話,errorShow();
     * 如果載入資料為null的話,emptyShow();
     * 一般來說使用emptyShow(int res),即自定義佈局
     */
    private LinearLayout emptyLinearLayout;//資料位null時,應該顯示的佈局
    private LinearLayout errorLinearLayout;//資料加載出錯時,應該顯示的佈局
    private LinearLayout loadLinearLayout;//正在載入時,應該顯示的佈局

    public static final int EMPTY_INT = 0;//回撥標記:資料為null
    public static final int ERROR_INT = 1;//回撥標記:資料出錯
    public static final int LOAD_INT = 2;//回撥標記:資料正在載入

    private OnSynExceptionListaner onSynExceptionListaner;

    public OnSynExceptionListaner getOnSynExceptionListaner() {
        return onSynExceptionListaner;
    }

    public void setOnSynExceptionListaner(OnSynExceptionListaner onSynExceptionListaner) {
        this.onSynExceptionListaner = onSynExceptionListaner;
    }

    public SynExceptionLayout(Context context) {
        super(context);
    }

    public SynExceptionLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SynExceptionLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 載入為null
     */
    public void emptyShow(){//預設載入
        empty(R.layout.empty_layout);
    }
    public void emptyShow(int res){//指定載入佈局
        empty(res);
    }
    public void empty(int res){
        if(emptyLinearLayout == null){
            emptyLinearLayout = (LinearLayout) LayoutInflater.from(getContext())
                    .inflate(res, this,false);
            emptyLinearLayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onSynExceptionListaner.onSynxceptionListener(EMPTY_INT);
                }
            });
        }
        if(errorLinearLayout == null){
            errorLinearLayout.setVisibility(View.GONE);
        }
        if(loadLinearLayout == null){
            loadLinearLayout.setVisibility(View.GONE);
        }
        /**
         * indexOfChild(View view) 方法返回該view在frameLayout中的位置索引
         * 不在裡面時,返回 -1;
         *
         * addView(View view) 將view新增到frameLayout中
         */
        if(indexOfChild(emptyLinearLayout) == -1){
            addView(emptyLinearLayout);
            emptyLinearLayout.setVisibility(View.VISIBLE);
        }else{
            emptyLinearLayout.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 加載出錯
     */
    public void errorShow(){
        error(R.layout.error_layout);
    }
    public void errorShow(int res){
        error(res);

    }
    private void error(int res){
        if(errorLinearLayout == null){
            errorLinearLayout = (LinearLayout) LayoutInflater.from(getContext())
                    .inflate(res, this,false);
            errorLinearLayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onSynExceptionListaner.onSynxceptionListener(ERROR_INT);
                }
            });
        }
        if(loadLinearLayout != null){
            loadLinearLayout.setVisibility(View.GONE);
        }
        if(emptyLinearLayout != null){
            emptyLinearLayout.setVisibility(View.GONE);
        }
        if(indexOfChild(errorLinearLayout) == -1){
            addView(errorLinearLayout);
            errorLinearLayout.setVisibility(VISIBLE);
        }else{
            errorLinearLayout.setVisibility(VISIBLE);
        }
    }

    /**
     * 正在載入
     */
    public void loadShow(){
        load(R.layout.load_layout);
    }
    public void loadShow(int res){
        load(res);
    }
    private void load(int res){
        if(loadLinearLayout == null){
            loadLinearLayout = (LinearLayout) LayoutInflater.from(getContext())
                    .inflate(res, this, false);
            loadLinearLayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onSynExceptionListaner.onSynxceptionListener(LOAD_INT);
                }
            });
        }
        if(errorLinearLayout != null){
            errorLinearLayout.setVisibility(View.GONE);
        }
        if(emptyLinearLayout  != null){
            emptyLinearLayout.setVisibility(View.GONE);
        }
        if(indexOfChild(loadLinearLayout) == -1){
            addView(loadLinearLayout);
            loadLinearLayout.setVisibility(View.VISIBLE);
        }else{
            loadLinearLayout.setVisibility(View.VISIBLE);
        }
    }

    /**
     *成功時,將三個佈局都設定為GONE
     */
    public void successShow(){
        if(emptyLinearLayout != null){
            emptyLinearLayout.setVisibility(View.GONE);
        }
        if(errorLinearLayout != null){
            errorLinearLayout.setVisibility(View.GONE);
        }
        if(loadLinearLayout != null){
            loadLinearLayout.setVisibility(View.GONE);
        }
    }

    /**
     * 回撥介面
     */
    public interface OnSynExceptionListaner{
        void onSynxceptionListener(int flug);
    }
}

附上操作SynExceptionLayout 的demo 想使用這種封裝的可以參考下