title: Selecting text in TextView and invoking floating menu on long-click
body: <p>I have a <code>TextView</code> with which I am trying to associate floating context menu activated on long-click. I need the text in the <code>TextView</code> to be selectable and once the selection is made (on long-click), the selected text to be used as input to the options in the floating context menu.<br>
  On long-pressing the <code>TextView</code>, the context menu shows up before the text selection range is displayed. This is different if I use the <code>Contextual Action Bar</code> menu instead, which gets invoked on long-press only after text has been selected on screen.  </p>
  
  <p>My question(s):<br>
  1. How do I ensure text selection mode is entered before the contextual menu is invoked?  </p>
  
  <pre><code>package com.sriram.hellotts;
  
  import java.io.File;
  import java.io.Serializable;
  
  import android.app.Activity;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.os.Bundle;
  import android.os.Environment;
  import android.text.Spannable;
  import android.text.style.BackgroundColorSpan;
  import android.util.Log;
  import android.view.ActionMode;
  import android.view.ContextMenu;
  import android.view.Menu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.WindowManager;
  import android.view.ContextMenu.ContextMenuInfo;
  import android.widget.AdapterView.AdapterContextMenuInfo;
  import android.widget.Button;
  import android.widget.TextView;
  import android.widget.Toast;
  
  public class HelloTTS extends Activity {
  
      //ui elements.
      //private ImageButton playBtn;
      private Button playBtn;
      private TextView tv;
  
      private boolean longClick = false;
      private String chosenText;
  
      private int count = 1;
  
      private int REQUEST_RETURN_SETTINGS = 2;
  
      private static final int RECORDER_RETURN = 1;  //request code.
  
      //text to read.
      private String content = "MUMBAI: Whatever the general market trend, Mumbai's realty market does not stop " +
              "creating new records. In the costliest apartment deal in the country, a sea-facing duplex in a Malabar Hill" +
              " building was recently sold for Rs 57 crore or roughly Rs 1.35 lakh a sq ft., an increase of over 15% year on year." +
              " The duplex in the tony Darshan Apartments on Mount Pleasant Road was sold last month to the Bulchandanis," +
              " a prominent business family with interests in software, aluminium and real estate. They own three other duplexes " +
              "in the same complex. The family's latest acquisition (flat number 111) sits on the 9th, 10th and 11th floors of the " +
              "complex's 'A' wing, has four bedrooms and is spread over 3,510 sq ft. It comes with attached terraces of 1,386 sq ft " +
              "on the 11th and 12th floors and a covered garage of about 700 sq ft.\n" + 
              " NEW DELHI: A bunch of skulls of human ancestors dating back to 1.8 million years ago has created a storm among scientists." +
              "The discovery suggests that three human ancestor species were actually just one, with variations in features." + 
              " Five hominid skulls were found by scientists in Dmanisi, Georgia in 2005. The site is well-known for having revealed" +
              " a range of fossils. Of the five skulls, one was found to fit with a jaw bone found in 2000 at the same site." + 
              " This fitting together gave rise to a complete skull. Informally known as \"skull 5\", it \"is the most complete skull" +
              " of an adult from this date\", says Marcia Ponce de Leon, of the Anthropological Institute and Museum in Zurich, Switzerland," + 
              " and one of the authors of the study.";
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_hello_tts);
  
          //prevent window from going to sleep.
          getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  
          //hierarchical navigation.
          getActionBar().setDisplayHomeAsUpEnabled(true);
  
          //get ui elements and add relevant functionality.
          tv = (TextView) findViewById(R.id.tv);
  
          //set other features for textview.
          tv.setFocusable(true);
  
  
          Log.v(this.toString(), "Setting content for textview: " + content);
          tv.setText(content);
  
          tv.setOnLongClickListener(new View.OnLongClickListener() {
  
              @Override
              public boolean onLongClick(View v) {
                  Log.v(this.toString(), "Long click of EditText.");
                  tv.setCursorVisible(true);
                  longClick = true;
  
                  //if the TTS is speaking, pause it.
                  if(TTS != null) {
                      if(TTS.isSpeaking()) {
                          TTS.pause();
                      }
                  }
  
                  //bring up our custom action mode menu.
                  Log.v(this.toString(), "Starting actionmodecallback.");
                  v.setSelected(true);
  
                  return false;
              }
          });
  </code></pre>
  
  <p>registerForContextMenu(tv);</p>
  
  <pre><code>        tv.setOnTouchListener(new View.OnTouchListener() {
  
              @Override
              public boolean onTouch(View v, MotionEvent event) {
  
                  int action = event.getAction();
  
                  /* 
                   * On action up,if longClick was active, then chosenText etc. are taken in.
                   */
  
                  switch(action) {
                  case (MotionEvent.ACTION_DOWN):
                      Log.v(this.toString(), "Action down.");
                  break;
  
                  case (MotionEvent.ACTION_UP):
                      Log.v(this.toString(), "Action up.");
                  if(longClick) {
                      Log.v(this.toString(), "Action up after long click. Getting to selecting text.");
                      int start = tv.getSelectionStart();
                      int end = tv.getSelectionEnd();
                      Log.v(this.toString(), "Start = " + start + " and end = " + end);
                      chosenText = tv.getText().toString().substring(start, end);
                  }
                  longClick = false;  //reset longClick.
  
                  break;
  
                  case (MotionEvent.ACTION_MOVE):
                      Log.v(this.toString(), "Action move.");
                  break;
  
                  default:
                      Log.v(this.toString(), "Some other activity seen which is not being handled.");
                  break;
                  }
                  return false;
              }
          });
      }
  
      @Override
      public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
          super.onCreateContextMenu(menu, v, menuInfo);
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.options_menu, menu);
      }
  
      @Override
      public boolean onContextItemSelected(MenuItem item) {
          AdapterContextMenuInfo adcm = (AdapterContextMenuInfo) item.getMenuInfo();
          boolean result = false;
          switch(item.getItemId()) {
  
          case R.id.option1:
              Log.v(this.toString(), "Option 1 chosen.");
              result = true;
              break;
  
          case R.id.readFromHere:
              Log.v(this.toString(), "Read from here.");
              result = true;
              break;
  
          default:
              result = super.onContextItemSelected(item);
              break;
          }
          return result;
      }
  </code></pre>
  
  <p>The options menu:  </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
  
        &lt;item android:id="@+id/readFromHere"
            android:icon="@drawable/ic_launcher"
            android:title="@string/readFromHere" /&gt;
  
        &lt;item android:id="@+id/option1"
            android:icon="@drawable/ic_launcher"
            android:title="@string/record" /&gt;   
  &lt;/menu&gt;
  </code></pre>