我正在使用Android中的富文本编辑器。基本上它有粗体,斜体和链接按钮,它们与EditText相关联,以改变内容的样式。如果您首先选择要设置样式的文本,然后使用此方法选择按钮,我的工作效果很好:http://developer.android.com/guide/appendix/faq/commontasks.html#selectingtext。
我要做的是让它像富文本编辑器一样工作,您可以使用按钮作为切换来根据需要设置文本样式,然后再次单击切换以停止使用风格。因此,如果我想以粗体键入“注意这个!”,我会点击“B”按钮,然后开始键入文本,我输入的所有内容都将是粗体,直到我点击“B”再次按钮。
关于如何解决此问题的任何想法?我希望我已经足够清楚了:))
答案 0 :(得分:9)
对于那些感兴趣的人,我通过在按下ToggleButton时保存光标位置(下面的'styleStart'变量)来实现这一点,然后当用户键入更多字符时,我实际上删除匹配的StyleSpan with removeSpan(),然后使用保存的原始光标位置+当前键入的字符长度,使用setSpan()重新添加它。
您还需要跟踪用户是否更改光标位置,以便不设置您不想要的文本样式。这是TextWatcher代码:
final EditText contentEdit = (EditText) findViewById(R.id.content);
contentEdit.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
//add style as the user types if a toggle button is enabled
ToggleButton boldButton = (ToggleButton) findViewById(R.id.bold);
ToggleButton emButton = (ToggleButton) findViewById(R.id.em);
ToggleButton bquoteButton = (ToggleButton) findViewById(R.id.bquote);
ToggleButton underlineButton = (ToggleButton) findViewById(R.id.underline);
ToggleButton strikeButton = (ToggleButton) findViewById(R.id.strike);
int position = Selection.getSelectionStart(contentEdit.getText());
if (position < 0){
position = 0;
}
if (position > 0){
if (styleStart > position || position > (cursorLoc + 1)){
//user changed cursor location, reset
styleStart = position - 1;
}
cursorLoc = position;
if (boldButton.isChecked()){
StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
for (int i = 0; i < ss.length; i++) {
if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
s.removeSpan(ss[i]);
}
}
s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (emButton.isChecked()){
StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
boolean exists = false;
for (int i = 0; i < ss.length; i++) {
if (ss[i].getStyle() == android.graphics.Typeface.ITALIC){
s.removeSpan(ss[i]);
}
}
s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (bquoteButton.isChecked()){
QuoteSpan[] ss = s.getSpans(styleStart, position, QuoteSpan.class);
for (int i = 0; i < ss.length; i++) {
s.removeSpan(ss[i]);
}
s.setSpan(new QuoteSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (underlineButton.isChecked()){
UnderlineSpan[] ss = s.getSpans(styleStart, position, UnderlineSpan.class);
for (int i = 0; i < ss.length; i++) {
s.removeSpan(ss[i]);
}
s.setSpan(new UnderlineSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (strikeButton.isChecked()){
StrikethroughSpan[] ss = s.getSpans(styleStart, position, StrikethroughSpan.class);
for (int i = 0; i < ss.length; i++) {
s.removeSpan(ss[i]);
}
s.setSpan(new StrikethroughSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//unused
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
//unused
}
});
这是ToggleButton点击操作之一:
final ToggleButton boldButton = (ToggleButton) findViewById(R.id.bold);
boldButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
EditText contentText = (EditText) findViewById(R.id.content);
int selectionStart = contentText.getSelectionStart();
styleStart = selectionStart;
int selectionEnd = contentText.getSelectionEnd();
if (selectionStart > selectionEnd){
int temp = selectionEnd;
selectionEnd = selectionStart;
selectionStart = temp;
}
if (selectionEnd > selectionStart)
{
Spannable str = contentText.getText();
StyleSpan[] ss = str.getSpans(selectionStart, selectionEnd, StyleSpan.class);
boolean exists = false;
for (int i = 0; i < ss.length; i++) {
if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
str.removeSpan(ss[i]);
exists = true;
}
}
if (!exists){
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
boldButton.setChecked(false);
}
}
});
可能有一个更好的解决方案,如果你有一个,很高兴听到它!
答案 1 :(得分:5)
您可以使用TextWatcher
和addTextChangedListener()
方法在他们输入的每个字符后更新样式。
好的,这只是简单的示例代码。
int mStart = -1;
// Bold onClickListener
public void onClick(View view)
{
if(mStart == -1) mStart = mEditText.getText().length();
else mStart = -1;
}
// TextWatcher
onTextChanged(CharSequence s, int start, int before, int count)
{
if(mStart > 0)
{
int end = mEditText.getText().length();
mEditText.getText().setSpan(new StyleSpan(android.graphics.Typeface.BOLD), mStart, end - mStart, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
答案 2 :(得分:1)
有一个名为android-richtexteditor的开源EditText富文本编辑器,但代码在r5中被莫名其妙地删除了。旧版本中的代码仍然存在;只需使用svn检查r4或更早版本即可访问它。该代码似乎支持斜体,下划线,颜色选择器,文本大小等。
答案 3 :(得分:1)
我知道这是一个老话题,但我的同事在网上发现了DroidWriter。我玩了一下它,它非常自我解释,非常容易使用和修改。希望这有助于任何想要创建富文本编辑器的人。
答案 4 :(得分:0)
只有一种可能性,不确定它是最好的解决方案,但是我想到了什么,谁知道它会激发你更优雅的解决方案:
也许您可以考虑在内部跟踪“文档”的分层样式结构及其所有样式标记,并在键入每个字符时重建/替换最终输出?当然,你也必须跟踪光标位置。