วิธีปิดการคัดลอก / วางจาก / ไปยัง EditText


131

ในแอปพลิเคชันของฉันมีหน้าจอการลงทะเบียนซึ่งฉันไม่ต้องการให้ผู้ใช้สามารถคัดลอก / วางข้อความลงในEditTextฟิลด์ได้ ฉันได้ตั้งค่าonLongClickListenerในแต่ละEditTextเพื่อให้เมนูบริบทแสดงคัดลอก / วาง / inputmethod และตัวเลือกอื่นไม่ปรากฏขึ้น ดังนั้นผู้ใช้จะไม่สามารถคัดลอก / วางในช่องแก้ไขได้

 OnLongClickListener mOnLongClickListener = new OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            // prevent context menu from being popped up, so that user
            // cannot copy/paste from/into any EditText fields.
            return true;
        }
    };

แต่ปัญหาจะเกิดขึ้นหากผู้ใช้เปิดใช้งานแป้นพิมพ์ของบุคคลที่สามนอกเหนือจากค่าเริ่มต้นของ Android ซึ่งอาจมีปุ่มสำหรับคัดลอก / วางหรืออาจแสดงเมนูบริบทเดียวกัน แล้วฉันจะปิดการคัดลอก / วางในสถานการณ์นั้นได้อย่างไร?

โปรดแจ้งให้เราทราบหากมีวิธีอื่นในการคัดลอก / วางด้วย (และอาจปิดการใช้งานได้อย่างไร)

ความช่วยเหลือใด ๆ จะได้รับการชื่นชม


หากการดำเนินการ "วาง" มาจาก IME แสดงว่าคุณไม่มีวิธีมาตรฐานในการแยกความแตกต่างจากการกดแป้นพิมพ์ปกติ แนวคิดอย่างหนึ่งที่ควรลองคือการวัดเวลาระหว่างการมาถึงของตัวละครแต่ละตัวและถ้าเวลาสั้นเกินไปแสดงว่าอักขระนั้นมาจากการดำเนินการ "วาง"
BitBank

ดูเหมือนจะเป็นความเหงาที่สกปรก! คุ้มค่ากับการดู
rDroid

1
ใช้ android: longClickable = "false"
Azay Gupta

คำตอบ:


112

หากคุณใช้ API ระดับ 11 ขึ้นไปคุณสามารถหยุดการคัดลอกวางตัดและเมนูบริบทที่กำหนดเองไม่ให้ปรากฏโดย

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;
            }
        });

การส่งคืนเท็จจาก onCreateActionMode (ActionMode, Menu) จะป้องกันไม่ให้โหมดการทำงานเริ่มทำงาน (เลือกทั้งหมดตัดคัดลอกและวางการกระทำ)


1
แล้ว api ระดับต่ำกว่า 13 ล่ะ
Jonathan

1
ไม่เข้าใจความคิดเห็นใด ๆ ตัวอย่างนี้ใช้งานได้ api11 + ก่อน api11 ไม่มีการคัดลอกและวาง IIRC
scottyab

28
ไม่ทำงานสำหรับฉันปุ่มวางจะปรากฏขึ้นในกรณีที่แตะที่ตัวบ่งชี้เคอร์เซอร์สีน้ำเงิน
เป็นโมฆะ

8
ยังไม่ได้ผลสำหรับฉัน เมื่อแตะสองครั้งเมนูของการคัดลอกวางจะปรากฏขึ้น
Android Killer

สิ่งนี้ไม่ทำงานอีกต่อไปบน Android 6.0 ตรวจสอบคำตอบนี้ stackoverflow.com/questions/27869983/…
has19

132

วิธีที่ดีที่สุดคือใช้:

etUsername.setLongClickable(false);

58
หรือแค่เป็น xml android:longClickable="false":)
lomza

19
ปุ่มวางจะปรากฏขึ้นในกรณีที่แตะที่ตัวบ่งชี้เคอร์เซอร์สีน้ำเงิน
เป็นโมฆะ

16
สิ่งนี้จะป้องกันไม่ให้มุมมองคลิกได้นาน แต่ยังสามารถขอตัวควบคุมการแก้ไขได้โดยการแตะสองครั้งที่ข้อความซึ่งหมายความว่าโซลูชันนี้ยังไม่สมบูรณ์ คำนึงถึงจุดประสงค์ของคุณ
Kevin Grant

1
นอกจากนี้แป้นพิมพ์ลัดยังสามารถใช้งานได้ (Ctrl + C) พร้อมแป้นพิมพ์ภายนอก
Oleg Vaskevich

สิ่งนี้ใช้ไม่ได้กับ Ice Cream Sandwich เนื่องจากตัวเลือกคลิปบอร์ดสามารถเปิดได้โดยการแตะข้อความสองครั้งและการแตะแบบยาว
Paul Wintz

44

คุณสามารถทำได้โดยปิดการใช้งานการกด EditText แบบยาว

ในการใช้งานเพียงเพิ่มบรรทัดต่อไปนี้ใน xml -

android:longClickable="false"

6
ปัญหาคือผู้ใช้แอปของฉันมีแป้นพิมพ์ของบุคคลที่สามซึ่งมีปุ่มคัดลอกและวาง
rDroid

3
ปัญหาอีกอย่างคือคุณสามารถเลือกข้อความได้โดยแตะสองครั้งและมันจะแสดงสำเนา / วางอีกครั้ง
Nikola

37

ฉันสามารถปิดใช้งานฟังก์ชันการคัดลอกและวางได้ด้วยสิ่งต่อไปนี้:

textField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

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

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

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

    public void onDestroyActionMode(ActionMode actionMode) {
    }
});

textField.setLongClickable(false);
textField.setTextIsSelectable(false);

หวังว่ามันจะเหมาะกับคุณ ;-)


นี่เป็นวิธีแก้ปัญหาเดียวกับที่ฉันลงเอยด้วยคำตอบอื่น ๆ ข้างต้น สิ่งนี้ควรถูกทำเครื่องหมายว่าเป็นวิธีแก้ปัญหาที่ถูกต้องเนื่องจากจัดการกับกรณีขอบที่คนอื่นไม่ทำ
Andrew Hoefling

2
ตัวเลือกนี้จะบล็อกสำเนา แต่คุณยังสามารถวางได้โดยคลิกที่เคอร์เซอร์
Mehul Kanzariya

12

นี่คือวิธีที่ดีที่สุดในการปิดการใช้งานการตัดการวางสำเนาของการแก้ไขข้อความในทุกเวอร์ชัน

if (android.os.Build.VERSION.SDK_INT < 11) {
        editText.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {

            @Override
            public void onCreateContextMenu(ContextMenu menu, View v,
                    ContextMenuInfo menuInfo) {
                // TODO Auto-generated method stub
                menu.clear();
            }
        });
    } else {
        editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                // TODO Auto-generated method stub
                return false;
            }

            public void onDestroyActionMode(ActionMode mode) {
                // TODO Auto-generated method stub

            }

            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // TODO Auto-generated method stub
                return false;
            }

            public boolean onActionItemClicked(ActionMode mode,
                    MenuItem item) {
                // TODO Auto-generated method stub
                return false;
            }
        });
    }

สิ่งนี้ใช้ได้ผลสำหรับฉันฉันต้องเพิ่ม @TargetApi (Build.VERSION_CODES.HONEYCOMB)
Sheepdogsheep

11

นอกเหนือจากsetCustomSelectionActionModeCallbackและปิดใช้งานโซลูชันการคลิกแบบยาวแล้วจำเป็นต้องป้องกันไม่ให้เมนู PASTE / REPLACEปรากฏขึ้นเมื่อมีการคลิกที่จุดจับการเลือกข้อความตามภาพด้านล่าง:

จัดการการเลือกข้อความพร้อมเมนูวาง

วิธีแก้ปัญหาอยู่ที่การป้องกันไม่ให้เมนู PASTE / REPLACE ปรากฏในshow()เมธอดของandroid.widget.Editorคลาส(ไม่มีเอกสาร) if (!canPaste && !canSuggest) return;ก่อนที่จะปรากฏเมนูการตรวจสอบจะทำเพื่อ สองวิธีที่ใช้เป็นพื้นฐานในการตั้งค่าตัวแปรเหล่านี้มีทั้งในEditTextคลาส:

คำตอบที่สมบูรณ์มากขึ้นคืออยู่ที่นี่


นี่คือโซลูชันที่ถูกต้องและสมบูรณ์
FireZenk

ในอุปกรณ์บางอย่างแทนที่จะเป็นตัวเลือกวางคลิปบอร์ดจะมองเห็นได้ทำหน้าที่วางเท่านั้น ฉันตรวจสอบลิงก์แล้ว แต่ฉันสามารถป้องกันการวางได้ แต่ไม่ใช่คลิปบอร์ด มีความคิดอย่างไร
Richa

11

โซลูชัน Kotlin:

fun TextView.disableCopyPaste() {
    isLongClickable = false
    setTextIsSelectable(false)
    customSelectionActionModeCallback = object : ActionMode.Callback {
        override fun onCreateActionMode(mode: ActionMode?, menu: Menu): Boolean {
            return false
        }

        override fun onPrepareActionMode(mode: ActionMode?, menu: Menu): Boolean {
            return false
        }

        override fun onActionItemClicked(mode: ActionMode?, item: MenuItem): Boolean {
            return false
        }

        override fun onDestroyActionMode(mode: ActionMode?) {}
    }
}

จากนั้นคุณสามารถเรียกวิธีนี้ในTextView:

override fun onCreate() {
    priceEditText.disableCopyPaste()
}

1
สวัสดีฉันกำลังใช้แนวทางนี้ แต่ฉันได้รับType mismatchข้อผิดพลาดเกี่ยวกับคำอธิบายRequired:ActionMode.Callback! Found: ในส่วนobject: ActionMode.Callbackนี้ มีความคิดว่าทำไมมันถึงใช้งานไม่ได้?
Abdul Mateen

8

การใช้โซลูชันอื่น API 26 (โอรีโอ) ยังคงแสดงที่จับเคอร์เซอร์โดยการแตะเพียงครั้งเดียวที่ข้อความที่ป้อนจากนั้นเมนูจะปรากฏขึ้น การรวมกันของโซลูชันเท่านั้นที่สามารถแก้ปัญหาของฉันได้

public class CustomEditText extends EditText {

    public CustomEditText(Context context) {
        super(context);
        init();
    }

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

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            this.setInsertionDisabled();
        }
        return super.onTouchEvent(event);
    }

    /**
    * This method sets TextView#Editor#mInsertionControllerEnabled field to false
    * to return false from the Editor#hasInsertionController() method to PREVENT showing
    * of the insertionController from EditText
    * The Editor#hasInsertionController() method is called in  Editor#onTouchUpEvent(MotionEvent event) method.
    */
    private void setInsertionDisabled() {
        try {
            Field editorField = TextView.class.getDeclaredField("mEditor");
            editorField.setAccessible(true);
            Object editorObject = editorField.get(this);

            Class editorClass = Class.forName("android.widget.Editor");
            Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
            mInsertionControllerEnabledField.setAccessible(true);
            mInsertionControllerEnabledField.set(editorObject, false);
        }
        catch (Exception ignored) {
            // ignore exception here
        }
    }

    @Override
    public boolean isSuggestionsEnabled() {
        return false;
    }

    private class BlockedActionModeCallback implements ActionMode.Callback {
        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) {
        }
    }
}

5

หากคุณไม่ต้องการปิดการใช้งานการคลิกแบบยาวเนื่องจากคุณต้องใช้ฟังก์ชันบางอย่างในการคลิกที่ยาวนานกว่าการคืนค่าจริงเป็นตัวเลือกที่ดีกว่า

การคลิกแบบยาวแก้ไขข้อความของคุณจะเป็นแบบนี้

edittext.setOnLongClickListener(new View.OnLongClickListener() {
      @Override
      public boolean onLongClick(View v) {
            //  Do Something or Don't
            return true;
      }
});

ตามเอกสาร ส่งคืน "True" จะระบุว่ามีการจัดการการคลิกแบบยาวดังนั้นจึงไม่จำเป็นต้องดำเนินการตามค่าเริ่มต้น

ฉันทดสอบสิ่งนี้กับ API ระดับ 16, 22 และ 25 มันใช้งานได้ดีสำหรับฉัน หวังว่านี่จะช่วยได้


1
สิ่งที่ดี. หรือเพียงแค่ตั้งค่าเป็นandroid:longClickable="false"XML
Alex Semeniuk

3

https://github.com/neopixl/PixlUIให้ไฟล์EditTextวิธีการ

myEditText.disableCopyAndPaste().

และใช้งานได้กับ API เก่า


1
สิ่งนี้เหมือนกับครึ่งโซลูชันที่จัดทำโดยstackoverflow.com/a/22756538/3063884 stackoverflow.com/a/22756538/3063884ดูรหัส: github.com/neopixl/PixlUI/blob/master/Library/src/com/neopixl/… ... แนวทางนี้ยังไม่ป้องกันไม่ให้ตัวจัดการการเลือกข้อความแสดง "วาง" หากมีข้อความในคลิปบอร์ด .
CJBS

3

นี่คือการแฮ็กเพื่อปิดใช้งานป๊อปอัป "วาง" คุณต้องแทนที่EditTextวิธีการ:

@Override
public int getSelectionStart() {
    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
        if (element.getMethodName().equals("canPaste")) {
            return -1;
        }
    }
    return super.getSelectionStart();
}

ที่คล้ายกันสามารถทำได้สำหรับการกระทำอื่น ๆ


คุณบอกได้ไหมว่าคลิปบอร์ดปิดการใช้งาน
Richa

3

ฉันได้ทดสอบโซลูชันนี้แล้วและได้ผล

    mSubdomainEditText.setLongClickable(false);
    mSubdomainEditText.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;
      }
    });

1

อ่านคลิปบอร์ดตรวจสอบอินพุตและเวลาที่ป้อนข้อมูล "พิมพ์" หากคลิปบอร์ดมีข้อความเหมือนกันและเร็วเกินไปให้ลบอินพุตที่วางไว้


1

@ Zain Ali คำตอบของคุณใช้ได้กับ API 11 ฉันแค่อยากจะแนะนำวิธีทำใน API 10 ด้วย เนื่องจากฉันต้องดูแล Project API ของฉันในเวอร์ชันนั้นฉันจึงเล่นกับฟังก์ชันที่มีใน 2.3.3 อยู่ตลอดเวลาและมีความเป็นไปได้ที่จะทำ ฉันได้แบ่งปันตัวอย่างด้านล่าง ฉันทดสอบโค้ดแล้วและมันใช้งานได้สำหรับฉัน ฉันทำตัวอย่างนี้ด้วยความเร่งด่วน อย่าลังเลที่จะปรับปรุงโค้ดหากมีการเปลี่ยนแปลงใด ๆ ที่สามารถทำได้ ..

// A custom TouchListener is being implemented which will clear out the focus 
// and gain the focus for the EditText, in few milliseconds so the selection 
// will be cleared and hence the copy paste option wil not pop up.
// the respective EditText should be set with this listener 
// tmpEditText.setOnTouchListener(new MyTouchListener(tmpEditText, tmpImm));

public class MyTouchListener implements View.OnTouchListener {

    long click = 0;
    EditText mEtView;
    InputMethodManager imm;

    public MyTouchListener(EditText etView, InputMethodManager im) {
        mEtView = etView;
        imm = im;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            long curr = System.currentTimeMillis();
            if (click !=0 && ( curr - click) < 30) {

                mEtView.setSelected(false);
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mEtView.setSelected(true);
                        mEtView.requestFocusFromTouch();
                        imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                    }
                },25);

            return true;
            }
            else {
                if (click == 0)
                    click = curr;
                else
                    click = 0;
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mEtView.requestFocusFromTouch();
                        mEtView.requestFocusFromTouch();
                        imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                    }
                },25);
            return true;
            }

        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            mEtView.setSelected(false);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mEtView.setSelected(true);
                    mEtView.requestFocusFromTouch();
                    mEtView.requestFocusFromTouch();
                    imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                }
            },25);
            return true;
        }
        return false;
    }

1

วิธีแก้ปัญหานั้นง่ายมาก

public class MainActivity extends AppCompatActivity {

EditText et_0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et_0 = findViewById(R.id.et_0);

    et_0.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            //to keep the text selection capability available ( selection cursor)
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            //to prevent the menu from appearing
            menu.clear();
            return false;
        }

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

        @Override
        public void onDestroyActionMode(ActionMode mode) {

        }
    });
   }
}

--------> ดูตัวอย่าง <---------


1

ลองทำตามชั้นเรียนที่เหมาะสมเพื่อคัดลอกและวาง Edittext

public class SegoeUiEditText extends AppCompatEditText {
private final Context context;


@Override
public boolean isSuggestionsEnabled() {
    return false;
}
public SegoeUiEditText(Context context) {
    super(context);
    this.context = context;
    init();
}

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

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


private void setFonts(Context context) {
    this.setTypeface(Typeface.createFromAsset(context.getAssets(), "Fonts/Helvetica-Normal.ttf"));
}

private void init() {

        setTextIsSelectable(false);
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        this.setLongClickable(false);

}
@Override
public int getSelectionStart() {

    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
        if (element.getMethodName().equals("canPaste")) {
            return -1;
        }
    }
    return super.getSelectionStart();
}
/**
 * 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, android.view.ActionMode.Callback {
    private final String TAG = SegoeUiEditText.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) {}

    @Override
    public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
        return false;
    }

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

    @Override
    public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
        return false;
    }

    @Override
    public void onDestroyActionMode(android.view.ActionMode mode) {

    }
}

}


1

สำหรับสมาร์ทโฟนที่มีคลิปบอร์ดสามารถป้องกันได้เช่นนี้

editText.setFilters(new InputFilter[]{new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.length() > 1) {
                return "";
            }  return null;
        }
    }});


0

ฉันพบว่าเมื่อคุณสร้างตัวกรองอินพุตเพื่อหลีกเลี่ยงการป้อนอักขระที่ไม่ต้องการการวางอักขระดังกล่าวลงในข้อความแก้ไขจะไม่มีผลใด ๆ วิธีนี้ก็ช่วยแก้ปัญหาของฉันได้เช่นกัน



0

วิธีแก้ปัญหาที่ได้ผลสำหรับฉันคือสร้าง Edittext แบบกำหนดเองและแทนที่วิธีการต่อไปนี้:

public class MyEditText extends EditText {

private int mPreviousCursorPosition;

@Override
protected void onSelectionChanged(int selStart, int selEnd) {
    CharSequence text = getText();
    if (text != null) {
        if (selStart != selEnd) {
            setSelection(mPreviousCursorPosition, mPreviousCursorPosition);
            return;
        }
    }
    mPreviousCursorPosition = selStart;
    super.onSelectionChanged(selStart, selEnd);
}

}


0

ลองนำไปใช้.

myEditext.setCursorVisible(false);

       myEditext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            // TODO Auto-generated method stub
            return false;
        }

        public void onDestroyActionMode(ActionMode mode) {
            // TODO Auto-generated method stub

        }

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // TODO Auto-generated method stub
            return false;
        }

        public boolean onActionItemClicked(ActionMode mode,
                MenuItem item) {
            // TODO Auto-generated method stub
            return false;
        }
    });

0

ใครกำลังมองหาวิธีแก้ปัญหาใน Kotlin ใช้คลาสด้านล่างเป็นวิดเจ็ตที่กำหนดเองและใช้ใน xml

คลาส SecureEditText: TextInputEditText {

/** 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 fun isSuggestionsEnabled(): Boolean {
    return false
}

override fun getSelectionStart(): Int {
    for (element in Thread.currentThread().stackTrace) {
        if (element.methodName == "canPaste") {
            return -1
        }
    }
    return super.getSelectionStart()
}

public override fun onSelectionChanged(start: Int, end: Int) {

    val text = text
    if (text != null) {
        if (start != text.length || end != text.length) {
            setSelection(text.length, text.length)
            return
        }
    }

    super.onSelectionChanged(start, end)
}

companion object {
    private val EDITTEXT_ATTRIBUTE_COPY_AND_PASTE = "isCopyPasteDisabled"
    private val PACKAGE_NAME = "http://schemas.android.com/apk/res-auto"
}

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
    disableCopyAndPaste(context, attrs)
}

/**
 * Disable Copy and Paste functionality on EditText
 *
 * @param context Context object
 * @param attrs   AttributeSet Object
 */
private fun disableCopyAndPaste(context: Context, attrs: AttributeSet) {
    val isDisableCopyAndPaste = attrs.getAttributeBooleanValue(
        PACKAGE_NAME,
        EDITTEXT_ATTRIBUTE_COPY_AND_PASTE, true
    )
    if (isDisableCopyAndPaste && !isInEditMode()) {
        val inputMethodManager =
            context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        this.setLongClickable(false)
        this.setOnTouchListener(BlockContextMenuTouchListener(inputMethodManager))
    }
}

/**
 * Perform Focus Enabling Task to the widget with the help of handler object
 * with some delay
 * @param inputMethodManager is used to show the key board
 */
private fun performHandlerAction(inputMethodManager: InputMethodManager) {
    val postDelayedIntervalTime: Long = 25
    Handler().postDelayed(Runnable {
        this@SecureEditText.setSelected(true)
        this@SecureEditText.requestFocusFromTouch()
        inputMethodManager.showSoftInput(
            this@SecureEditText,
            InputMethodManager.RESULT_SHOWN
        )
    }, postDelayedIntervalTime)
}

/**
 * Class to Block Context Menu on double Tap
 * A custom TouchListener is being implemented which will clear out the focus
 * and gain the focus for the EditText, in few milliseconds so the selection
 * will be cleared and hence the copy paste option wil not pop up.
 * the respective EditText should be set with this listener
 *
 * @param inputMethodManager is used to show the key board
 */
private inner class BlockContextMenuTouchListener internal constructor(private val inputMethodManager: InputMethodManager) :
    View.OnTouchListener {
    private var lastTapTime: Long = 0
    val TIME_INTERVAL_BETWEEN_DOUBLE_TAP = 30
    override fun onTouch(v: View, event: MotionEvent): Boolean {
        if (event.getAction() === MotionEvent.ACTION_DOWN) {
            val currentTapTime = System.currentTimeMillis()
            if (lastTapTime != 0L && currentTapTime - lastTapTime < TIME_INTERVAL_BETWEEN_DOUBLE_TAP) {
                this@SecureEditText.setSelected(false)
                performHandlerAction(inputMethodManager)
                return true
            } else {
                if (lastTapTime == 0L) {
                    lastTapTime = currentTapTime
                } else {
                    lastTapTime = 0
                }
                performHandlerAction(inputMethodManager)
                return true
            }
        } else if (event.getAction() === MotionEvent.ACTION_MOVE) {
            this@SecureEditText.setSelected(false)
            performHandlerAction(inputMethodManager)
        }
        return false
    }
}

}


0

ฉันเพิ่มฟังก์ชันส่วนขยายในภาษาKotlin :

fun EditText.disableTextSelection() {
    this.setCustomSelectionActionModeCallback(object : android.view.ActionMode.Callback {
        override fun onActionItemClicked(mode: android.view.ActionMode?, item: MenuItem?): Boolean {
            return false
        }
        override fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
            return false
        }
        override fun onPrepareActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
            return false
        }
        override fun onDestroyActionMode(mode: android.view.ActionMode?) {
        }
    })
}

คุณสามารถใช้มันได้ดังนี้:

edit_text.disableTextSelection()

นอกจากนี้ยังเพิ่มบรรทัดด้านล่างใน xml ของคุณ:

                android:longClickable="false"
                android:textIsSelectable="false"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.