2

これは主に概念的な質問です。アクティビティで ListFragment を使用しています。そのリストには、次のいずれかの情報が表示されている必要があります。

  • アイテム一覧
  • アイテムがない場合は空のビュー
  • データベースからデータがロードされるときの「ロード中」ビュー

私の ListFragment の onCreateView は次のようなカスタム ビューを作成しているため、空のビューはフレームワークによって自動的に管理されます。

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

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 に更新する必要がある場合、カスタム ローダーを使用してデータベースにクエリを実行し、カーソルを ListFragment に返します。ContentProvider を作成したくないので、CursorLoader ではなくカスタム ローダーを使用します。

だから、私がやりたいことは次のとおりです。アプリケーションがデータベースからデータのクエリを開始すると、「読み込み中」ビューが表示され、進行状況の画像と「データの取得」のようなテキストが表示されます。次に、ローダーがジョブを終了したら、クエリされたデータを ListView に表示するか、データがない場合は「空の」ビューを表示します。

何らかの理由で ProgressDialog を使用したくありません。私の質問は次のとおりです。「読み込み中」ビューを提供するにはどうすればよいですか? これが私の最初の大まかなアイデアです。

  1. データのロード中に ListView をカスタム ビューに置き換え、ローダーがジョブを終了したときにリストを表示します。

また

  1. データの表示に 1 つのアダプターを使用する
  2. 「読み込み中」ビューであるアイテムを 1 つだけ含む別のアダプタを使用します
  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>

ListView空のビューのコンテナー (ここではlistContainer ) を作成することが非常に重要です。ListView の Visibility を GONE に設定しようとすると、空のビューの Visibility が自動的に Visible に設定されました。ListViewに対してそれを行う内部コードがあるように見えるので、解決策はそれらをコンテナに入れて完全に表示/非表示にすることでした。

つまり、基本的な考え方は次のとおりです。データが読み込まれているときに、読み込み中のビューを表示したいのですが、そのために、Visibility を GONE に設定して ListView コンテナを非表示にします (Visibility を INVISIBLE に設定すると、 GONE を使用すると、ビューを完全に削除するようなものになるため、「読み込み中」のビューはすべての画面を占有できます)、可視性を VISIBLE に設定して「読み込み中」のビューを表示します。

私の 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);
    }
}
4

4 に答える 4

1

これは、アプリケーションの動作に関連する非常に具体的な質問です。fragmentそうは言っても、あなたの場合に行う最善のことは、レイアウトファイルに3つのビューを含めることだと思います。ListViewクエリが完了し、アイテム数がゼロ以外の場合は常にアイテムのリストを表示します。ProgressBarクエリの進行中に使用される別のビュー。進行状況の数値 (デフォルトは 0 から 100) を設定することで、これの可視性を制御できます。ProgressBarまたはindeterminate、ProgressBar のスタイルを使用している場合はvisibility、ビューの可視性を使用して制御できます。そして最後に、表示するアイテムがない場合に使用されるLabelorTextViewは、このビューの可視性を制御します。ListViewあなたのケースでTextViewは相互に排他的ListViewですTextViewが隠されています。HTH

于 2013-09-30T15:21:39.557 に答える
1

ListFragmentサポート ライブラリに付属の を参照してください。そのソース コードのコピーはここにあります

このクラスは通常ListFragmentの とは異なり、その違いはonCreateView関数で見ることができます。それを見ると、まさにあなたが説明しているものを提供しています。

  1. データがバインドされる前に、アニメーション化された読み込みスピナーを提供します。
  2. 通常のListFragment.
  3. 呼び出して設定できるオプションの空のフィールドがありますsetEmptyText()

したがって、通常のものではなく、サポート ライブラリのコピーを使用することをお勧めしますListFragment。それ以外の場合は、上記でリンクしたソース コードを、クラスの独自のバージョンを作成するための足がかりとして使用します。

于 2013-09-30T15:28:49.807 に答える
0

ユーザーをブロックせずに、リストに読み込みメッセージを含めたいと思われます。データの取得が完了したときにリストを非同期に更新する方法をいくつか考え出したと思います。

とにかく、頭に浮かぶいくつかのアプローチがあります。

最も単純な方法は、線形レイアウトに 3 つのビューを配置し、そのうちの 2 つを非表示にして、表示するものがあるビューのみを公開することです。たとえば、読み込み中は id/android:list を非表示にして、「読み込み中...」というビューを公開します。読み込みが完了したら、「読み込み中...」を非表示にして、リストまたは「空の」ビューを再表示します。

もう 1 つのアプローチは、3 種類のリスト項目を使用することです。Adapterを見てください。Adapter (または使用しているそのバリアント) をサブクラス化し、3 を返すように getViewTypeCount を定義します。次に、表示する内容に応じて、3 つの値のいずれかを返すように getItemViewType を定義します。最後に、getView を拡張して (この関数のバージョンを既に持っている必要があります)、3 種類のビューを返します。

于 2013-09-30T15:17:57.060 に答える
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();
}

これは単なるサンプルコードであり、正しく動作しません...

于 2013-09-30T17:50:09.857 に答える