私は知っている、この質問は以前に尋ねられたが、私はそれのための実用的な答えを見ていません。
ソースデータを変更せずにListView
の一部のアイテムを非表示にする方法はありますか?
アイテムビューの表示設定を削除しようとしましたが、表示されなくなりましたが、このアイテム用に予約された場所はまだ残っています。
私も設定します:
Android:dividerHeight="0dp"
Android:divider="#FFFFFF"
成功なし。
独自のListAdapter
を記述するか、既存のサブクラスをサブクラス化できます。
ListAdapter
では、getCount()
、getItem()
およびgetItemId()
の変更された値を返すことで、表示したくない項目を除外するだけです。適切な。
次のようにアイテムを非表示にする場合:
convertView.setLayoutParams(new AbsListView.LayoutParams(-1,1));
convertView.setVisibility(View.GONE);
absListView.LayoutParams(-1,0);にはできません。
convertviewを再利用する場合は、以下に追加して高さを元に戻す必要があります。
if(convertView.getVisibility() == View.GONE) {
convertView.setVisibility(View.VISIBLE);
convertView.setLayoutParams(new AbsListView.LayoutParams(-1,-2));
}
私はsetVisibitlity(View.GONE)
を含むいくつかの解決策を試し、デフォルトのnull
ビューを膨らませましたが、それらすべてに共通の問題があり、非表示のアイテム間の仕切りが積み重なって、大きな目に見える灰色のスペースができてしまいますリスト。
ListView
がCursorAdapter
でサポートされている場合、最善の解決策はCursorWrapper
でラップすることです。
だから私の解決策(@RomanUsachevの回答 ここ に基づく)はこれです:
FilterCursorWrapper
public class FilterCursorWrapper extends CursorWrapper {
private int[] index;
private int count = 0;
private int pos = 0;
public boolean isHidden(String path) {
// the logic to check where this item should be hidden
// if (some condintion)
// return false;
// else {
// return true;
// }
return false;
}
public FilterCursorWrapper(Cursor cursor, boolean doFilter, int column) {
super(cursor);
if (doFilter) {
this.count = super.getCount();
this.index = new int[this.count];
for (int i = 0; i < this.count; i++) {
super.moveToPosition(i);
if (!isHidden(this.getString(column)))
this.index[this.pos++] = i;
}
this.count = this.pos;
this.pos = 0;
super.moveToFirst();
} else {
this.count = super.getCount();
this.index = new int[this.count];
for (int i = 0; i < this.count; i++) {
this.index[i] = i;
}
}
}
@Override
public boolean move(int offset) {
return this.moveToPosition(this.pos + offset);
}
@Override
public boolean moveToNext() {
return this.moveToPosition(this.pos + 1);
}
@Override
public boolean moveToPrevious() {
return this.moveToPosition(this.pos - 1);
}
@Override
public boolean moveToFirst() {
return this.moveToPosition(0);
}
@Override
public boolean moveToLast() {
return this.moveToPosition(this.count - 1);
}
@Override
public boolean moveToPosition(int position) {
if (position >= this.count || position < 0)
return false;
return super.moveToPosition(this.index[position]);
}
@Override
public int getCount() {
return this.count;
}
@Override
public int getPosition() {
return this.pos;
}
}
Cursor
の準備ができたら、目的の列インデックスを使用してFilterCursorWrapper
にフィードします
FilterCursorWrapper filterCursorWrapper = new FilterCursorWrapper(cursor, true,DATA_COLUMN_INDEX);
dataAdapter.changeCursor(filterCursorWrapper);
フィルタリングと並べ替えを行う場合は、すべての場所でFilterCursorWrapper
を使用することを忘れないでください。
dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
String selection = MediaStore.Video.Media.DATA + " LIKE '%" + constraint.toString().toLowerCase() + "%'";
return new FilterCursorWrapper(context.getContentResolver().query(videoMediaUri, columns, selection, null, null), true, DATA_COLUMN_INDEX);
}
});
リストを更新するには、空のフィルターでクエリを実行するのに十分です。
dataAdapter.getFilter().filter("");
そして、isHidden
メソッドのロジックを変更するだけで、非表示のアイテムを表示または非表示にするように制御できます。そして、利点は、不要な仕切りが積み重なって表示されないことです。 :-)
場合によっては簡単な解決策があります:
ビューに入力するアイテムが無効であるため、リストビューでビューを非表示にする必要があります。そのため、ビューを表示したくありません。
私のリストのアダプタでは:
public class PlanListAdapter extends BaseAdapter{
//some code here : constructor ......
// my code that create the view from the item list (one view by item ...)
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.my_layout, null);
if(my_data_are_not_valid) {
//just create an empty view
convertView = new Space(context);
}
else {
//populate the view with data here
populate(convertView);
}
return convertView;
}
//some code here to populate the view ...
}
データベースから結果を取得した後、アイテムを表示するかどうかを確認する必要があったため、バッキング配列で変更できないCursorAdapter
があります。他の投稿で説明したのと同じような方法でbindView(View v, Context context, Cursor c)
にソリューションを実装しました。 私が思う getView()でconvertViewのnull-ckeckingを実行する必要があるため、bindView()
ではなくgetView(int position, View convertView, ViewGroup parent)
メソッドをオーバーライドするのが最善の方法だと思います。
2番目のもの:_View v
_をbindView(View v, Context context, Cursor c)
に隠そうとしましたが、機能しません。調査後、非表示にする必要があることがわかりましたビュー内の各要素(テキスト、画像などを含むレイアウトを含む)
この問題を解決する簡単な方法メソッドを呼び出す前に、アクティビティのリストを解析して確認するだけ、たとえば:
for(Object a : list){
//here must be some condition for getting all items without hidden
newList += a;
}
setAdapter(newList);
私にとって簡単な解決策は、すべてのコンテンツのラッパー(例:LinearLayout)を含むカスタム行レイアウトで独自のアダプターを作成し、このラッパーの可視性をアダプターのgetView()メソッドでView.GONEに設定することでした。そのアイテムが表示されます。データセットを変更したり、2つのリストを維持したりする必要はありません。 ListViewを作成するときに、仕切りを自動的に表示しないように設定します。
Android:divider="@null"
Android:dividerHeight="0dp"
自分のディバイダーを描画します(アイテムが不要な場合は、これもGONEに設定します)。それ以外の場合は、複数の仕切りまたは複数のアイテムが非表示になっている太い灰色の線が表示されます。
独自のadapter
を作成する場合は、public View getView(int position, View convertView, ViewGroup parent)
メソッドで作成できます。これは、ある時点で非表示のアイテムを表示することを計画している場合に役立ちます。例えば:
if(item.getYourRequirement == undesiredVlue)
convertView.setVisibility(View.GONE);
else
convertView.setVisibility(View.VISIBLE);
これが役に立てば幸い
ハックは、非表示にするリストアイテムの高さを0に設定することです。
しかし、sereturが言うように、正しいアプローチはアイテムを削除してnotifyDataSetChanged()
を使用することです。このソリューションがあなたのケースでは適切ではないのはなぜですか?
ここに私の解決策:
public class MyAdapter extends ArrayAdapter<MyEntry> {
public MyAdapter(Context context, int resId) {
super(context, resId);
}
private List<MyEntry> visibleEntries() {
List<MyEntry> result = new ArrayList<MyEntry>();
int i = 0;
try {
while (true) {
if (getItem(i).isVisible())
result.add(getItem(i));
i++;
}
} catch(Exception e) {
}
return result;
}
@Override
public int getCount() {
return visibleEntries().size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout layout =
convertView == null ?
(LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.entry, parent, false) :
(LinearLayout) convertView;
MyEntry entry = visibleEntries().get(position);
...
return layout;
}
}
listview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:padding="10dp" >
<ImageView
Android:id="@+id/imgView"
Android:layout_width="40dp"
Android:layout_height="20dp"/>
<TextView
Android:id="@+id/totalTime"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:textSize="14dp"
Android:text="16 分鐘"
Android:layout_weight="1"
Android:paddingLeft="10dp" />
<TextView
Android:id="@+id/currentTime"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:textSize="14dp"
Android:text="11:46"
Android:layout_weight="1"
Android:gravity="right"
Android:paddingLeft="10dp" />
<ImageView
Android:id="@+id/img"
Android:layout_width="40dp"
Android:layout_height="20dp"
/>
</LinearLayout>
MainActivity.Java
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.findViewById(R.id.img).setVisibility(View.GONE);
}
});
それは私にとって効果的です。