java - una - Cómo ordenar recylerview por menor número/String android studio
ordenar un array java (2)
Tengo una vista de reciclaje en mi aplicación, que contiene dos textviews, una es rankTextView y otra es nameTextview. Algo como esto;
Lo que quiero hacer es ordenar esta vista de reciclador, en primer lugar en el orden de número más bajo y si hay dos mismos números, entonces quiero que se clasifique por cadenas. En la captura de pantalla anterior, tengo, por ejemplo, dos personas en el rango 1, en primer lugar quiero que la vista de reciclado las coloque en la parte superior y luego ordenarlas por String.
He buscado en línea para ver cómo puedo hacer esto, pero siendo nuevo en Android no he podido jugar / adaptar los hallazgos en mi proyecto. Por ejemplo;
Cómo ordenar cadenas en un dispositivo Android RecyclerView?
¿Qué es SortedList <T> que trabaja con RecyclerView.Adapter?
He creado un adaptador personalizado que contiene una vista de texto llamada rankTextview y otra vista de texto llamada nameTextview, como esta;
rankTextview = (TextView) itemView.findViewById(R.id.ranktextview);
nameTextview = (TextView) itemView.findViewById(R.id.nametextview);
entonces tengo un método que toma qué valor poner en estos textview como parámetro, como este;
public addPerson(String rankTextview, String personTextview,) {
this.rankTextview = rankTextview;
this.personTextview = personTextview;
}
y luego llamo a este método en mi clase principal para agregar datos, como este;
person.add(new addPerson
("1/nrank", "James Kub"));
person.add(new addPerson
("2/nrank", "Peter Hanly"));
person.add(new addPerson
("3/nrank", "Josh Penny"));
person.add(new addPerson
("1/nrank", "Danny Jackson"));
person.add(new addPerson
("3/nrank", "Brad Black"));
Ahora lo que quiero hacer es ordenar estos datos primero por orden de rango más bajo, por ejemplo, 1, 2,3 ... y si hay dos mismos números, entonces quiero ordenarlos por orden alfabético. Además, en el futuro mi aplicación contendrá puntos en lugar de rangos que serán números decimales como este. 1.1, 1.5, 1.1, 2.1, 2.5 y así sucesivamente, así que sería posible tomar en cuenta los números decimales al ordenar por rango.
Gracias de antemano y, por favor, avíseme si mi pregunta no fue lo suficientemente clara. Además, dado que tenía tantas líneas de código, no estaba seguro de qué sección proporcionar y cuáles no proporcionar, por favor avíseme si hay algún código que me falta que debería haber incluido.
EDITADO:
public void animateTo(List<ExampleModel> models) {
applyAndAnimateRemovals(models);
applyAndAnimateAdditions(models);
applyAndAnimateMovedItems(models);
}
private void applyAndAnimateRemovals(List<ExampleModel> newModels) {
for (int i = mModels.size() - 1; i >= 0; i--) {
final ExampleModel model = mModels.get(i);
if (!newModels.contains(model)) {
removeItem(i);
}
}
}
private void applyAndAnimateAdditions(List<ExampleModel> newModels) {
for (int i = 0, count = newModels.size(); i < count; i++) {
final ExampleModel model = newModels.get(i);
if (!mModels.contains(model)) { // error here, saying cannot resolve method contains
addItem(i, model);
}
}
}
private void applyAndAnimateMovedItems(List<ExampleModel> newModels) {
for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
final ExampleModel model = newModels.get(toPosition);
final int fromPosition = mModels.indexOf(model);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
public ExampleModel removeItem(int position) {
final ExampleModel model = mModels.remove(position); // Error here, saying in sortedlist cannot be applied to (int)
notifyItemRemoved(position);
return model;
}
public void addItem(int position, ExampleModel model) {
mModels.add(position, model); // Error here, saying add has private access in ''android.support.v7.util.SortedList''
notifyItemInserted(position);
}
public void moveItem(int fromPosition, int toPosition) {
final ExampleModel model = mModels.remove(fromPosition); // Error here, saying in sortedlist cannot be applied to (int)
mModels.add(toPosition, model); // Error here, saying add has private access in ''android.support.v7.util.SortedList''
notifyItemMoved(fromPosition, toPosition);
}
Hay algunas opciones para implementar la ordenación en un RecyclerView
. Por supuesto, es posible confiar en Comparable<T>
interfaces Comparable<T>
y Comparator<T>
pero, como mencionaste, también es posible explotar la SortedList<T>
definida en Android SDK.
El propósito de SortedList<T>
es simplificar la clasificación de elementos en un RecyclerView
, lo que le permite interceptar eventos importantes como "nuevo elemento agregado", "elemento eliminado", etc.
En su caso puede proceder de la siguiente manera:
Defina una clase de persona para ajustar el rango y el nombre. Tenga en cuenta que en esta versión supongo que tendrá valores enteros para el rango, pero es bastante fácil pasar al valor decimal.
class Person { private String rank; private String name; public Person(String rank, String name) { this.rank = rank; this.name = name; } // getters and setters here }
Defina una Actividad donde construir
RecyclerView
y el adaptador correspondiente. En este ejemplo, he incluido unFloatingActionButton
para insertar nuevas personas aleatorias. Como puede ver, al crear unaPerson
nueva, se invoca el métodoaddPerson
en el adaptador. Su efecto será actualizar elRecyclerView
, clasificándolo de acuerdo con los criterios definidos dentro del adaptador mismo (vea el punto 3).public class SortPersonsActivity extends AppCompatActivity { private List<Person> mPersons; private SortPersonsAdapter mPersonsAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_persons_list); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mPersons = new ArrayList<>(); mPersons.add(new Person("1/nrank", "James Kub")); mPersons.add(new Person("2/nrank", "Peter Hanly")); mPersons.add(new Person("3/nrank", "Josh Penny")); mPersons.add(new Person("1/nrank", "Danny Jackson")); mPersons.add(new Person("3/nrank", "Brad Black")); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.lst_items); recyclerView.setLayoutManager(getLayoutManager()); mPersonsAdapter = new SortPersonsAdapter(this, mPersons); recyclerView.setAdapter(mPersonsAdapter); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // building new fake person Person person = new Person( buildRandomInt(10) + "/nrank", buildRandomName(5) + " " + buildRandomName(5)); // let''s keep also basic list updated mPersons.add(person); // let''s update adapter mPersonsAdapter.addPerson(person); } }); } private RecyclerView.LayoutManager getLayoutManager() { LinearLayoutManager llm = new LinearLayoutManager(this); llm.setOrientation(LinearLayoutManager.VERTICAL); return llm; } // support method for random names and ranks here }
Implemente un adaptador RecyclerView que se base en
SortedList<Person>
. Aquí es importante observar que todas las Personas están insertadas en unaSortedList<Person>
. La creación de unaSortedList<T>
requiere unaCallback
deCallback
que se definirá para interceptar eventos, así como para definir criterios de clasificación. En nuestro caso, como puede ver, el método decompare
define criterios para clasificar personas mientras que el métodoonInserted
define qué hacer cuando se inserta una nueva persona (notifique un cambio en el conjunto de datos para actualizarRecyclerView
en este caso). Tenga en cuenta también la implementación del métodoaddPerson
descrito en el punto 2. Simplemente agrega una persona aSortedList
, porque la lógica para actualizarRecyclerView
está incrustada en el métodoCallback
onInserted
mencionado anteriormente.class SortPersonsAdapter extends RecyclerView.Adapter<SortPersonsAdapter.PersonViewHolder> { protected static class PersonViewHolder extends RecyclerView.ViewHolder { View layout; TextView txt_rank; TextView txt_full_name; public PersonViewHolder(View itemView) { super(itemView); layout = itemView; txt_rank = (TextView) itemView.findViewById(R.id.txt_rank); txt_full_name = (TextView) itemView.findViewById(R.id.txt_full_name); } } private Context mContext; private LayoutInflater mLayoutInflater; private SortedList<Person> mPersons; public SortPersonsAdapter(Context context, List<Person> persons) { mContext = context; mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mPersons = new SortedList<>(Person.class, new PersonListCallback()); mPersons.addAll(persons); } public void addPerson(Person person) { mPersons.add(person); } @Override public int getItemCount() { return mPersons.size(); } @Override public SortPersonsAdapter.PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = mLayoutInflater.inflate(R.layout.view_person_item, parent, false); return new PersonViewHolder(itemView); } @Override public void onBindViewHolder(final PersonViewHolder viewHolder, final int position) { Person person = mPersons.get(position); viewHolder.txt_rank.setText(person.getRank()); viewHolder.txt_full_name.setText(person.getName()); } /** * Implementation of callback for getting updates on person list changes. */ private class PersonListCallback extends SortedList.Callback<Person> { @Override public int compare(Person p1, Person p2) { String[] rank1 = p1.getStringRank().split("/n"); String[] rank2 = p2.getStringRank().split("/n"); int diff = Integer.parseInt(rank1[0]) - Integer.parseInt(rank2[0]); return (diff == 0) ? p1.getName().compareTo(p2.getName()) : diff; } @Override public void onInserted(int position, int count) { notifyItemInserted(position); } @Override public void onRemoved(int position, int count) { notifyItemRemoved(position); } @Override public void onMoved(int fromPosition, int toPosition) { } @Override public void onChanged(int position, int count) { } @Override public boolean areContentsTheSame(Person oldItem, Person newItem) { return false; } @Override public boolean areItemsTheSame(Person item1, Person item2) { return false; } } }
Espero que esto pueda ayudar. Aquí he puesto una implementación para su RecyclerView
, en caso de que necesite más detalles sobre el código.
public int compare(Person p1, Person p2) {
if(p1.getRank() == p2.getRank()){
return p1.getName().compareTo(p2.getName());
}else if(p1.getRank() > p2.getRank()){
return 1;
}else{
return -1;
}
}
La clasificación depende de qué resultado de comparación se devuelve. Debe devolver -1
, 0
o 1
. En el fragmento de código, todo lo que hago es verificar primero los rangos. Si tienen el mismo rango, comparo sus nombres que son String
y cada String
tiene un compareTo( )
que compara lexicográficamente dos cadenas.
Si no, los clasificamos según el rango.
Puede simplificar aún más su método compare( )
haciendo que su clase Person
implemente una interfaz Comparable
. Eso le permitirá utilizar las Collections
marco de Collections
de la caja.