2013-01-07 13 views
44

我想有內部EDITTEXT常量文本,如:把常量文本內的EditText這應該是不可編輯的 - Android電子

http://<here_user_can_write> 

用戶應該不能夠從「http://」刪除任何字符,我搜索有關這一點,並發現這一點:

editText.setFilters(new InputFilter[] { 
    new InputFilter() { 
     public CharSequence filter(CharSequence src, int start, 
      int end, Spanned dst, int dstart, int dend) { 
      return src.length() < 1 ? dst.subSequence(dstart, dend) : ""; 
     } 
    } 
}); 

,但我不知道是否會限制用戶不能從開始刪除任何字符結束限制。我也無法理解Spanned類的使用。

如果我們可以將TextView放在EditText的內部,但是我不認爲在Android中可能,因爲兩者都是視圖,單向會是一個不錯的選擇,有可能嗎?

+0

檢查這個答案http://stackoverflow.com/a/19789317/983741 –

回答

85

你試過這種方法嗎?

final EditText edt = (EditText) findViewById(R.id.editText1); 

edt.setText("http://"); 
Selection.setSelection(edt.getText(), edt.getText().length()); 


edt.addTextChangedListener(new TextWatcher() { 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, 
       int after) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      if(!s.toString().startsWith("http://")){ 
       edt.setText("http://"); 
       Selection.setSelection(edt.getText(), edt.getText().length()); 

      } 

     } 
    }); 
+22

它的安全使用'startsWith'而不是'contains',以避免用戶移動光標位置,在常量之前輸入任何內容。 –

+0

但刪除它時,如果不從刪除按鈕移動手,文本將被刪除,我可以解決嗎? – user1767260

+0

感謝machan,這是有用的... –

9

@Rajitha Siriwardena的回答有一個小問題。 它假定了後綴,這意味着除了前後綴整個字符串已被刪除,如果你有串

http://stackoverflow.com/ 

,並嘗試刪除http://任何部分將刪除stackoverflow.com/導致只有http://

我還添加了一個檢查用戶嘗試輸入前的前綴。

@Override 
public void afterTextChanged(Editable s) { 
    String prefix = "http://"; 
    if (!s.toString().startsWith(prefix)) { 
     String cleanString; 
     String deletedPrefix = prefix.substring(0, prefix.length() - 1); 
     if (s.toString().startsWith(deletedPrefix)) { 
      cleanString = s.toString().replaceAll(deletedPrefix, ""); 
     } else { 
      cleanString = s.toString().replaceAll(prefix, ""); 
     } 
     editText.setText(prefix + cleanString); 
     editText.setSelection(prefix.length()); 
    } 
} 

注意:這不處理用戶試圖僅在前後編輯前綴本身的情況。

0

這是一個效率較低的解決方案,它應該處理在字符或單詞被刪除/插入前綴周圍的所有情況。

prefix = "http://" 
extra = "ahhttp://" 
differencePrefix(prefix, extra) = "aht" 

代碼:

public static String differencePrefix(String prefix, String extra) { 
    if (extra.length() < prefix.length()) return ""; 
    StringBuilder sb = new StringBuilder(); 
    StringBuilder eb = new StringBuilder(); 
    int p = 0; 
    for (int i = 0; i < extra.length(); i++) { 
     if (i >= prefix.length()) { 
      while(p < extra.length()) { 
       eb.append(extra.charAt(p)); 
       p++; 
      } 
      break; 
     } 
     if (p >= extra.length()) break; 
     char pchar = extra.charAt(p); 
     char ichar = prefix.charAt(i); 
     while(pchar != ichar) { 
      //check if char was deleted 
      int c = i + 1; 
      if (c < prefix.length()) { 
       char cchar = prefix.charAt(c); 
       if (cchar == pchar) { 
        break; 
       } 
      } 
      sb.append(pchar); 
      p++; 
      if (p >= extra.length()) break; 
      pchar = extra.charAt(p); 
     } 
     p++; 
    } 

    return eb.toString() + sb.toString(); 
} 

您可以使用它像這樣

editText.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) { 

    } 

    @Override 
    public void afterTextChanged(Editable s) { 
     String input = s.toString(); 
     if (!input.startsWith(prefix)) { 
      String extra = differencePrefix(prefix, input); 
      String newInput = prefix + extra; 
      editText.setText(newInput); 
      editText.setSelection(newInput.length()); 
     } 
    } 
}); 
3

你有它差不多吧,儘量

private final String PREFIX="http://"; 

editText.setFilters(new InputFilter[]{new InputFilter() { 
      @Override 
      public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int 
        dend) { 
       return dstart<PREFIX.length()?dest.subSequence(dstart,dend):null; 
      } 
     }}); 
9

這就是你能真正做到這一點與InputFilter

final String prefix = "http://" 
editText.setText(prefix); 

editText.setFilters(new InputFilter[] { 
    new InputFilter() { 
     @Override 
     public CharSequence filter(final CharSequence source, final int start, 
      final int end, final Spanned dest, final int dstart, final int dend) { 
     final int newStart = Math.max(prefix.length(), dstart); 
     final int newEnd = Math.max(prefix.length(), dend); 
     if (newStart != dstart || newEnd != dend) { 
      final SpannableStringBuilder builder = new SpannableStringBuilder(dest); 
      builder.replace(newStart, newEnd, source); 
      if (source instanceof Spanned) { 
      TextUtils.copySpansFrom(
       (Spanned) source, 0, source.length(), null, builder, newStart); 
      } 
      Selection.setSelection(builder, newStart + source.length()); 
      return builder; 
     } else { 
      return null; 
     } 
     } 
    } 
}); 

如果您還希望前綴不可選,您可以添加以下代碼。

final SpanWatcher watcher = new SpanWatcher() { 
    @Override 
    public void onSpanAdded(final Spannable text, final Object what, 
     final int start, final int end) { 
    // Nothing here. 
    } 

    @Override 
    public void onSpanRemoved(final Spannable text, final Object what, 
     final int start, final int end) { 
    // Nothing here. 
    } 

    @Override 
    public void onSpanChanged(final Spannable text, final Object what, 
     final int ostart, final int oend, final int nstart, final int nend) { 
    if (what == Selection.SELECTION_START) { 
     if (nstart < prefix.length()) { 
     final int end = Math.max(prefix.length(), Selection.getSelectionEnd(text)); 
     Selection.setSelection(text, prefix.length(), end); 
     } 
    } else if (what == Selection.SELECTION_END) { 
     final int start = Math.max(prefix.length(), Selection.getSelectionEnd(text)); 
     final int end = Math.max(start, nstart); 
     if (end != nstart) { 
     Selection.setSelection(text, start, end); 
     } 
    } 
    } 
}; 

editText.getText().setSpan(watcher, 0, 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 
+0

非常有用和正在工作 – ashishdhiman2007

0

我知道我恢復舊的文章,但我想,我已經跟這個話題這些天奮鬥社會各界分享,我發現,放置TextViewEditText不僅是完全可行的(以回答問題的第二部分),在這種情況下,當起始位置需要常量文本時更多,但也更可取。而且光標甚至不會在「可變」文本之前移動,這是一種優雅的效果。 我更喜歡這個解決方案,因爲它不會增加我的應用程序的工作量和複雜度,無論是聽衆還是任何人。

這裏是我的解決方案的示例代碼:

<RelativeLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerVertical="true" 
     android:layout_marginStart="3dp" 
     android:text="http://" /> 

    <EditText 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:inputType="textUri" 
     android:paddingStart="choose an appropriate padding" /> 
</RelativeLayout> 

通過封閉他們將被重疊在RelativeLayout的意見。 這裏的訣竅是玩EditTextandroid:paddingStart屬性,使文本剛好在TextView之後開始,android:layout_centerVertical="true"android:layout_marginStart="3dp"的屬性確保其文本與輸入的文本正確對齊,並且與開始的底線EditText(或至少這發生在使用材質主題時)。

2

使用這個定製的EditText:

public class PrefixEditText extends EditText { 

private String mPrefix = "$"; // add your prefix here for example $ 
private Rect mPrefixRect = new Rect(); // actual prefix size 

public PrefixEditText(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect); 
    mPrefixRect.right += getPaint().measureText(" "); // add some offset 

    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint()); 
} 

@Override 
public int getCompoundPaddingLeft() { 
    return super.getCompoundPaddingLeft() + mPrefixRect.width(); 
} 
} 
+0

謝謝,這非常有幫助 –

2

CODE

代碼從中通過阿里穆扎法爾

public class PrefixEditText extends AppCompatEditText { 
    float originalLeftPadding = -1; 

    public PrefixEditText(Context context) { 
     super(context); 
    } 

    public PrefixEditText(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public PrefixEditText(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     calculatePrefix(); 
    } 

    private void calculatePrefix() { 
     if (originalLeftPadding == -1) { 
      String prefix = (String) getTag(); 
      float[] widths = new float[prefix.length()]; 
      getPaint().getTextWidths(prefix, widths); 
      float textWidth = 0; 
      for (float w : widths) { 
       textWidth += w; 
      } 
      originalLeftPadding = getCompoundPaddingLeft(); 
      setPadding((int) (textWidth + originalLeftPadding), 
       getPaddingRight(), getPaddingTop(), 
       getPaddingBottom()); 
     } 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     String prefix = (String) getTag(); 
     canvas.drawText(prefix, originalLeftPadding, getLineBounds(0, null), getPaint()); 
    } 
} 

和XML添加自定義前綴爲您EDITTEXT(PREFIX不可編輯)

<com.yourClassPath.PrefixEditText 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:gravity="bottom" 
    android:textSize="14sp" 
    android:tag="€ " /> 
+0

請確保您在xml文件中使用正確的類路徑。 com.alimuzaffar.customwidgets.PrefixEditText - 如果你使用它,你的應用程序將粉碎。 –

+0

是的,我沒錯,我會編輯帖子。我的錯 –

0

我剛剛發現解決方案如何使前綴不可編輯,以及如何嘗試刪除前綴時如何保存文本。這非常接近@Rajitha Siriwardena的答案。您錯過的所有內容都是在應用更改之前保存文本。它將在afterTextChanged(...)中恢復。

代碼:

final String prefix = "http://"; 
editText.setText(prefix); 
Selection.setSelection(editText.getText(), editText.getText().length()); 

editText.addTextChangedListener(new TextWatcher() { 
    String text; 
    @Override 
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { 
     text = charSequence.toString(); 
    } 

    @Override 
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { 
    } 

    @Override 
    public void afterTextChanged(Editable editable) { 
     if (!editable.toString().startsWith(prefix)) { 
      editText.setText(text); 
      Selection.setSelection(editText.getText(), editText.getText().length()); 
     } 
    } 
}); 
相關問題