android - sirve - Barra de acción de corte/copia personalizada para EditText que muestra los controles de selección de texto
ejemplos de if en android studio (3)
Tengo una aplicación en la que deseo poder mostrar un TextView (o EditText) que permite al usuario seleccionar texto, luego presionar un botón para hacer algo con ese texto. Implementar esto en versiones de Android anteriores a Honeycomb no es un problema, pero en Honeycomb y por encima de la acción predeterminada de pulsación larga es mostrar una barra de acción con las opciones Copiar / Cortar / Pegar. Puedo interceptar la pulsación larga para mostrar mi propia barra de acción, pero luego no aparece el manejador de selección de texto.
Una vez que he comenzado mi propio Modo de Acción, ¿cómo se muestran los controles de selección de texto?
Aquí está el código que estoy usando para iniciar el Modo de Acción, que funciona, excepto que no se muestran los controles de selección de texto que se muestran:
public boolean onLongClick(View v) {
if(actionMode == null)
actionMode = startActionMode(new QuoteCallback());
return true;
}
class QuoteCallback implements ActionMode.Callback {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.quote, menu);
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch(item.getItemId()) {
case R.id.quote:
Log.d(TAG, "Selected menu");
mode.finish();
// here is where I would grab the selected text
return true;
}
return false;
}
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
}
}
Descubrí la respuesta a mi propia pregunta; TextView (y, por lo tanto, EditText) tiene un método setCustomSelectionActionModeCallback()
que se debe usar en lugar de startActionMode()
. El uso de esto permite la personalización del menú utilizado por TextView para la selección de texto. Código de muestra:
bodyView.setCustomSelectionActionModeCallback(new StyleCallback());
donde StyleCallback personaliza el menú de selección de texto al eliminar Seleccionar todo y agregar algunas acciones de estilo:
class StyleCallback implements ActionMode.Callback {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
Log.d(TAG, "onCreateActionMode");
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.style, menu);
menu.removeItem(android.R.id.selectAll);
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Log.d(TAG, String.format("onActionItemClicked item=%s/%d", item.toString(), item.getItemId()));
CharacterStyle cs;
int start = bodyView.getSelectionStart();
int end = bodyView.getSelectionEnd();
SpannableStringBuilder ssb = new SpannableStringBuilder(bodyView.getText());
switch(item.getItemId()) {
case R.id.bold:
cs = new StyleSpan(Typeface.BOLD);
ssb.setSpan(cs, start, end, 1);
bodyView.setText(ssb);
return true;
case R.id.italic:
cs = new StyleSpan(Typeface.ITALIC);
ssb.setSpan(cs, start, end, 1);
bodyView.setText(ssb);
return true;
case R.id.underline:
cs = new UnderlineSpan();
ssb.setSpan(cs, start, end, 1);
bodyView.setText(ssb);
return true;
}
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
}
El XML para las adiciones de menú es:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/italic"
android:showAsAction="always"
android:icon="@drawable/italic"
android:title="Italic"/>
<item android:id="@+id/bold"
android:showAsAction="always"
android:icon="@drawable/bold"
android:title="Bold"/>
<item android:id="@+id/underline"
android:showAsAction="always"
android:icon="@drawable/underline"
android:title="Underline"/>
</menu>
La forma más sencilla de hacerlo es agregar una línea en el estilo de tema principal que haya definido en la etiqueta de application
de AndroidManifest
. Abra su estilo de tema y agregue lo siguiente:
<item name="actionModeBackground">@color/your_color</item>
O
<item name="android:actionModeBackground">@color/your_color</item>
Por ejemplo: el estilo de mi tema que he definido:
<style name="AppTheme" parent="AppBaseTheme">
<item name="calendarViewStyle">@style/Widget.Holo.CalendarView</item>
<item name="android:actionBarStyle">@style/AppTheme1</item>
<!-- below is the line you have to add -->
<item name="android:actionModeBackground">@color/black_actionBar</item>
</style>
La solución anterior es buena si desea personalizar las opciones en la barra de acciones. Pero si desea anular la barra de acciones, copiar, pegar, etc., a continuación se muestra el código ...
public class MainActivity extends Activity {
EditText editText;
private ClipboardManager myClipboard;
private ClipData myClip;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myClipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
editText = (EditText) findViewById(R.id.editText3);
myClipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
editText = (EditText) findViewById(R.id.editText3);
editText.setCustomSelectionActionModeCallback(new Callback() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case android.R.id.copy:
int min = 0;
int max = editText.getText().length();
if (editText.isFocused()) {
final int selStart = editText.getSelectionStart();
final int selEnd = editText.getSelectionEnd();
min = Math.max(0, Math.min(selStart, selEnd));
max = Math.max(0, Math.max(selStart, selEnd));
}
// Perform your definition lookup with the selected text
final CharSequence selectedText = editText.getText()
.subSequence(min, max);
String text = selectedText.toString();
myClip = ClipData.newPlainText("text", text);
myClipboard.setPrimaryClip(myClip);
Toast.makeText(getApplicationContext(), "Text Copied",
Toast.LENGTH_SHORT).show();
// Finish and close the ActionMode
mode.finish();
return true;
case android.R.id.cut:
// add your custom code to get cut functionality according
// to your requirement
return true;
case android.R.id.paste:
// add your custom code to get paste functionality according
// to your requirement
return true;
default:
break;
}
return false;
}
});
}
}