2017-02-15 6 views
1

첫 번째 문자열에 두 번째 문자열이 포함되어 있으면 문자열에서 문자열을 강조 표시하려고합니다. 문제는 부모 문자열에 악센트 부호가있는 문자가 포함되어있을 때 indexOf이 오류와 함께 첫 번째 일치 색인을 반환한다는 것입니다. filterText은 강조 표시 할 문자열입니다. 예를 들어.String indexOf UTF로 발행

@Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     View rowView = convertView; 
     ViewHolder viewHolder; 

     if (rowView == null) { 
      LayoutInflater inflater = getLayoutInflater(); 
      rowView = inflater.inflate(R.layout.list_row_search, parent, false); 
      // configure view holder 
      viewHolder = new ViewHolder(); 
      viewHolder.tvName = (TextView) rowView.findViewById(R.id.tv_name); 
      viewHolder.tvDescription = (TextView) rowView.findViewById(R.id.tv_description); 
      rowView.setTag(viewHolder); 

     } else { 
      viewHolder = (ViewHolder) convertView.getTag(); 
     } 


     viewHolder.tvName.setTypeface(tfBold); 
     viewHolder.tvDescription.setTypeface(tfRegular); 

     viewHolder.tvName.setText(getSpannedFromHtml(parkingList.get(position).getPostTitle())); 
     viewHolder.tvDescription.setText(getSpannedFromHtml(parkingList.get(position).getPostSubTitle())); 

     if(getUTF8Length(filterText) > 2){ 
      if(parkingList.get(position).getPostTitle().toLowerCase(Locale.getDefault()).contains(filterText)) { 

       Log.d("AAA", "length 1: " + parkingList.get(position).getPostTitle().toLowerCase(Locale.getDefault()).length()); 
       Log.d("AAA", "length 2: " + getUTF8Length(parkingList.get(position).getPostTitle().toLowerCase(Locale.getDefault()).toString())); 


       // Find all occurrences for the fist letter of filterText in Name 
       for (int cont = -1; (cont = parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US), cont + 1)) != -1;) { 
        String str1 = ""; 
        String str2 = ""; 
        String str3 = ""; 

        Log.d("AAA", "parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US)): " + parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US))); 

        Log.d("AAA", "parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US): " + parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US))); 

        if (cont > 0) 
         str1 = viewHolder.tvName.getText().subSequence(0, cont).toString(); 
        str2 = viewHolder.tvName.getText().subSequence(cont, cont + getUTF8Length(filterText)).toString(); 
        if ((cont + getUTF8Length(filterText)) < getUTF8Length(viewHolder.tvName.getText().toString())) 
         str3 = viewHolder.tvName.getText().subSequence(cont + getUTF8Length(filterText), getUTF8Length(viewHolder.tvName.getText().toString())).toString(); 

        String highlilightedString = str1 + "<font color = #ef6c00>" + str2 + "</font>" + str3; 
        viewHolder.tvName.setText(getSpannedFromHtml(highlilightedString)); 
       } 
      } 

      if(parkingList.get(position).getPostSubTitle().toLowerCase(Locale.getDefault()).contains(filterText)) 
       // Find all occurrences for the fist letter of filterText in Description 
       for(int cont = -1; (cont = parkingList.get(position).getPostSubTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US), cont + 1)) != -1;){ 
        String str1=""; 
        String str2=""; 
        String str3=""; 

        if(cont > 0) 
         str1 = viewHolder.tvDescription.getText().subSequence(0, cont).toString(); 
        str2 = viewHolder.tvDescription.getText().subSequence(cont, cont + filterText.length()).toString(); 
        if((cont + filterText.length()) < viewHolder.tvDescription.getText().length()) 
         str3 = viewHolder.tvDescription.getText().subSequence(cont + filterText.length(), viewHolder.tvDescription.getText().length()).toString(); 

        String highlilightedString = str1 + "<font color = #ef6c00>" + str2 + "</font>" + str3; 
        viewHolder.tvDescription.setText(getSpannedFromHtml(highlilightedString)); 
       } 
      } 

     return rowView; 
    } 

    /** 
    * 
    */ 
    private int getUTF8Length (String str) { 
     int count = 0; 

     for(int cont = 0, len = str.length(); cont < len; cont++){ 
      char ch = str.charAt(cont); 
      if(ch <= 0x7F){ 
       count++; 
      } else if(ch <= 0x7FF){ 
       cont+=2; 
      } else if(Character.isHighSurrogate(ch)){ 
       count+=4; 
       cont++; 
      } else { 
       count+=3; 
      } 
     } 

     return count; 
    } 

문제는 parkingList (위치) 예를 들어 문자열 "포켓몬 숍"을 포함하고 filterText는 "월"을 포함하는 경우, 같이 IndexOf 방법은 다음 로그 체인이 경우 예를들 수 있습니다 (9) 4 대신의 반환이다 평가 된은 "포켓 몬스터 숍"이고 내부 검색 할 문자열은 "월": 그것은 때문에 당신의 getUTF8Length()이다

D/AAA: length 1: 17 
D/AAA: length 2: 17 
D/AAA: parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US), 0): 9 
D/AAA: parkingList.get(position).getPostTitle().toLowerCase(Locale.US).indexOf(filterText.toLowerCase(Locale.US): 9 
+0

이 표현식을 기록 하시겠습니까? pstr.toLowerCase (Locale.US) 및 filterText.toLowerCase (Locale.US)? –

+0

http://stackoverflow.com/questions/2373213/java-ignore-accents-when-comparing-strings – Mikerizzo

+1

4를 볼 수 있습니다. http://ideone.com/UIYoci –

답변

0

. 길이가 잘못되었습니다. 아래 코드를 사용해보십시오. (당신은 당신의 문자열 요구 사항을 충족 할 수있는 정규식을 조정해야 할 수도 있습니다.)

private int getUTF8Length (String str) { 
    int count = 0; 

    List<String> characters=new ArrayList<String>(); 
    Pattern pat = Pattern.compile("[\\s*\\p{L}*]\\p{M}*"); 
    Matcher matcher = pat.matcher(str); 
    while (matcher.find()) { 
     characters.add(matcher.group()); 
    } 

    count = characters.size(); 
    String s = characters.toString(); 
    Log.d("LogDebug", s); 

    return count; 
} 

샘플 출력 :

D/LogDebug: [P, o, k, é, m, o, n, , S, h, o, p] 
D/LogDebug: getUTF8Length() = 12 

PS. 이 코드는 Java Unicode String length을 기반으로하며 문자열 입력 "Pokémon Shop"에 맞게 정규식을 조정합니다.