Android Java: 列表视图的自定义适配器用于滚动和过滤问题
Android Java: Custom adapter for listview for scrolling and filtering issue
我在网上搜索到我的列表视图需要一个自定义适配器来解决滚动和过滤问题。我正在使用片段,因为我的主 activity.
上有一些选项卡
我尝试实现我发现的不同代码变体,但我无法使其工作。
public class Symptoms extends Fragment {
String filename = "symptoms.txt";
private static final String TAG = "SymptomsFragment";
ReadFile rf = new ReadFile();
String[] lines;
ListView simpleList;
Context context;
private EditText filterText;
private ArrayAdapter<String> arrayAdapter;
ArrayList<String> listItems = new ArrayList<String>();
int count = 0;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View mView = inflater.inflate(R.layout.symptoms_layout,container,false);
simpleList = (ListView) mView.findViewById(R.id.list);
filterText = (EditText) mView.findViewById(R.id.editText);
try {
lines = rf.readLines(filename, getContext());
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines);
simpleList.setAdapter(arrayAdapter);
}
catch(IOException e) {
// Print out the exception that occurred
Toast.makeText(getContext(), "Unable to create "+filename+": "+e.getMessage(), Toast.LENGTH_LONG).show();
}
filterText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
arrayAdapter.getFilter().filter(s);
}
@Override
public void afterTextChanged(Editable s) { }
});
simpleList.setCacheColorHint(Color.TRANSPARENT);
simpleList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
simpleList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView)view.findViewById(android.R.id.text1);
String selectedSymptom = tv.getText().toString();
if(!listItems.contains(selectedSymptom)) {
tv.setTextColor(Color.WHITE);
tv.setBackgroundColor(Color.CYAN);
listItems.add(selectedSymptom);
}else{
tv.setTextColor(Color.BLACK);
tv.setBackgroundColor(Color.TRANSPARENT);
listItems.remove(selectedSymptom);
}
System.out.println(listItems);
}
});
return mView;
}
}
我正在读取一个文本文件并将每一行保存到一个 arraylist 元素中,我正在为我的列表视图使用 ArrayAdapter。我正在更改所选项目的背景和文本颜色。但是,当我使用 "EditText" 在列表视图上搜索时,或者当我滚动时,突出显示的元素会被打乱(仅在视觉上)。我在网上为那些在列表视图中的复选框遇到同样问题的人找到了许多解决方案,但我真的很难实施这些解决方案。在这种情况下,Custom Listview 适配器应该是什么样子的?提前致谢!
错误来自 lines = rf.readLines(filename, getContext());
您无法在主线程上读取文件,因为应用程序将出现 ANR
ANR (App Not Responding) is a state in which the app is frozen and does not respond to any user gestures or draw. Unlike unresponsive gestures which are attributed to a design decision (e.g. an image that mistakenly looks like a tappable button), ANRs usually occur due to long running code that freezes the “UI thread”.
您可以使用 AsyncTask class 在后台创建一个新线程来读取文件,然后您可以将结果绑定到 UI。
考虑使用 RecyclerView 它看起来像这样:
适配器声明:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements Filterable {
private List<IssuePOJO> myList; // search results
private List<IssuePOJO> myListFull; // all items
}
构造函数:
public RecyclerViewAdapter(Context context, List<String> myList){
this.context = context;
this.myList = myList;
myListFull = new ArrayList<>(myList); // initializing both lists with same data
}
覆盖过滤器:
@Override
public Filter getFilter() {
return listFilter;
}
private Filter listFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) { // checking if filter field is empty
filteredList.addAll(myListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (String item : myListFull) {
if (item.toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
myList.clear();
myList.addAll((List) results.values); // only this list is pressented to users inside RecyclerView, myListFull
notifyDataSetChanged();
}
};
并且在 Activity
或 Fragment
内:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
recyclerAdapter.getFilter().filter(newText);
return false;
}
});
//super.onCreateOptionsMenu(menu, inflater);
}
菜单:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.damianadamski.service.MainActivity">
<item
android:id="@+id/action_search"
android:icon="@drawable/ico_search"
android:title=""
android:tooltipText="Search..."
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
您不必添加 icon
,但您可以对其进行自定义以适合您的应用程序。
尝试更改:
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines);
收件人:
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv1 = (TextView)super.getView(position, convertView, parent);
String selectedSymptom = getItem(position);
if(listItems.contains(selectedSymptom)) {
tv1.setTextColor(Color.WHITE);
tv1.setBackgroundColor(Color.CYAN);
}else{
tv1.setTextColor(Color.BLACK);
tv1.setBackgroundColor(Color.TRANSPARENT);
}
return tv1;
}
};
希望对您有所帮助!
我在网上搜索到我的列表视图需要一个自定义适配器来解决滚动和过滤问题。我正在使用片段,因为我的主 activity.
上有一些选项卡我尝试实现我发现的不同代码变体,但我无法使其工作。
public class Symptoms extends Fragment {
String filename = "symptoms.txt";
private static final String TAG = "SymptomsFragment";
ReadFile rf = new ReadFile();
String[] lines;
ListView simpleList;
Context context;
private EditText filterText;
private ArrayAdapter<String> arrayAdapter;
ArrayList<String> listItems = new ArrayList<String>();
int count = 0;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View mView = inflater.inflate(R.layout.symptoms_layout,container,false);
simpleList = (ListView) mView.findViewById(R.id.list);
filterText = (EditText) mView.findViewById(R.id.editText);
try {
lines = rf.readLines(filename, getContext());
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines);
simpleList.setAdapter(arrayAdapter);
}
catch(IOException e) {
// Print out the exception that occurred
Toast.makeText(getContext(), "Unable to create "+filename+": "+e.getMessage(), Toast.LENGTH_LONG).show();
}
filterText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
arrayAdapter.getFilter().filter(s);
}
@Override
public void afterTextChanged(Editable s) { }
});
simpleList.setCacheColorHint(Color.TRANSPARENT);
simpleList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
simpleList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView)view.findViewById(android.R.id.text1);
String selectedSymptom = tv.getText().toString();
if(!listItems.contains(selectedSymptom)) {
tv.setTextColor(Color.WHITE);
tv.setBackgroundColor(Color.CYAN);
listItems.add(selectedSymptom);
}else{
tv.setTextColor(Color.BLACK);
tv.setBackgroundColor(Color.TRANSPARENT);
listItems.remove(selectedSymptom);
}
System.out.println(listItems);
}
});
return mView;
}
}
我正在读取一个文本文件并将每一行保存到一个 arraylist 元素中,我正在为我的列表视图使用 ArrayAdapter。我正在更改所选项目的背景和文本颜色。但是,当我使用 "EditText" 在列表视图上搜索时,或者当我滚动时,突出显示的元素会被打乱(仅在视觉上)。我在网上为那些在列表视图中的复选框遇到同样问题的人找到了许多解决方案,但我真的很难实施这些解决方案。在这种情况下,Custom Listview 适配器应该是什么样子的?提前致谢!
错误来自 lines = rf.readLines(filename, getContext());
您无法在主线程上读取文件,因为应用程序将出现 ANR
ANR (App Not Responding) is a state in which the app is frozen and does not respond to any user gestures or draw. Unlike unresponsive gestures which are attributed to a design decision (e.g. an image that mistakenly looks like a tappable button), ANRs usually occur due to long running code that freezes the “UI thread”.
您可以使用 AsyncTask class 在后台创建一个新线程来读取文件,然后您可以将结果绑定到 UI。
考虑使用 RecyclerView 它看起来像这样:
适配器声明:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements Filterable {
private List<IssuePOJO> myList; // search results
private List<IssuePOJO> myListFull; // all items
}
构造函数:
public RecyclerViewAdapter(Context context, List<String> myList){
this.context = context;
this.myList = myList;
myListFull = new ArrayList<>(myList); // initializing both lists with same data
}
覆盖过滤器:
@Override
public Filter getFilter() {
return listFilter;
}
private Filter listFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) { // checking if filter field is empty
filteredList.addAll(myListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (String item : myListFull) {
if (item.toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
myList.clear();
myList.addAll((List) results.values); // only this list is pressented to users inside RecyclerView, myListFull
notifyDataSetChanged();
}
};
并且在 Activity
或 Fragment
内:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
recyclerAdapter.getFilter().filter(newText);
return false;
}
});
//super.onCreateOptionsMenu(menu, inflater);
}
菜单:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.damianadamski.service.MainActivity">
<item
android:id="@+id/action_search"
android:icon="@drawable/ico_search"
android:title=""
android:tooltipText="Search..."
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
您不必添加 icon
,但您可以对其进行自定义以适合您的应用程序。
尝试更改:
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines);
收件人:
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines){
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv1 = (TextView)super.getView(position, convertView, parent);
String selectedSymptom = getItem(position);
if(listItems.contains(selectedSymptom)) {
tv1.setTextColor(Color.WHITE);
tv1.setBackgroundColor(Color.CYAN);
}else{
tv1.setTextColor(Color.BLACK);
tv1.setBackgroundColor(Color.TRANSPARENT);
}
return tv1;
}
};
希望对您有所帮助!