2013-09-30 49 views
2

這主要是一個概念性問題。我在我的Activity中使用了ListFragment。其列表必須顯示這些信息之一:如何在ListView中顯示空視圖,進度視圖和數據?

  • 物品的清單
  • 如果沒有項目的空視圖
  • 「加載」視圖時的數據都是從數據庫加載

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance){ 
    if(Globals.DEBUG_LIFECYCLE) 
     Log.d("Fragment", "ONCREATEVIEW"); 

    return inflater.inflate(R.layout.kanji_list, null); 
} 

空視圖自動由框架,因爲我ListFragment上onCreateView的是創建一個像這樣的自定義視圖管理

kanji_list的佈局是這樣的一個:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:orientation="vertical" > 

<ListView android:id="@id/android:list" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:listSelector="@android:color/transparent" /> 

    <ch.shibastudio.kanjinotepad.list.KanjiListEmptyView android:id="@id/android:empty" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:text="@string/no_kanji" 
     android:visibility="gone"/> 

的的數據都是存儲在嵌在我的應用程序SQLite數據庫。當應用程序想要更新到ListView時,將使用自定義Loader來查詢數據庫並將一個Cursor返回給ListFragment。我使用自定義Loader而不是CursorLoader,因爲我不想創建ContentProvider。

所以,我希望做的是:當應用程序開始從數據庫數據更查詢時,「加載」視圖將顯示,顯示進度圖片和文本說像「獲取數據「。然後,當Loader完成其工作時,我想在ListView中顯示查詢的數據,如果沒有數據,則顯示「空白」視圖。

由於某些原因,我不想使用ProgressDialog。所以我的問題是:如何提供「加載」視圖?這裏是我的第一次,粗糙的想法:

  1. 數據更負荷期間更換由自定義視圖的ListView和顯示列表當裝載完成其工作

  1. 使用一個適配器顯示數據
  2. 使用另一個只包含一個「加載」視圖的項目的適配器
  3. 設置正確的適配器在正確的時間(當裝載機開始它的工作:myList.setAdapter(mLoadingAdapter),當裝載完成它的工作:myList.setAdapter(mDataAdapter))

任何其他的想法?你有什麼「良好的做法」暗示給我,以實現這一目標?


我找到了解決辦法,謝謝Kasra Rahjerdi和Harikris! 這是我如何做的:

首先,創建爲ListView佈局文件,空視圖和「加載」觀點:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:orientation="vertical" > 

    <LinearLayout android:id="@+id/listcontainer" 
     android:orientation="vertical" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     > 

     <ListView android:id="@id/android:list" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:listSelector="@android:color/transparent" 
      /> 

     <ch.shibastudio.kanjinotepad.list.KanjiListEmptyView android:id="@id/android:empty" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:text="@string/no_kanji" 
      android:visibility="gone"/> 
    </LinearLayout> 

    <ch.shibastudio.kanjinotepad.customviews.LoadingView android:id="@+id/loading" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" 
    android:visibility="gone" 
    /> 
</LinearLayout> 

這是創建一個容器非常重要的(這裏listContainer)爲ListView 的空視圖。我嘗試將ListView的可見性設置爲GONE,並自動將空視圖的可見性設置爲可見。看起來有一些內部代碼正在爲ListView執行此操作,因此解決方案是將它們放入容器中並完全顯示/隱藏它。

所以基本上,這個想法是:當數據加載時,我想顯示加載視圖,爲此,我通過將它的可見性隱藏到GONE來隱藏ListView容器(如果我將可見性設置爲INVISIBLE,它會保留視圖中列表的大小,使用GONE就像完全刪除它,因此,「加載」視圖可以佔據所有屏幕),並通過將其可見性顯示爲可見來顯示「加載」視圖。

在我ListFragment,我的這些看法是這樣的引用:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance){ 
    View v = inflater.inflate(R.layout.kanji_list, null); 
    mLoadingView = (LoadingView)v.findViewById(R.id.loading); 
    mListContainer = (LinearLayout)v.findViewById(R.id.listcontainer); 
    return v; 
} 

我顯示/調用此方法隱藏「裝載」的觀點:

private void setLoadingViewVisible(boolean visible){ 
    if(null != mLoadingView && null != mListContainer){ 
     mListContainer.setVisibility(visible ? View.GONE : View.VISIBLE); 
     mLoadingView.setVisibility(visible ? View.VISIBLE : View.GONE); 
    } 
} 

回答

1

看看它自帶的支持庫,副本of its source code is hereListFragment

該類別與常規的ListFragment不同,差別在onCreateView函數中可見。如果你看看它,它提供了你正在描述的內容。

  1. 它提供了一個動畫加載微調器之前,數據綁定到它。
  2. 它顯示您想要在適配器中顯示的任何數據,就像常規的ListFragment一樣。
  3. 它有一個可選的空場,你可以通過調用setEmptyText()

所以我想無論是推薦您使用的ListFragment支持庫的副本,而不是正常的設置,否則用我上面鏈接的源代碼作爲製作自己版本的課程的墊腳石。

+0

謝謝Kasra Rahjerdi,我會看看這個源代碼來獲取靈感。 – Shibakaneki

+0

通過查看您提供的鏈接中的源代碼,我找到了解決方案(現在將發佈)。謝謝Kasra Rahjerdi! – Shibakaneki

0

這聽起來像您希望列表包含一條加載消息而不會阻止用戶。我猜想你已經想出了一些方法來在數據讀取完成時異步更新列表。

反正有我想到了幾個辦法。

最簡單的可能是在你的線性佈局三個視圖和隱藏其中兩個,只露出有東西給了一個。例如,在加載時,您會隱藏id/android:list並顯示「loading ...」的視圖。加載完成後,您將隱藏「加載...」並取消隱藏列表或「空白」視圖。

另一種方法是使用3種列表項。看看Adapter。子類適配器(或者你使用的任何變體)並定義getViewTypeCount返回3.然後根據你想要顯示的內容定義getItemViewType返回三個值之一。最後,增強getView(你必須已經有了這個函數的一個版本)才能返回三種類型的視圖。

+0

我喜歡在佈局另一種觀點的想法和隱藏加載過程中ListView的,謝謝你的想法,我會給它是一個嘗試! – Shibakaneki

1

這是關係到你的應用程序的工作非常具體的問題。話雖如此,我認爲在你的情況下最好的做法是在你的fragment佈局文件中有3個視圖。 ListView每當查詢完成且項目計數爲非零時顯示項目列表。查詢進行中時將使用的另一個ProgressBar視圖。通過設置進度號(默認值爲0到100),你可以控制這個ProgressBar的知名度,或者如果您使用的是indeterminate風格進度,你可以控制它通過使用視圖的可見性是visibility。最後一個LabelTextView用於顯示零個項目時 - 控制此視圖的可見性。 ListViewTextView在你的情況下是相互排斥的,當ListView顯示時,隱藏TextView。 HTH

+0

謝謝Harikris,你的想法也指出了我的正確方向。問題結束時我發佈了我的解決方案。 – Shibakaneki

+0

@Shibakaneki如果它對你有所幫助,請在你有機會時進行投票。它也會幫助其他跟隨你的人。謝謝。 –

+0

當然!現在我需要更多的投票聲望。 – Shibakaneki

0

我建議你在onCreateView中創建包含空視圖的ListView。
然後在onStart顯示您的ProgressBar。現在開始一個線程,否則你的ProgressBar可能不會顯示,因爲下面的代碼在主線程上運行。在這個線程中,你加載你的數據,顯示它並關閉ProgressBar。

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     View view = inflater.inflate(R.layout.list_view, container, false); 

     return view; 
} 

public void onStart() { 
    super.onStart(); 

    // ProgressBar 
    new ProgressDialog(getActivity()); 
    final ProgressDialog dialog = ProgressDialog.show(getActivity(), 
      getString(R.string.loading_title), 
      getString(R.string.loading_msg), true, false); 

    // get ListView 
    final ListView myListView = (ListView) getView().findViewById(
       R.id.listView1); 

    Thread thread = new Thread() { 
     @Override 
     public void run() { 
      //load your data here (fill Adapter)! 
      loadData(); 

      getActivity().runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        // fill ListView, dismiss Dialog 
        myListView.setAdapter(yourAdapterWithData); 
        dialog.dismiss(); 
        } 
       }); 
      } 
     }; 

    thread.start(); 
} 

這只是IST示例代碼,它不會正常工作...

+0

謝謝你馬努的答案。但是,正如我在我的問題中所說的,我不想使用對話框。但是,您提出的解決方案可能是另一個應用程序的一個好主意。 – Shibakaneki

+0

對不起,我讀到你想用對話框......我的錯。這個想法仍然是一樣的:創建一個視圖(在你的案例中的圖片),啓動一個線程,一旦它完成,你可以改變視圖。這可能有助於 – Manu

+0

解決方案是在2個xml文件中聲明2個視圖,然後切換它們。在[本網站]上描述(http://www.aslingandastone.com/2010/dynamically-changing-android-views/) – Manu