如何以及在哪里需要更改以在不更改 UI android 的情况下接受重音内容中的正常字符搜索
How and where exactly need to change to accept normal character search from the accented content without changing the UI android
我正在使用搜索过滤列表。该列表包含重音字符。
如果我输入 Cam,它应该支持并接受 Càm,但它不起作用。我不知道我到底需要在哪里才能在 Adapter class 中工作。
这是代码。
public class MainActivity extends AppCompatActivity {
private HighlightArrayAdapter mHighlightArrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Listview sample data
String products[] = {"Càmdoón", "córean", "Lamià", "dell", "HTC One X", "HTC Wildfire S", "HTC Sense", "HTC Sensàtion XE",
"iPhone 4S", "Samsóng Galàxy Note 800",
"Samsung Galàxy S3", "MacBook Air", "Màc Mini", "MàcBook Pro"};
ListView listView = (ListView) findViewById(R.id.listview);
EditText editText = (EditText) findViewById(R.id.inputSearch);
// Adding items to listview
mHighlightArrayAdapter = new HighlightArrayAdapter(this, R.layout.list_item, R.id.product_name, products);
listView.setAdapter(mHighlightArrayAdapter);
// Enabling Search Filter
editText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
mHighlightArrayAdapter.getFilter().filter(cs);
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
}
});
}
}
//HighlightArrayAdapter.
public class HighlightArrayAdapter extends ArrayAdapter<String> {
private final LayoutInflater mInflater;
private final Context mContext;
private final int mResource;
private List<String> mObjects;
private int mFieldId = 0;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
private final Object mLock = new Object();
private String mSearchText; // this var for highlight
Pattern mPattern;
public HighlightArrayAdapter(Context context, int resource, int textViewResourceId, String[] objects) {
super(context, resource, textViewResourceId, objects);
mContext = context;
mInflater = LayoutInflater.from(context);
mResource = resource;
mObjects = Arrays.asList(objects);
mFieldId = textViewResourceId;
}
@Override
public Context getContext() {
return mContext;
}
@Override
public int getCount() {
return mObjects.size();
}
@Override
public String getItem(int position) {
return mObjects.get(position);
}
@Override
public int getPosition(String item) {
return mObjects.indexOf(item);
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
mSearchText = "";
ArrayList<String> list;
synchronized (mLock) {
list = new ArrayList<>(mOriginalValues);
}
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
mSearchText = prefixString;
ArrayList<String> values;
synchronized (mLock) {
values = new ArrayList<>(mOriginalValues);
}
final int count = values.size();
final ArrayList<String> newValues = new ArrayList<>();
for (int i = 0; i < count; i++) {
final String value = values.get(i);
final String valueText = value.toLowerCase();
// First match against the whole, non-splitted value
if (valueText.startsWith(prefixString) || valueText.contains(prefixString)) {
newValues.add(value);
} else {
final String[] words = valueText.split(" ");
final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString) || words[k].contains(prefixString)) {
newValues.add(value);
break;
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
mObjects = (List<String>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(mResource, parent, false);
} else {
view = convertView;
}
try {
if (mFieldId == 0) {
// If no custom field is assigned, assume the whole resource is a TextView
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
text = (TextView) view.findViewById(mFieldId);
}
} catch (ClassCastException e) {
Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException(
"ArrayAdapter requires the resource ID to be a TextView", e);
}
// HIGHLIGHT...
String fullText = getItem(position);
if (mSearchText != null && !mSearchText.isEmpty()) {
int startPos = fullText.toLowerCase(Locale.US).indexOf(mSearchText.toLowerCase(Locale.US));
int endPos = startPos + mSearchText.length();
if (startPos != -1) {
//Spannable spannable = new SpannableString(removeAccents(fullText)); // i used removeAccents but not worked.
Spannable spannable = new SpannableString(fullText);
ColorStateList blueColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.BLUE});
TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, blueColor, null);
spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setText(spannable);
} else {
text.setText(fullText);
}
} else {
text.setText(fullText);
}
return view;
}
/* public static String removeAccents(String text) {
return text == null ? null : Normalizer.normalize(text, Normalizer.Form.NFD)
.replaceAll("\p{InCombiningDiacriticalMarks}+", "");
}*/
/*private SpannableStringBuilder createHighlightedString(String nodeText, int highlightColor) {
SpannableStringBuilder returnValue = new SpannableStringBuilder(nodeText);
String lowercaseNodeText = nodeText.toLowerCase();
Matcher matcher = mSearchText.matcher(lowercaseNodeText);
while (matcher.find()) {
returnValue.setSpan(new ForegroundColorSpan(highlightColor), matcher.start(0),
matcher.end(0), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
return returnValue;
}*/
}
这是屏幕截图。
场景 1:(有效)
场景 2:(当我键入 a 的普通字符时,这不起作用):
场景 3:(这在我输入重音字符时有效):
那么当我在 word 中给出普通字符搜索以支持重音字符列表接受时,如何使方案 2 工作。
我使用了 InCombiningDiacriticalMarks 但它不起作用我不知道到底需要在哪里给出。
请在适配器中帮助我 class。
您应该将过滤后的列表与无变音符号的字符串相匹配。
public static String removeDiacritics(String input) {
String out = "" + input;
out = out.replaceAll(" ", "");
out = out.replaceAll("[èéêë]", "e");
out = out.replaceAll("[ûù]", "u");
out = out.replaceAll("[ïî]", "i");
out = out.replaceAll("[àâ]", "a");
out = out.replaceAll("Ô", "o");
out = out.replaceAll("[ÈÉÊË]", "E");
out = out.replaceAll("[ÛÙ]", "U");
out = out.replaceAll("[ÏÎ]", "I");
out = out.replaceAll("[ÀÂ]", "A");
out = out.replaceAll("Ô", "O");
out = out.replaceAll("-", "");
return out;
}
这样您就不会再将 "Cam" 与 "Càm" 进行匹配,而是将 "Cam" 与 "Cam" 进行匹配。您还应该将字符串转换为小写(或大写)以允许大写。
希望对您有所帮助!
我正在使用搜索过滤列表。该列表包含重音字符。
如果我输入 Cam,它应该支持并接受 Càm,但它不起作用。我不知道我到底需要在哪里才能在 Adapter class 中工作。
这是代码。
public class MainActivity extends AppCompatActivity {
private HighlightArrayAdapter mHighlightArrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Listview sample data
String products[] = {"Càmdoón", "córean", "Lamià", "dell", "HTC One X", "HTC Wildfire S", "HTC Sense", "HTC Sensàtion XE",
"iPhone 4S", "Samsóng Galàxy Note 800",
"Samsung Galàxy S3", "MacBook Air", "Màc Mini", "MàcBook Pro"};
ListView listView = (ListView) findViewById(R.id.listview);
EditText editText = (EditText) findViewById(R.id.inputSearch);
// Adding items to listview
mHighlightArrayAdapter = new HighlightArrayAdapter(this, R.layout.list_item, R.id.product_name, products);
listView.setAdapter(mHighlightArrayAdapter);
// Enabling Search Filter
editText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
mHighlightArrayAdapter.getFilter().filter(cs);
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
}
});
}
}
//HighlightArrayAdapter.
public class HighlightArrayAdapter extends ArrayAdapter<String> {
private final LayoutInflater mInflater;
private final Context mContext;
private final int mResource;
private List<String> mObjects;
private int mFieldId = 0;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
private final Object mLock = new Object();
private String mSearchText; // this var for highlight
Pattern mPattern;
public HighlightArrayAdapter(Context context, int resource, int textViewResourceId, String[] objects) {
super(context, resource, textViewResourceId, objects);
mContext = context;
mInflater = LayoutInflater.from(context);
mResource = resource;
mObjects = Arrays.asList(objects);
mFieldId = textViewResourceId;
}
@Override
public Context getContext() {
return mContext;
}
@Override
public int getCount() {
return mObjects.size();
}
@Override
public String getItem(int position) {
return mObjects.get(position);
}
@Override
public int getPosition(String item) {
return mObjects.indexOf(item);
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
mSearchText = "";
ArrayList<String> list;
synchronized (mLock) {
list = new ArrayList<>(mOriginalValues);
}
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
mSearchText = prefixString;
ArrayList<String> values;
synchronized (mLock) {
values = new ArrayList<>(mOriginalValues);
}
final int count = values.size();
final ArrayList<String> newValues = new ArrayList<>();
for (int i = 0; i < count; i++) {
final String value = values.get(i);
final String valueText = value.toLowerCase();
// First match against the whole, non-splitted value
if (valueText.startsWith(prefixString) || valueText.contains(prefixString)) {
newValues.add(value);
} else {
final String[] words = valueText.split(" ");
final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString) || words[k].contains(prefixString)) {
newValues.add(value);
break;
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
mObjects = (List<String>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(mResource, parent, false);
} else {
view = convertView;
}
try {
if (mFieldId == 0) {
// If no custom field is assigned, assume the whole resource is a TextView
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
text = (TextView) view.findViewById(mFieldId);
}
} catch (ClassCastException e) {
Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException(
"ArrayAdapter requires the resource ID to be a TextView", e);
}
// HIGHLIGHT...
String fullText = getItem(position);
if (mSearchText != null && !mSearchText.isEmpty()) {
int startPos = fullText.toLowerCase(Locale.US).indexOf(mSearchText.toLowerCase(Locale.US));
int endPos = startPos + mSearchText.length();
if (startPos != -1) {
//Spannable spannable = new SpannableString(removeAccents(fullText)); // i used removeAccents but not worked.
Spannable spannable = new SpannableString(fullText);
ColorStateList blueColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.BLUE});
TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, blueColor, null);
spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setText(spannable);
} else {
text.setText(fullText);
}
} else {
text.setText(fullText);
}
return view;
}
/* public static String removeAccents(String text) {
return text == null ? null : Normalizer.normalize(text, Normalizer.Form.NFD)
.replaceAll("\p{InCombiningDiacriticalMarks}+", "");
}*/
/*private SpannableStringBuilder createHighlightedString(String nodeText, int highlightColor) {
SpannableStringBuilder returnValue = new SpannableStringBuilder(nodeText);
String lowercaseNodeText = nodeText.toLowerCase();
Matcher matcher = mSearchText.matcher(lowercaseNodeText);
while (matcher.find()) {
returnValue.setSpan(new ForegroundColorSpan(highlightColor), matcher.start(0),
matcher.end(0), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
return returnValue;
}*/
}
这是屏幕截图。
场景 1:(有效)
场景 2:(当我键入 a 的普通字符时,这不起作用):
场景 3:(这在我输入重音字符时有效):
那么当我在 word 中给出普通字符搜索以支持重音字符列表接受时,如何使方案 2 工作。
我使用了 InCombiningDiacriticalMarks 但它不起作用我不知道到底需要在哪里给出。
请在适配器中帮助我 class。
您应该将过滤后的列表与无变音符号的字符串相匹配。
public static String removeDiacritics(String input) {
String out = "" + input;
out = out.replaceAll(" ", "");
out = out.replaceAll("[èéêë]", "e");
out = out.replaceAll("[ûù]", "u");
out = out.replaceAll("[ïî]", "i");
out = out.replaceAll("[àâ]", "a");
out = out.replaceAll("Ô", "o");
out = out.replaceAll("[ÈÉÊË]", "E");
out = out.replaceAll("[ÛÙ]", "U");
out = out.replaceAll("[ÏÎ]", "I");
out = out.replaceAll("[ÀÂ]", "A");
out = out.replaceAll("Ô", "O");
out = out.replaceAll("-", "");
return out;
}
这样您就不会再将 "Cam" 与 "Càm" 进行匹配,而是将 "Cam" 与 "Cam" 进行匹配。您还应该将字符串转换为小写(或大写)以允许大写。
希望对您有所帮助!