it-swarm.com.de

So verbergen Sie ein Element in einer Listenansicht in Android

Ich weiß, diese Frage wurde schon früher gestellt, aber ich habe keine funktionierende Antwort darauf gesehen.

Gibt es eine Möglichkeit, einige Elemente in einer ListView auszublenden, ohne die Quelldaten zu ändern?

Ich habe versucht, die Sichtbarkeit der Elementansicht auf "gegangen" zu setzen, sie wird nicht mehr angezeigt, aber der für diesen Artikel reservierte Platz ist immer noch vorhanden.

Ich habe auch eingestellt:

Android:dividerHeight="0dp"
Android:divider="#FFFFFF"

Ohne Erfolg.

22
Tima

Sie können entweder Ihre eigene ListAdapter schreiben oder eine der vorhandenen Klassen unterteilen.

In Ihrer ListAdapter würden Sie einfach die Elemente herausfiltern, die nicht angezeigt werden sollen, indem Sie geänderte Werte für getCount(), getItem() und getItemId() entsprechend zurückgeben.

20
Carsten

Ich habe mehrere Lösungen ausprobiert, darunter setVisibitlity(View.GONE) und das Aufblasen einer Standardansicht von null, aber alle haben ein gemeinsames Problem, und das ist der Teiler zwischen versteckten Objekten, die in großen Listen einen grauen Bereich darstellen.

Wenn Ihre ListView von einer CursorAdapter unterstützt wird, ist es die beste Lösung, sie mit einer CursorWrapper zu umschließen.

Also meine Lösung (basierend auf @RomanUsachev Antwort hier ) ist diese:

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

wenn Ihre Cursor fertig ist, geben Sie FilterCursorWrapper den gewünschten Spaltenindex an

FilterCursorWrapper filterCursorWrapper = new FilterCursorWrapper(cursor, true,DATA_COLUMN_INDEX);

dataAdapter.changeCursor(filterCursorWrapper);

und wenn Sie filtern und sortieren, vergessen Sie nicht, FilterCursorWrapper überall zu verwenden:

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

und zum Aktualisieren der Liste reicht es aus, mit einem leeren Filter abzufragen:

dataAdapter.getFilter().filter("");

und Sie sind fertig, indem Sie einfach die Logik der isHidden-Methode ändern und steuern, ob ausgeblendete Elemente ein- oder ausgeblendet werden sollen. Und der Vorteil ist, dass Sie keine unerwünschten Trennwände sehen. :-)

11
Mohsen Afshin

wenn Sie das Element so ausblenden möchten:

convertView.setLayoutParams(new AbsListView.LayoutParams(-1,1));
convertView.setVisibility(View.GONE);

kann nicht AbsListView.LayoutParams (-1,0) sein;

wenn convertview wiederverwendet wird, sollten Sie Folgendes hinzufügen, um die Höhe zurückzusetzen:

if(convertView.getVisibility() == View.GONE) {
            convertView.setVisibility(View.VISIBLE);
            convertView.setLayoutParams(new AbsListView.LayoutParams(-1,-2));
        }
9
taotao

In einigen Fällen haben Sie eine einfache Lösung:

Ich muss eine Ansicht in einer Listenansicht ausblenden, da die Elemente, die in die Ansicht eingefügt werden sollen, ungültig sind. Daher möchte ich die Ansicht nicht anzeigen:

In meinem Listenadapter:

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 ...


}
4
Tobliug

Ich habe eine CursorAdapter, die nicht mit einem Backing-Array geändert werden kann, da nach dem Abrufen des Ergebnisses aus der Datenbank geprüft wurde, ob ein Element angezeigt werden soll oder nicht. Ich habe die Lösung in bindView(View v, Context context, Cursor c) auf ähnliche Weise implementiert, wie in anderen Beiträgen beschrieben. Ich denke dass der beste Weg die bindView()-Methode und nicht getView(int position, View convertView, ViewGroup parent) überschreibt, da Sie in getView () etwa null-ckecking für convertView mitführen sollten.
Die zweite Sache : Ich habe versucht, View v in bindView(View v, Context context, Cursor c) zu verbergen und es hat nicht funktioniert. Nach einer Untersuchung habe ich herausgefunden, dass ich jedes Element in der Ansicht ausblenden muss (einschließlich Layouts, die Ihre Texte, Bilder usw. enthalten).

2
Subtle Fox

Einfache Möglichkeit, dieses Problem für mich zu lösen, Vor dem Aufruf der Methode "setAdapter" müssen Sie lediglich Ihre Liste in Activity analysieren und überprüfen. Beispiel:

for(Object a : list){
//here must be some condition for getting all items without hidden
newList += a;
}
setAdapter(newList);
1
Igor Levkivskiy

Wenn Sie eine eigene adapter erstellen, können Sie dies mit der public View getView(int position, View convertView, ViewGroup parent)-Methode tun. Dies kann nützlich sein, wenn Sie planen, die unsichtbaren Elemente zu einem bestimmten Zeitpunkt anzuzeigen. Zum Beispiel:

if(item.getYourRequirement == undesiredVlue)
    convertView.setVisibility(View.GONE);
else
    convertView.setVisibility(View.VISIBLE);

Ich hoffe das hilft

1
raukodraug

Ein Hack wäre, die Höhe des Listenelements, das ausgeblendet werden soll, auf 0 zu setzen. 

Wie seretur jedoch sagt, ist der richtige Ansatz, den Gegenstand zu entfernen und notifyDataSetChanged() zu verwenden. Warum ist diese Lösung in Ihrem Fall nicht angemessen?

1
Dave

Hier meine Lösung:

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;
    }
}
0
almisoft

Für mich bestand eine einfache Lösung darin, einen eigenen Adapter mit einem benutzerdefinierten Zeilenlayout zu erstellen, der einen Wrapper mit allen Inhalten enthält (z. B. LinearLayout), und diese Wrapper-Sichtbarkeit in der getView () -Methode des Adapters auf View.GONE zu setzen, wenn ich dies nicht wollte das gezeigte Element. Es ist nicht erforderlich, den Datensatz zu ändern oder zwei Listen zu verwalten. Beim Erstellen der ListView habe ich außerdem festgelegt, dass Trennlinien nicht automatisch angezeigt werden:

    Android:divider="@null"
    Android:dividerHeight="0dp"

und zeichne meinen eigenen Teiler (den ich auch auf GONE gesetzt habe, wenn ich diesen Gegenstand nicht haben will). Andernfalls sehen Sie mehrere Trennlinien oder eine dicke graue Linie, in der mehrere Elemente ausgeblendet wurden.

0
gregko

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>

Hauptaktivität.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);

        }
    });

es ist effektiv für mich.

0
deh3215