最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 頁面多狀態(tài)布局管理的開發(fā)

 更新時(shí)間:2018年10月15日 10:05:42   作者:關(guān)注SheHuan  
頁面多狀態(tài)布局是開發(fā)中常見的需求,即頁面在不同狀態(tài)需要顯示不同的布局,這篇文章主要介紹了Android 頁面多狀態(tài)布局管理的開發(fā),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、現(xiàn)狀

頁面多狀態(tài)布局是開發(fā)中常見的需求,即頁面在不同狀態(tài)需要顯示不同的布局,實(shí)現(xiàn)的方式也比較多,最簡單粗暴的方式就是在 XML 中先將不同狀態(tài)對(duì)應(yīng)的布局隱藏起來,根據(jù)需要改變其可見狀態(tài),如果多個(gè)界面公用相同的狀態(tài)布局,缺點(diǎn)也很明顯,繁瑣、重復(fù)、不優(yōu)雅等,類似的實(shí)現(xiàn)也可以使用 ViewStub,這樣性能會(huì)更好些。所以我們要做的就是盡可能避免這些方式所導(dǎo)致的問題,更加高效、優(yōu)雅的管理不同的狀態(tài)布局。

二、目標(biāo)

我們要實(shí)現(xiàn)的 StatusView 要實(shí)現(xiàn)的主要功能如下:

  • 可在 Activity、Fragment 、XML 中使用,可作用于XML的根布局View或其子View
  • 支持默認(rèn)的狀態(tài)布局,可進(jìn)行常規(guī)配置
  • 可自定義狀態(tài)布局
  • 狀態(tài)布局懶加載,僅在初次顯示時(shí)初始化

效果預(yù)覽如下:

preview

三、實(shí)現(xiàn)

這里只對(duì)實(shí)現(xiàn)過程中一些比較重要的點(diǎn)進(jìn)行分析。

3.1、初始化

首先有一個(gè)最重要的知識(shí)點(diǎn)需要明確,XML 布局中的每個(gè)View都有其對(duì)應(yīng)的父 View,必然在其父View中都有固定的位置,如果是 Activity 對(duì)應(yīng)的 XML,那XML根布局View的父View是誰呢?其實(shí)就是一個(gè) id 為 android.R.id.content 的 View,如果是 Fragment 對(duì)應(yīng)的 XML,那 XML 根布局 View 的父 View 可以通過 fragment.getView() 方法得到。所以現(xiàn)在我們可以得到XML 中每一個(gè)View和對(duì)應(yīng)的 LayoutParams 位置信息。

既然有了 View 和其對(duì)應(yīng)的 LayoutParams 位置信息,就可以通過其父 View 將指定的子 View 移除掉,然后將 StatusView 添加到被移除的 View 的位置,進(jìn)而就可以控制 StatusView 來切換不同的狀態(tài)布局。

簡單總結(jié)下,就是用 StatusView 替換掉要進(jìn)行多狀態(tài)布局切換的 View,這個(gè) View 可以時(shí) XML 中的任意 View。這也是直接在 Activity、Fragment 中使用 StatusView 要做的核心初始化工作。

那么 StatusView 又是個(gè)什么呢?其實(shí)就是一個(gè)繼承了 FrameLayout 的 ViewGroup,之所以要繼承 FrameLayout,因?yàn)?StatusView 此時(shí)僅僅是作為父容器存在的,并不關(guān)心內(nèi)部各種狀態(tài) View 的具體情況,所以使用 FrameLayout 就夠了,更有通用性。這樣 StatusView 也就可以在 XML 中使用了

先將上邊這部分內(nèi)容轉(zhuǎn)化成代碼:

public class StatusView extends FrameLayout {
  ......
  /**
   * 在 Activity 中的初始化方法,默認(rèn)頁面的根布局使用多狀態(tài)布局
   */
  public static StatusView init(Activity activity) {
    View contentView = ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
    return init(contentView);
  }

  /**
   * 在 Activity 中的初始化方法
   * @param viewId  使用多狀態(tài)布局的 ViewId
   */
  public static StatusView init(Activity activity, @IdRes int viewId) {
    View rootView = ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
    View contentView = rootView.findViewById(viewId);
    return init(contentView);
  }

  /**
   * 在Fragment中的初始化方法
   * @param viewId  使用多狀態(tài)布局的 ViewId
   */
  public static StatusView init(Fragment fragment, @IdRes int viewId) {
    View rootView = fragment.getView();
    View contentView = null;
    if (rootView != null) {
      contentView = rootView.findViewById(viewId);
    }
    return init(contentView);
  }

  /**
   * 用 StatusView 替換要使用多狀態(tài)布局的 View
   */
  private static StatusView init(View contentView) {
    if (contentView == null) {
      throw new RuntimeException("ContentView can not be null!");
    }
    ViewGroup parent = (ViewGroup) contentView.getParent();
    if (parent == null) {
      throw new RuntimeException("ContentView must have a parent view!");
    }
    ViewGroup.LayoutParams lp = contentView.getLayoutParams();
    int index = parent.indexOfChild(contentView);
    parent.removeView(contentView);
    StatusView statusView = new StatusView(contentView.getContext());
    statusView.addView(contentView);
    statusView.setContentView(contentView);
    parent.addView(statusView, index, lp);
    return statusView;
  }
  ......
}

如果在 XML 中使用 StatusView 如何進(jìn)行初始化呢,自然是通過 onFinishInflate() 方法:

@Override
protected void onFinishInflate() {
  super.onFinishInflate();
  if (getChildCount() == 1) {
    View view = getChildAt(0);
    setContentView(view);
  }
}

3.2、狀態(tài)布局的切換

StatusView 默認(rèn)支持 Loading、Empty、Error 三種狀態(tài)布局,加上原始的頁面內(nèi)容布局,一共四種。切換狀態(tài)布局時(shí),我們做法是直接從 StatusView 中移除掉正在顯示的狀態(tài)布局,然后添加要顯示的狀態(tài)布局:

private void switchStatusView(View statusView) {
  if (statusView == currentView) {
    return;
  }
  removeView(currentView);
  currentView = statusView;
  addView(currentView);
}

3.3、狀態(tài)布局的懶加載

在APP使用環(huán)境良好的情況下,有些狀態(tài)布局可能根本沒有顯示的機(jī)會(huì),如果在初始化時(shí)一股腦的加載出來自然不可取,影響性能,所以我們要做的就是按需加載,即僅在狀態(tài)布局初次顯示時(shí)加載并初始化,之后復(fù)用即可:

private View generateStatusView(@LayoutRes int layoutId) {
    View statusView = viewArray.get(layoutId);
    if (statusView == null) {
      statusView = inflate(layoutId);
      viewArray.put(layoutId, statusView);
      configStatusView(layoutId, statusView);
    }
    return statusView;
  }

3.4、更自由的用法

一般的多狀態(tài)布局管理都會(huì)提供默認(rèn)的 Loading、Empty、Error 三種狀態(tài)布局,并可以自定義對(duì)應(yīng)的狀態(tài)布局, 并提供對(duì)應(yīng)的開放 api。但這樣會(huì)有些局限性,如果有其它業(yè)務(wù)場(chǎng)景的狀態(tài)布局,雖然布局文件可以自定義,但原有的api方法調(diào)用起來難免會(huì)有違和感,并不友好!所以有必要在常用業(yè)務(wù)場(chǎng)景的基礎(chǔ)上再提供更加通用的api方法,并不局限于特定的場(chǎng)景。

目前的做法是用狀態(tài)布局和對(duì)應(yīng)的索引之間的關(guān)系來實(shí)現(xiàn):

// 添加指定索引對(duì)應(yīng)的狀態(tài)布局
statusView.setStatusView(int index, @LayoutRes int layoutId)
// 為指定索引的狀態(tài)布局設(shè)置初次顯示的監(jiān)聽事件,用來進(jìn)行狀態(tài)布局的相關(guān)初始化
statusView.setOnStatusViewConvertListener(int index, StatusViewConvertListener listener)
// 顯示指定索引的狀態(tài)布局
statusView.showStatusView(int index)

3.5、注意事項(xiàng)

  • 當(dāng) Fragment 布局文件的根 View 使用 StatusView 時(shí),為避免出現(xiàn)的異常問題,建議在 XML 中初始化!
  • 當(dāng)直接在 Fragment 中使用時(shí),init()方法需要在onCreateView()之后的生命周期方法中執(zhí)行!
  • 由于StatusView 繼承自 FrameLayout,所以會(huì)多一層布局嵌套。

主要的點(diǎn)就這么多了,剩下的就是些屬性配置的內(nèi)容,其實(shí)挺簡單的,更多細(xì)節(jié)和用法可參考GitHub: StatusView

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android自定義View實(shí)現(xiàn)等級(jí)滑動(dòng)條的實(shí)例

    Android自定義View實(shí)現(xiàn)等級(jí)滑動(dòng)條的實(shí)例

    這篇文章主要介紹了 Android自定義View實(shí)現(xiàn)等級(jí)滑動(dòng)條的實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Android 路徑查詢具體實(shí)現(xiàn)

    Android 路徑查詢具體實(shí)現(xiàn)

    可以通過RasterMap的getDirection()方法來查詢路徑,和查詢地址類似,路徑查詢的結(jié)果也是通過回調(diào)函數(shù)的方式來通知應(yīng)用程序的,下面的例子返回南京到北京的路徑
    2013-10-10
  • Android手勢(shì)密碼實(shí)現(xiàn)實(shí)例代碼

    Android手勢(shì)密碼實(shí)現(xiàn)實(shí)例代碼

    本篇文章主要介紹了Android手勢(shì)密碼實(shí)現(xiàn)實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易頂部導(dǎo)航欄效果

    Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易頂部導(dǎo)航欄效果

    這篇文章主要為大家詳細(xì)介紹了Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易頂部導(dǎo)航欄效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android實(shí)現(xiàn)仿微信tab高亮icon粘著手的滑動(dòng)效果

    Android實(shí)現(xiàn)仿微信tab高亮icon粘著手的滑動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)仿微信tab高亮icon粘著手的滑動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • 揭秘在ListView等AdapterView上動(dòng)態(tài)添加刪除項(xiàng)的陷阱

    揭秘在ListView等AdapterView上動(dòng)態(tài)添加刪除項(xiàng)的陷阱

    今天遇到這么個(gè)需求,需要在運(yùn)行時(shí)動(dòng)態(tài)添加ListView的item,看起來很簡單,實(shí)際操作過程中卻遇到了麻煩,下面揭秘在ListView等AdapterView上動(dòng)態(tài)添加刪除項(xiàng)的陷阱
    2016-04-04
  • Android基礎(chǔ)入門之dataBinding的簡單使用教程

    Android基礎(chǔ)入門之dataBinding的簡單使用教程

    DataBinding 是谷歌官方發(fā)布的一個(gè)框架,顧名思義即為數(shù)據(jù)綁定,下面這篇文章主要給大家介紹了關(guān)于Android基礎(chǔ)入門之dataBinding的簡單使用,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 源碼分析Android?LayoutInflater的使用

    源碼分析Android?LayoutInflater的使用

    簡單來說,LayoutInflater的工作就是將使用xml文件編寫的布局轉(zhuǎn)換成Android里的View對(duì)象,并且這也是Android中將xml布局轉(zhuǎn)換成View的唯一方式。本文將從源碼帶大家了解一下LayoutInflater的具體使用
    2023-04-04
  • 解析Android框架之Volley源碼

    解析Android框架之Volley源碼

    我們知道Volley是在2013年Google I/O大會(huì)上推出了一個(gè)新的網(wǎng)絡(luò)通信框架,他的設(shè)計(jì)目的就是為了那些請(qǐng)求數(shù)據(jù)量不是特別大,但是又是特別頻繁的網(wǎng)絡(luò)操作非常適合。但是對(duì)于數(shù)據(jù)量較大的請(qǐng)求,比如說下載一個(gè)較大的文件,Volley可能相比于其他的框架,就有點(diǎn)不足了。
    2021-06-06
  • Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間

    Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間

    這篇文章主要介紹了Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間的相關(guān)資料,需要的朋友可以參考下
    2016-05-05

最新評(píng)論

朝阳市| 万州区| 香港 | 寻乌县| 淅川县| 宁武县| 当阳市| 海城市| 嘉义县| 拉孜县| 西盟| 隆林| 昂仁县| 武宣县| 耒阳市| 平远县| 辽宁省| 札达县| 兴文县| 奇台县| 普格县| 三穗县| 佳木斯市| 乌鲁木齐市| 邯郸县| 赣州市| 如皋市| 河池市| 衡东县| 松阳县| 陈巴尔虎旗| 青铜峡市| 农安县| 报价| 弥渡县| 靖远县| 莱芜市| 洛隆县| 延吉市| 化州市| 苏尼特左旗|