如何按最低数字/字符串Android Studio对recyclerview进行排序
Posted
技术标签:
【中文标题】如何按最低数字/字符串Android Studio对recyclerview进行排序【英文标题】:How to sort recyclerview by lowest number / String Android Studio 【发布时间】:2016-04-30 03:24:18 【问题描述】:我的应用中有一个recyclerview,它包含两个textview,一个是rankTextView,另一个是nameTextview。像这样的东西;
我想要做的是对这个 recyclerview 进行排序,首先按最低数字顺序,如果有两个相同的数字,那么我希望它按字符串排序。在上面的截图中,我有两个人排名 1,首先我希望 recyclerview 将这些放在顶部,然后按 String 排序。
我已经在网上搜索过,看看我该怎么做,但是我是 android 新手,我无法在我的项目中使用/调整这些发现。例如;
How to sort Strings on an Android RecyclerView?
What is the SortedList<T> working with RecyclerView.Adapter?
我创建了一个自定义适配器,其中包含一个名为 rankTextview 的文本视图和另一个名为 nameTextview 的文本视图,如下所示;
rankTextview = (TextView) itemView.findViewById(R.id.ranktextview);
nameTextview = (TextView) itemView.findViewById(R.id.nametextview);
然后我有一个方法可以将这些文本视图中的值作为参数,像这样;
public addPerson(String rankTextview, String personTextview,)
this.rankTextview = rankTextview;
this.personTextview = personTextview;
然后我在我的主类中调用这个方法来添加数据,像这样;
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"));
现在我要做的是首先按排名最低的数字顺序排序这些数据,例如 1、2,3... 如果有两个相同的数字,那么我想按名称字母顺序排序。此外,将来我的应用程序将包含点,而不是像这样的十进制数字。 1.1, 1.5, 1.1, 2.1, 2.5 等等,那么按等级排序时是否可以考虑十进制数。
另外,由于我有这么多行代码,我不确定要提供哪些部分,不提供哪些部分,如果我缺少任何我应该包含的代码,请告诉我。
已编辑:
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);
【问题讨论】:
【参考方案1】:在RecyclerView
中有一些实现排序的选项。当然可以依赖Comparable<T>
和Comparator<T>
接口,但正如您所提到的,也可以利用Android SDK 中定义的SortedList<T>
类。
SortedList<T>
的目的是简化RecyclerView
中元素的排序,允许您拦截“添加新项目”、“删除项目”等重要事件。
在您的情况下,您可以进行如下操作:
定义一个用于包装等级和名称的 Person 类。请注意,在这个版本中,我假设排名具有整数值,但移动到十进制值非常容易。
class Person
private String rank;
private String name;
public Person(String rank, String name)
this.rank = rank;
this.name = name;
// getters and setters here
定义一个 Activity 来构建 RecyclerView
和相应的适配器。在此示例中,我包含了一个 FloatingActionButton
用于插入新的随机人员。如您所见,在创建新的Person
时,适配器上会调用方法addPerson
。它的作用是更新RecyclerView
,根据适配器本身定义的标准对其进行排序(见第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
实现一个依赖SortedList<Person>
的 RecyclerView 适配器。在这里重要的是要注意所有人员都插入到SortedList<Person>
中。创建SortedList<T>
需要定义Callback
来拦截事件以及定义排序标准。如您所见,在我们的例子中,compare
方法定义了对 Person 进行排序的标准,而 onInserted
方法定义了当插入新 Person 时要做什么(在这种情况下通知数据集更改以更新 RecyclerView
)。另请注意第 2 点描述的 addPerson
方法的实现。它只是在 SortedList
中添加了一个人,因为更新 RecyclerView
的逻辑嵌入在前面提到的 Callback
方法 onInserted
中。
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;
希望这会有所帮助。 Here 我已经为您的RecyclerView
提供了一个实现,以防您需要有关代码的更多详细信息。
【讨论】:
您好,感谢您的详细回答。在这一行上,“私有类 PersonListCallback 扩展 SortedList.CallbackSearchView
来过滤项目,最好在没有SortedList
的情况下实现排序。它没有那么复杂。您需要创建Person
类来实现Comparable
接口,然后在通知更改之前在您的列表中使用Collections.sort(mPersons)
。如果您需要,我可以为您提供更多详细信息。
@Henry 现在我看到了您编辑的帖子。 SortedList
不是List
,所以它有不同的界面。可以利用方法来添加和删除项目,但它们可能与List
中定义的方法不同。我可以尝试检查是否可以修改包含此功能的代码并保留SortedList
。
@Henry 好的没问题...我只希望最后你能解决:)【参考方案2】:
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;
排序取决于返回的比较结果。您需要返回-1
、0
或1
。在代码 sn-p 中,我所做的只是先检查排名。如果它们的等级相同,我会比较它们的名称String
s,每个String
都有一个compareTo( )
,它按字典顺序比较两个字符串。
如果不是,我们只是根据排名对它们进行排序。
您可以通过使您的Person
类实现Comparable
接口来进一步简化您的compare( )
方法。这将允许您使用开箱即用的 Collections
框架好东西。
【讨论】:
您好,感谢您的回答。因此,作为一种方法,当我在创建时调用它时,是否将 customadapter 类作为参数传递?此外,由于排名 textview 是一个字符串,因为它包含一个数字和单词,所以我收到一个错误,它说我不能在字符串上使用 >。 另外,谢谢,当我让它工作时,我已经竖起大拇指,我会将它标记为正确的。 "rank" 应该是一个浮点数。你希望它也有小数。将其存储为字符串是一个坏主意。 抱歉回复晚了,排名必须是字符串,因为它包含数字和字母,例如1\n排名(1 排名)。 另外,当我在onCreate中调用这个方法时,我传递什么值作为参数?以上是关于如何按最低数字/字符串Android Studio对recyclerview进行排序的主要内容,如果未能解决你的问题,请参考以下文章