Android ListViewでaddHeaderを使用する
あるアプリ
レイアウトが非常に似ています。上が検索バー、下がローテーション、カテゴリー、アクティブテーマ、おすすめ商品リスト、そして下のバーです。全部をScrollViewで実装すれば簡単ですが、下のおすすめ商品は数が不定で、結構な数になる可能性があるので
1. 商品リストにListViewを使用する場合、ScrollViewとの衝突とListViewの高さの問題を解決する必要があります。
2.ScrollViewやLinearLayoutを使った商品リストでは、画像の枚数が多い場合、キャッシュの再利用ができないため、パフォーマンスの問題が発生する場合があります。
addHeader,addFooterメソッドの使い方は非常に簡単なので、ここでは説明しません。主なポイントは、それらを使用する際の潜在的な落とし穴を文書化することです。
1. ヘッダーの表示・非表示について
ListViewには共通のHeader関連APIがあります
listView.getHeaderViewsCount();
listView.addHeaderView(View v);
listView.removeHeaderView(View v);
listView.areHeaderDividersEnabled();
4つの関数で、順番やHeaderを表示するかどうかを制御するAPIはない。
ヘッダーを隠すには?表示されなくなったヘッダーは
emoveHeaderView
再び表示する必要がある場合はどうすればよいのでしょうか。順序の問題があります。
そして、headerViewに設定することを考え
GONE
これは理論的には正しいのですが、実際には何の効果もなく、空白のプレースホルダーが残り、その親が正しいレスポンスとレイアウトになることを意味します。一般的な解決策は、headerViewを隠したい場合、送信されたchildViewのvisibilityを
GONE
表示時には、Viewの可視性を
VISIBLE
.
最終的な解答は
addHeaderViewを使用して、すべてのHeaderViewをListViewに順番に追加することから始め、HeaderViewの子ビューの可視性を制御することによって、それらが表示されるかどうかを制御します。
2. setAdapterとaddHeaderViewの実行順序について
ListViewがヘッドビューを追加したい場合、その処理は
addHeaderView
メソッドを呼び出し、ListViewにデータを設定したい場合は
setAdapter
メソッドを使用します。ただし、下位バージョンのデバイス(API<=17)では
IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
これは、HeaderViewをリストに追加しているためです。これは
setAdapter
.
ソースコードに目を通すと
API-17 (Android 4.2)
public void addHeaderView(View v, Object data, boolean isSelectable) {
if (mAdapter ! = null && ! (mAdapter instanceof HeaderViewListAdapter)) {
throw new IllegalStateException(
"Cannot add header view to list -- setAdapter has already been called.");
}
FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
// in the case of re-adding a header view, or adding one later on,
// we need to notify the observer
if (mAdapter ! = null && mDataSetObserver ! = null) {
mDataSetObserver.onChanged();
}
}
API-18 (Android 4.3)
public void addHeaderView(View v, Object data, boolean isSelectable) {
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter ! = null) { if (!
if (! (mAdapter instanceof HeaderViewListAdapter)) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
// In the case of re-adding a header view, or adding one later on,
// we need to notify the observer.
if (mDataSetObserver ! = null) {
mDataSetObserver.onChanged();
}
}
}
API<=17では、アダプターが空でなければ直接例外を投げるのに対し、API>17ではmAdapterを判定し、空であればまずmHeaderViewInfosにヘッダーを記録し、HeaderViewListAdapterの場合はsetAdapterでヘッダーとアダプターをカプセル化して、空でなければ直接HeaderViewListAdapterを構築することがわかると思います。
したがって、互換性の問題を確実にするために、settingAdapterの前にListViewにすべてのヘッダーを追加します。settingAdapterの後にHeaderViewを追加しないでください。
3. onItemClickListenにおける位置の問題
ListViewにHeaderやFooterがある場合、ListViewは内部でHeaderViewListAdapterをカプセル化することがソースコードからわかっているので、Headerを含むアイテムの位置はonItemClickListenの中で取得され、すでに我々の一般常識ではデータソースの位置ではありません。そのため、実際には
Clicked position=fetched position-headerConunt
もちろんこの方法で直接変換することもできますが、実際には HeaderViewListAdapter の内部で行ってくれています。
HeaderViewListAdapter.java
public Object getItem(int position) {
// Header (negative positions will throw an IndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (positions < numHeaders) {
return mHeaderViewInfos.get(positions).data;
}
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter ! = null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItem(adjPosition);
}
}
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).data;
}
HeaderViewListAdapter の
getItem()
HeaderViewListAdapterのadjPositionは、実データソースChinaの位置となります。
そのため、onItemClickListenでデータを取得する場合は、以下のようにします。
parent.getAdapter().getItem(position);
を使用して実体を取得します。(カスタムアダプタは
getItem()
メソッドを実行し、NULLを返さないようにします)。
のソースになります。 http://www.zhangningning.com.cn/blog/Android/Android_listview_addheade.html
関連
-
[android.os.NetworkOnMainThreadException を解決してください。
-
Android プロジェクトのライブラリに armeabi-v7a、armeabi、x86 が追加されました。
-
Jniエラー:構造体でも組合でもないものにメンバー 'FindClass' を要求する、 解決方法
-
Android 開発の問題 - いくつかのプロジェクトはすでにワークスペースに存在するため、インポートできません。
-
Android ConstraintLayout コンストレイントレイアウト
-
Androidです。ListView.addHeaderView()の使用方法と注意点
-
Androidレイアウトにおけるmargin,padding,alignの使い分けと違いについて
-
スピナー実装のダウンメニューとイベントリスニング(グラフィックモード)
-
Android TextViewの自動改行問題
-
アンドロイドについて:DescendantFocusability いくつかの使用感
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
AndroidStudioのエラーAAPT2エラーの解決:詳細のログを確認する
-
com.android.ide.common.process.ProcessException が発生する可能性のある原因。aaptの実行に失敗したエラー(解決済み)
-
android:ems="10 "の意味。
-
Androidにおけるメッセージの仕組みの分析 - 解決策。ビュー階層を作成した元のスレッドだけが、そのビューに触れることができる。
-
Android Studioで「Error:SSL peer shut down incorrectly」というエラーが表示される。
-
Android eclipseが起動できない:選択項目を起動できず、最近起動した項目もない
-
Android用ニュースアプリの簡単な実装です。
-
Androidの内部育成に磨きをかける2年間
-
android ImageViewの割り当て問題 setImageResourceとsetImageBitmap
-
AndroidManifest.xml ファイルが見つからない 解決方法