18

I m under delphi and i use the android framework to create an edit. When i set the theme to Theme.DeviceDefault.Light.NoActionBar then i can select some text in my EditText and i have a popup with "select all/cut/copy/paste/etc" like you can see on the picture below.

However, when i select Theme.Material.Light.NoActionBar or Theme.Holo.Light.NoActionBar then i can't select any text in my EditText (i have no right or left text selection handles) and off course i don't have any copy/paste popup

Is their any way to have this copy/paste popup on Theme_Material_Light_NoActionBar ?

enter image description here Theme.DeviceDefault.Light.NoActionBar

enter image description here Theme_Material_Light_NoActionBar

enter image description here Theme.Holo.Light.NoActionBar

NOTE 1:

When i move the screen to the horizontal then the edittext take all the available space, and then i can see my right and left text selection handles like on the picture below, but i think it's because theme swap to Theme.DeviceDefault.Light.NoActionBar when i move the screen to the horizontal but i m not sure :

enter image description here

NOTE 2:

On my editText, when i do setCustomSelectionActionModeCallback(new Callback() {}) then the Callback is never called :( this is not normal i think ? What in the editText can forbid the callback ?

NOTE 2:

I can select text in all theme (but i can't copy it off course), but except in Theme.DeviceDefault.Light.NoActionBar i can't see the right and left text selection handle.

NOTE 3:

Theme.DeviceDefault.Light.NoActionBar show the right and left text selection handle only on some phones like the samsung galaxy. On some other it's didn't work.

NOTE 4:

i found partially the source of the problem! it's because i create my view via the WindowManager.addView(view, layout_params) and in this way startactionmodeforChild return null and this forbid the actionbar and the text selection handles to be show. Now if i do something like this in my edittext :

@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
    Activity host = (Activity) this.getContext();    
    return host.getWindow().getDecorView().startActionMode(callback); 
} 

then i can see the right and left text action handles (but not on marshmallow, it's work only on lollipop this i don't know why). My problem now is that the actionbar is showed, but it's showed empty :( nothing is draw inside (but i can see that the cut/copy/past control are inside in the dump view hierarchie). So now i m not looking for a way to replace this actionbar by a popup menu instead (like on the picture Theme.DeviceDefault.Light.NoActionBar). Any idea ?

zeus
  • 12,173
  • 9
  • 63
  • 184
  • 1
    This thread is old. Anyway a working example: http://www.worldbestlearningcenter.com/tips/Android-floating-context-menu.htm – boctulus Dec 24 '17 at 14:20
  • 1
    @boctulus Link is broken, here the "wayback" one https://web.archive.org/web/20170602162118/http://www.worldbestlearningcenter.com/tips/Android-floating-context-menu.htm – cmak Mar 17 '22 at 21:51

3 Answers3

5

add following in your activity

ActionMode mActionMode;

and you have to create an ActionMondeCallback interface

class ActionBarCallback implements ActionMode.Callback
    {

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.contextual_menu, menu);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

            int id = item.getItemId();
            if(id == R.id.item_delete)
            {
                tv.setText("");
                Toast.makeText(MainActivity.this,"option deleted",Toast.LENGTH_LONG);
            }
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {

        }
    }

where contextual_menu.xml is as follows with required icons

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context="com.example.letschat"
    >
    <item
        android:id="@+id/item_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="ifRoom|withText"
        android:title="Delete"
        android:titleCondensed="Delete">
    </item>
    <item
        android:id="@+id/item_delete"
        android:icon="@android:drawable/ic_menu_delete"
        app:showAsAction="ifRoom|withText"
        android:title="Delete"
        android:titleCondensed="Delete">
    </item>
    <item
        android:id="@+id/item_share"
        android:icon="@android:drawable/ic_menu_share"
        app:showAsAction="ifRoom|withText"
        android:title="Delete"
        android:titleCondensed="Delete">
    </item>
</menu>

Now Enable your Contextual ActionBar(CAB) As follows as for example here am are enabling on long click of a textview

yourtextView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                mActionMode = MainActivity.this.startActionMode(new ActionBarCallback());
                return true;
            }
        });

then you have to write your own action on click on each action event on CAB.

~Bounty Hunter More details here

W4R10CK
  • 5,502
  • 2
  • 19
  • 30
  • @Loki, did this helped? – W4R10CK Sep 18 '16 at 13:00
  • Thanks Loki, the best part about this question, my office team of 5 discussed in this topic and I googled a lot and at last I found this. – W4R10CK Sep 18 '16 at 18:12
  • if you like bounty i start another on something similar : http://stackoverflow.com/questions/39561133/why-the-floating-actionbar-copy-paste-is-under-my-edittext :) – zeus Sep 24 '16 at 21:19
4

For API level 11 or above then you can stop copy,paste,cut and custom context menus from appearing by.

edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public void onDestroyActionMode(ActionMode mode) {                  
        }

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return false;
        }
    });

Returning false from onCreateActionMode(ActionMode, Menu) will prevent the action mode from being started(Select All, Cut, Copy and Paste actions).

Solution: Override isSuggestionsEnabled and canPaste in EditText.

For the quick solution, copy the class below - this class overrides the EditText class, and blocks all events accordingly.

For the gritty details, keep reading.

The solution lies in preventing PASTE/REPLACE menu from appearing in the show() method of the (non-documented) android.widget.Editor class. Before the menu appears, a check is done to if (!canPaste && !canSuggest) return;. The two methods that are used as the basis to set these variables are both in the EditText class:

isSuggestionsEnabled() is public, and may thus be overridden. canPaste() is not, and thus must be hidden by introducing a function of the same name in the derived class. So incorporating these updates into a class that also has the setCustomSelectionActionModeCallback, and the disabled long-click, here is the full class to prevent all editing (but still display the text selection handler) for controlling the cursor:

package com.cjbs.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;


/**
 *  This is a thin veneer over EditText, with copy/paste/spell-check removed.
 */
public class NoMenuEditText extends EditText

{
    private final Context context;

    /** This is a replacement method for the base TextView class' method of the same name. This 
     * method is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup
     * appears when triggered from the text insertion handle. Returning false forces this window
     * to never appear.
     * @return false
     */
    boolean canPaste()
    {
       return false;
    }

    /** This is a replacement method for the base TextView class' method of the same name. This method
     * is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup
     * appears when triggered from the text insertion handle. Returning false forces this window
     * to never appear.
     * @return false
     */
    @Override
    public boolean isSuggestionsEnabled()
    {
        return false;
    }

    public NoMenuEditText(Context context)
    {
        super(context);
        this.context = context;
        init();
    }

    public NoMenuEditText(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        this.context = context;
        init();
    }

    public NoMenuEditText(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        this.context = context;
        init();
    }

    private void init()
    {
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        this.setLongClickable(false);
    }


    /**
     * Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing
     * by intercepting the callback that would cause it to be created, and returning false.
     */
    private class ActionModeCallbackInterceptor implements ActionMode.Callback
    {
        private final String TAG = NoMenuEditText.class.getSimpleName();

        public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; }
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
        public void onDestroyActionMode(ActionMode mode) {}
    }
} 
W4R10CK
  • 5,502
  • 2
  • 19
  • 30
  • Thanks !! Your suggestion is working, however i don't want to remove the cut/copy/past/ in opposite i want to show it ! but i understand why it's was not showing, it's because startactionmodeforChild return null ! now i override startActionMode(ActionMode.Callback callback) with ActionMode = MyActivity.startActionMode(callback); and it's work (partially). it's work partially because the actionbar is shown but it's not drawed :( i don't understand why – zeus Sep 15 '16 at 14:03
  • Lemme know if I get bounty. Hahaha – W4R10CK Sep 15 '16 at 17:06
  • i don't understand what you mean by lemme ? – zeus Sep 15 '16 at 20:46
  • Its British accent "lemme" = "let me" – W4R10CK Sep 16 '16 at 02:35
  • W4R10CK you answer was very good, but unfortunatly it's the total opposite of what i want to achieve (i want to show the action bar and you explain me how to hide it) – zeus Sep 16 '16 at 12:45
  • @loki try setting `false` to `true`. – W4R10CK Sep 16 '16 at 12:46
  • yes when i set false to true, i can see the text selection handle but not the status bar :( actually i try to create my action bar myself with Toolbar toolbar = new Toolbar(this.getContext()); and set it to the activity like MyActivity.setActionBar(toolbar); ... it's didn't work too my toolbar is not use as an action bar :( – zeus Sep 16 '16 at 12:49
  • If you want a custom bar, I just posted a answer from a link. Please follow and let me know. – W4R10CK Sep 16 '16 at 12:55
  • @loki the below answer is for custom Actionbar, just like what we get when copy paste. Try to work on it . – W4R10CK Sep 16 '16 at 13:06
2

Try to use theme Theme.AppCompat.Light.NoActionBar.
Also set android:textIsSelectable="true" on your EditText in xml file.

dzikovskyy
  • 5,027
  • 3
  • 32
  • 43
  • when i try to use Theme.AppCompat.Light.NoActionBar i receive: *No resource found that matches the given name (at 'theme' with value '@android:style/Theme.AppCompat.Light.NoActionBar'). – zeus Sep 08 '16 at 22:00
  • If possible, kindly help herehttps://stackoverflow.com/questions/58858810/clipboard-shows-a-different-label-especially-on-samsung-android-phone – Edijae Crusar Nov 14 '19 at 15:01