Android自定义文本选中模式(全选、复制,剪切,粘帖)
来源:互联网 发布:udp自定义端口号 编辑:程序博客网 时间:2024/06/06 06:31
为了方便操作,在PC端我们常用的Ctrl+A(全选)/Ctrl+C(复制)/Ctrl+X(剪切)/Ctrl+V(粘帖)提高了我们的办公效率。然后在手机端怎么实现呢?我花了一天的时间研究了一下。
- 首先说一下TextView的选中,要想选中TextView中的文本有两种方式:
1、setSelectAllOnFocus(true);
2、android:textIsSelectable=”true” - 然后看一下EditText
从上面的图可以看出EditText是继承于TextView的,所以setSelectAllOnFocus(true)和android:textIsSelectable=”true”对它也同样适用,不过EditText默认setSelectAllOnFocus(true),所以没有必要手动设置;如果真的在布局文件中设置了android:textIsSelectable=”true”,那么EditText就不能被编辑,失去了光标,如下图:
所以android:textIsSelectable=”true”一般是给TextView设置的。
首先我们看一下默认的选中模式(上面弹出操作提示框):
那么要想改变原有的东西呢?这里有一个方法
setCustomSelectionActionModeCallback(new MyActionModeCallback(ActionMode.Callback callback));
通过ActionMode.Callback中的四个回调方法进行操作:
//创建菜单 @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { return true; }//这个相当于是菜单创建好以后的操作 @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return true; }//菜单中item的点击处理 @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return true; }//菜单销毁操作 @Override public void onDestroyActionMode(ActionMode actionMode) { }
首先要去自定义一个菜单布局:
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/it_all" android:title="全选" android:icon="@drawable/all" /> <item android:id="@+id/it_copy" android:title="复制" android:icon="@drawable/copy" /> <item android:id="@+id/it_cut" android:title="剪切" android:icon="@drawable/cut" /> <item android:id="@+id/it_paste" android:title="粘帖" /></menu>
这里的android:icon=“@drawable/xxx”设置了,但是不显示。然后在onCreateActionMode方法中去初始化菜单;
MenuInflater menuInflater = actionMode.getMenuInflater(); menuInflater.inflate(R.menu.menu,menu); return true;
菜单创建好以后就是具体的操作了。
全选
Edittext有个selectAll()方法来实现全选;这个方法是Edittext独有的,所以TextView是没这个方法的。
复制、剪切
复制和剪切的原理一样,就是最后的处理稍有不同,所以我把他们放在了同一个方法中进行处理。
/** * 统一处理复制和剪切的操作 * @param mode 用来区别是复制还是剪切 * @return */ private String getSelectText(SelectMode mode) { //获取剪切班管理者 ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE); //获取选中的起始位置 int selectionStart = mTvSelect.getSelectionStart(); int selectionEnd = mTvSelect.getSelectionEnd(); Log.i(TAG,"selectionStart="+selectionStart+",selectionEnd="+selectionEnd); //截取选中的文本 String txt = mTvSelect.getText().toString(); String substring = txt.substring(selectionStart, selectionEnd); Log.i(TAG,"substring="+substring); //将选中的文本放到剪切板 cbs.setPrimaryClip(ClipData.newPlainText(null,substring)); //如果是复制就不往下操作了 if (mode==SelectMode.COPY) return txt; //把剪切后的数据替换"" txt = txt.replace(substring, ""); return txt; } /** * 用枚举来区分是复制还是剪切 */ public enum SelectMode{ COPY,CUT; }
这里我把兼容低版本没有做,API Level 11以前用的setText(),getText(),hasText()这三个方法做复制粘帖的操作(只限于对文本的操作);以后的API中废弃了以前的三个方法,通过ClipData对象来操作文本、Uri和Intent,用ClipboardManager.setPrimaryClip(ClipData data),ClipboardManager.getPrimaryClip()和hasPrimaryClip()代替前面的三个方法了。这里操作的就不是纯文本,而是复杂的对象了。
ClipData 的三个静态方法分别担任不同的工作(ClipData对象中包含一个或多个ClipData.Item对象)
- ClipData.newPlainText(“Label”, “Content”)创建普通字符型ClipData
- ClipData.newRawUri(“Label”, Uri.parse(“https://www.baidu.com/“)) 创建URL型ClipData
- ClipData.newIntent(“Label”, intent)创建Intent型ClipData
粘帖
//获取剪切班管理者 ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE); if (cbs.hasPrimaryClip()){ mTvSelect.setText(cbs.getPrimaryClip().getItemAt(0).getText()); }
基本操作就OK了,我把完整的Java代码贴一下。
/** * 描述:文本的选中模式的使用 * 开发者:开发者的乐趣JRT * 创建时间:2017-3-12 12:29 * CSDN地址:http://blog.csdn.net/Jiang_Rong_Tao/article * E-mail:jrtxb520@163.com **/public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private EditText mTvSelect; private MainActivity mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext =this; init(); } private void init() { mTvSelect = (EditText) findViewById(R.id.tv_select); mTvSelect.setCustomSelectionActionModeCallback(new MyActionModeCallback()); } private class MyActionModeCallback implements ActionMode.Callback { private Menu mMenu; @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { MenuInflater menuInflater = actionMode.getMenuInflater(); menuInflater.inflate(R.menu.menu,menu); return true; } @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { //菜单创建完成以后获取到其对象,便于后续操作 this.mMenu=menu; return true; } @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { switch (menuItem.getItemId()){ case R.id.it_all: //全选 mTvSelect.selectAll(); Toast.makeText(mContext, "完成全选", Toast.LENGTH_SHORT).show(); break; case R.id.it_copy: String selectText = getSelectText(SelectMode.COPY); //setText(selectText)是为了后面的this.mMenu.close()起作用 mTvSelect.setText(selectText); Toast.makeText(mContext, "选中的内容已复制到剪切板", Toast.LENGTH_SHORT).show(); this.mMenu.close(); break; case R.id.it_cut: //剪切 String txt = getSelectText(SelectMode.CUT); mTvSelect.setText(txt); Toast.makeText(mContext, "选中的内容已剪切到剪切板", Toast.LENGTH_SHORT).show(); this.mMenu.close(); break; case R.id.it_paste: //获取剪切班管理者 ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE); if (cbs.hasPrimaryClip()){ mTvSelect.setText(cbs.getPrimaryClip().getItemAt(0).getText()); } this.mMenu.close(); break; } return true; } @Override public void onDestroyActionMode(ActionMode actionMode) { } } /** * 统一处理复制和剪切的操作 * @param mode 用来区别是复制还是剪切 * @return */ private String getSelectText(SelectMode mode) { //获取剪切班管理者 ClipboardManager cbs = (ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE); //获取选中的起始位置 int selectionStart = mTvSelect.getSelectionStart(); int selectionEnd = mTvSelect.getSelectionEnd(); Log.i(TAG,"selectionStart="+selectionStart+",selectionEnd="+selectionEnd); //截取选中的文本 String txt = mTvSelect.getText().toString(); String substring = txt.substring(selectionStart, selectionEnd); Log.i(TAG,"substring="+substring); //将选中的文本放到剪切板 cbs.setPrimaryClip(ClipData.newPlainText(null,substring)); //如果是复制就不往下操作了 if (mode==SelectMode.COPY) return txt; txt = txt.replace(substring, ""); return txt; } /** * 用枚举来区分是复制还是剪切 */ public enum SelectMode{ COPY,CUT; }}
注意:这里this.mMenu.close()有个细节,如果单纯的调用close方法是不起作用的,必须EditText的文本有所变化
- 如果不重新设置EditText的文本,则menu的close方法不管用
- 重新设置文本后
总结
基本的操作就到此结束了,EditText的UI和选中后的光标也有点抽,这些都是可以自定义改变的,具体操作,自行Search。
github:源码下载
- Android自定义文本选中模式(全选、复制,剪切,粘帖)
- Android自定义文本选中模式(全选、复制,剪切,粘帖)
- 文本复制、剪切、撤销
- 记事本(含剪切、复制、粘贴、全选、撤销)核心设计
- C#RichTextBox实现(复制, 剪切,粘贴,全选)
- 模拟键盘录入,复制粘贴剪切,全选
- Mac全选,剪切和复制粘贴
- android 复制、剪切、粘贴
- android 复制、剪切、粘贴
- Android 复制剪切操作
- android 复制、剪切、粘贴
- android 复制,剪切,粘贴
- android 复制剪切
- android EditText 屏蔽长按弹出剪切 复制 全选菜单 的解决办法
- 屏蔽选中、粘贴、复制、剪切、右键菜单
- vim选中字符复制/剪切/粘贴
- vim选中字符复制/剪切/粘贴
- 记事本(新建,打开,保存,关闭,复制,粘贴,剪切,全选,日期)
- tomcat 下载及配置
- cocos JniHelper调用java时总是报 Failed to find static method id of
- struts学习(七)—拦截器概述
- 【Ubuntu 16】安装deb
- TCP会话开始与结束
- Android自定义文本选中模式(全选、复制,剪切,粘帖)
- java.util.Date和java.sql.Date的区别和相互转化
- Android第三方授权分享在新浪微博授权提示:文件不存在 C8998 的解决方法
- 基于Jetson TX1的faster-rcnn的算法搭建
- RxSwift (9) 调试符号
- SqlServer获取存储过程的返回值
- 二叉搜索树
- java FileInputStream 基础使用
- matlab管理内存方法---解决out of memory