Number of elements of a ListView in a TextView

1

I update the code I have now:

public class ArrayAdapterWithCountingFilter extends AppCompatActivity implements Filter.FilterListener {

ListView lvElements;
TextView tvTotals;
EditText etSearch;
StringFilterCountArrayAdapter adapter;
Filter.FilterListener listener;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_arrayadapter);



    String tokens[] =
            {"Constitución Española",
                    "Ley Orgánica 10/1995, de 23 de noviembre, del Código Penal",
                    "Real Decreto de 14 de septiembre de 1882 por el que se aprueba la Ley de Enjuiciamiento Criminal",
                    "Ley Orgánica 4/2015, de 30 de marzo, de protección de la seguridad ciudadana",
                    "Ley Orgánica 4/2000, de 11 de enero, sobre derechos y libertades de los extranjeros en España y su integración social",

            };

    lvElements = (ListView) findViewById(R.id.lvElements);
    tvTotals = (TextView) findViewById(R.id.tvTotals);
    etSearch = (EditText) findViewById(R.id.etSearch);



    etSearch.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            ArrayAdapterWithCountingFilter.this.adapter.getFilter().filter(arg0);
        }
        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {        }
        @Override
        public void afterTextChanged(Editable arg0) {  }
    });

    List data = new ArrayList();
    data.addAll(Arrays.asList(tokens));
    adapter = new StringFilterCountArrayAdapter(this,R.layout.list_text_item, R.id.tvLisTextItem,data );

    lvElements.setAdapter(adapter);
    onFilterComplete(data.size()); //El parámetro no se usa pero ya que estamos pasémoslo bien



}

@Override
public void onFilterComplete(int count) {
    String totalsText = String.format("%d/%d", adapter.getFilteredCount(), adapter.getTotalCount());
    tvTotals.setText(totalsText);

}


public static class StringFilterCountArrayAdapter extends ArrayAdapter<String>{

    private int filteredCount = getCount ();
    private List<String> objects;
    private List<String> origObjects = new ArrayList<>();
    private Filter.FilterListener callbackListener;


    public StringFilterCountArrayAdapter(@NonNull Context context, int resource, int textViewResourceId, @NonNull List<String> objects) {
        super(context, resource, textViewResourceId, objects);
        this.objects = objects;
        origObjects.addAll(objects);
        this.callbackListener = (Filter.FilterListener) context;
    }


    public int getFilteredCount() {
        return filteredCount;
    }

    public int getTotalCount(){
        return origObjects.size();
    }

    @NonNull
    @Override
    public Filter getFilter() {
        Filter filter = new Filter(){

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                if(constraint == null || constraint.toString().trim().length() == 0){
                    filterResults.values = origObjects;
                }else{
                    List<String> filtered = new ArrayList<>();
                    for(String s : origObjects){
                        if(s.contains(constraint)){
                            filtered.add(s);
                        }
                    }

                    filterResults.values = filtered;
                    filterResults.count = filtered.size();
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                objects.clear();
                objects.addAll((List<String>) results.values);
                filteredCount = results.count;
                notifyDataSetChanged();
                callbackListener.onFilterComplete(filteredCount);
            }
        };
        return filter;
    }
}

}

    
asked by Ruben Gallegos 23.10.2018 в 13:09
source

1 answer

1

To implement a Filter that also counts the results you have to extend ArrayAdapter<String> , make a @override of getFilter() to return a Filter that besides filtering, count the elements and leave the account in a new attribute ' filteredCount 'that you can recover with a getFilteredCount() .

Some implementation details:

As filtering requires removing and re-adding elements to the list that is displayed, the original list with all the elements is retuned in a separate list when creating the adapter.

The operation of the Filter is asynchronous, therefore, we need to be able to notify the activity in this case, when the filter finished filtering. For that we implemented a callback using the interface Filter.FilterListener . For this example, I had the activity implement it, but it could also have been implemented as one more object, only in that case it would have to be passed to the adapter's contstructor in an additional argument.

When building the adapter I changed the array for a List since the array brought me some problems to be able to delete the existing elements and replace them with the leaked ones.

For convenience the class StringFilterCountArrayAdapter in the code is as a static class but it could be a separate class.

ArrayAdapterWithCountingFilter Activity

public class ArrayAdapterWithCountingFilter extends AppCompatActivity implements Filter.FilterListener {

    ListView lvElements;
    TextView tvTotals;
    EditText etSearch;
    StringFilterCountArrayAdapter adapter;
    Filter.FilterListener listener;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_arrayadapter);

        String tokens[] =
                {"Constitución Española",
                        "Ley Orgánica 10/1995, de 23 de noviembre, del Código Penal",
                        "Real Decreto de 14 de septiembre de 1882 por el que se aprueba la Ley de Enjuiciamiento Criminal",
                        "Ley Orgánica 4/2015, de 30 de marzo, de protección de la seguridad ciudadana",
                        "Ley Orgánica 4/2000, de 11 de enero, sobre derechos y libertades de los extranjeros en España y su integración social",

                };

        lvElements = (ListView) findViewById(R.id.lvElements);
        tvTotals = (TextView) findViewById(R.id.tvTotals);
        etSearch = (EditText) findViewById(R.id.etSearch);

        etSearch.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
                ArrayAdapterWithCountingFilter.this.adapter.getFilter().filter(arg0);
            }
            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {        }
            @Override
            public void afterTextChanged(Editable arg0) {  }
        });

        List data = new ArrayList();
        data.addAll(Arrays.asList(tokens));
        adapter = new StringFilterCountArrayAdapter(this,R.layout.list_text_item, R.id.tvLisTextItem,data );

        lvElements.setAdapter(adapter);
        // Inicializa el TextView con la cantidad de filtrados.
        onFilterComplete(data.size()); //El parámetro no se usa pero ya que estamos pasémoslo bien
    }

    @Override
    public void onFilterComplete(int count) {
        int cantFiltrados = adapter.getFilteredCount();
        int cantTotal = adapter.getTotalCount();

        String totalsText = String.format("Mostrando: %d/%d", cantFiltrados, cantTotal);
        tvTotals.setText(totalsText);
    }


    public static class StringFilterCountArrayAdapter extends ArrayAdapter<String>{

        private int filteredCount = 0;
        private List<String> objects;
        private List<String> origObjects = new ArrayList<>();
        private Filter.FilterListener callbackListener;

        public StringFilterCountArrayAdapter(@NonNull Context context, int resource, int textViewResourceId, @NonNull List<String> objects) {
            super(context, resource, textViewResourceId, objects);
            this.objects = objects;
            origObjects.addAll(objects);
            // Setear la cantidad de filtrados inicial, que es el total de elementos de la lista
            this.filteredCount = origObjects.size();
            this.callbackListener = (Filter.FilterListener) context;
        }


        public int getFilteredCount() {
            return filteredCount;
        }

        public int getTotalCount(){
            return origObjects.size();
        }

        @NonNull
        @Override
        public Filter getFilter() {
            Filter filter = new Filter(){

                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults filterResults = new FilterResults();
                    if(constraint == null || constraint.toString().trim().length() == 0){
                        filterResults.values = origObjects;
                        // Si no hay registros filtrados volver a setear la cantidad de filtrados al total de la lista.
                        filterResults.count = origObjects.size();
                    }else{
                        List<String> filtered = new ArrayList<>();
                        for(String s : origObjects){
                            if(s.contains(constraint)){
                                filtered.add(s);
                            }
                        }

                        filterResults.values = filtered;
                        filterResults.count = filtered.size();
                    }
                    return filterResults;
                }

                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {
                    objects.clear();
                    objects.addAll((List<String>) results.values);
                    filteredCount = results.count;
                    notifyDataSetChanged();
                    callbackListener.onFilterComplete(filteredCount);
                }
            };
            return filter;
        }
    }
}

list_text_item.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tvLisTextItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

activity_array_adapter.xml

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

    <EditText
        android:id="@+id/etSearch"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <ListView
        android:id="@+id/lvElements"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8">
    </ListView>

    <TextView
        android:id="@+id/tvTotals"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </TextView>

</LinearLayout>
    
answered by 23.10.2018 / 16:24
source