本帖最后由 小鲁哥哥 于 2017-6-17 14:37 编辑
【济南中心】Android课程同步笔记智慧北京:Day06(上)
科大讯飞-语音合成
注册用户进行登录
创建应用
下载云服务SDK
添加依赖库
配置权限
[XML] 纯文本查看 复制代码 <!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--读取联系人权限,上传联系人需要用到此权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置权限,用来记录应用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
初始化云服务
[Java] 纯文本查看 复制代码 public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
// 将“12345678”替换成您申请的 APPID,申请地址:[url=http://www.xfyun.cn]http://www.xfyun.cn[/url]
// 请勿在“=”与 appid 之间添加任务空字符或者转义符
SpeechUtility.createUtility(this, SpeechConstant.APPID +"=57f75ccc");
}
将文字合成语音
[Java] 纯文本查看 复制代码 //把文字转换成语言
public void say(View view){
//1.创建 SpeechSynthesizer 对象, 第二个参数:本地合成时传 InitListener
SpeechSynthesizer mTts= SpeechSynthesizer.createSynthesizer(this, null);
//2.合成参数设置,详见《MSC Reference Manual》SpeechSynthesizer 类
//设置发音人(更多在线发音人,用户可参见 附录13.2
mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan"); //设置发音人 mTts.setParameter(SpeechConstant.SPEED, "50");//设置语速 mTts.setParameter(SpeechConstant.VOLUME, "80");//设置音量,范围 0~100
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); //设置云端
//设置合成音频保存位置(可自定义保存位置),保存在“./sdcard/iflytek.pcm” //保存在 SD 卡需要在 AndroidManifest.xml 添加写 SD 卡权限
//仅支持保存为 pcm 和 wav 格式,如果不需要保存合成音频,注释该行代码
mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, "./sdcard/iflytek.pcm");
//3.开始合成
mTts.startSpeaking("黑马程序员,让世界聆听我们的声音", mSynListener);
}
//合成监听器
private SynthesizerListener mSynListener = new SynthesizerListener(){
//会话结束回调接口,没有错误时,error为null
public void onCompleted(SpeechError error) {}
//缓冲进度回调
//percent为缓冲进度0~100,beginPos为缓冲音频在文本中开始位置,endPos表示缓冲音频在文本中结束位置,info为附加信息。
public void onBufferProgress(int percent, int beginPos, int endPos, String info) {}
//开始播放
public void onSpeakBegin() {}
//暂停播放
public void onSpeakPaused() {}
//播放进度回调
//percent为播放进度0~100,beginPos为播放音频在文本中开始位置,endPos表示播放音频在文本中结束位置.
public void onSpeakProgress(int percent, int beginPos, int endPos) {}
//恢复播放回调接口
public void onSpeakResumed() {}
//会话事件回调接口
public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {}
};
科大讯飞-语言识别
语言识别:将连续语音快速识别为文字的过程,科大讯飞语音听写能识别通用常见的语句、词汇, 而且不限制说法。 功能实现:
[Java] 纯文本查看 复制代码 //把语言转换成文字
public void listen(View view){
//1.创建SpeechRecognizer对象,第二个参数:本地识别时传InitListener
SpeechRecognizer mIat= SpeechRecognizer.createRecognizer(this, null);
//2.设置听写参数,详见《MSC Reference Manual》SpeechConstant类
mIat.setParameter(SpeechConstant.DOMAIN, "iat"); mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); mIat.setParameter(SpeechConstant.ACCENT, "mandarin ");
//3.开始听写
mIat.startListening(mRecoListener);
}
//听写监听器
private RecognizerListener mRecoListener = new RecognizerListener(){
//听写结果回调接口(返回Json格式结果,用户可参见附录13.1);
//一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
//关于解析Json的代码可参见Demo中JsonParser类; //isLast等于true时会话结束。
StringBuilder sb = new StringBuilder();
public void onResult(RecognizerResult results, boolean isLast) {
// Log.d(TAG, "result:" + results.getResultString ());
VoiceInfo info = new Gson().fromJson(results.getResultString(), VoiceInfo.class);
if(isLast){
String content = info.ws.get(0).cw.get(0).w;
sb.append(content);
Log.d(TAG, "result:" + sb.toString());
}else{
//拼接内容
List<VoiceInfo.WS> ws = info.ws;
for (VoiceInfo.WS w:ws){
String content = w.cw.get(0).w;
sb.append(content);
}
}
}
//会话发生错误回调接口
public void onError(SpeechError error) {
//打印错误码描述
Log.d(TAG, "error:" + error.getPlainDescription(true)); }
//开始录音
public void onBeginOfSpeech() {}
//volume音量值0~30,data音频数据
public void onVolumeChanged(int volume, byte[] data){}
//结束录音
public void onEndOfSpeech() {}
//扩展用接口
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {}
};
将转换为文字封装成java数据模型
[Java] 纯文本查看 复制代码 public class VoiceInfo {
public int bg;
public int ed;
public boolean ls;
public int sn;
public List<WS> ws;
public class WS{
public int bg;
public List<CW> cw;
}
public class CW{
public String sc;
public String w;
}
}
在听写监听器中转换java模型,并拼接一句完整的文字
[Java] 纯文本查看 复制代码 //听写监听器
private RecognizerListener mRecoListener = new RecognizerListener(){
//听写结果回调接口(返回Json格式结果,用户可参见附录13.1);
//一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
//关于解析Json的代码可参见Demo中JsonParser类; //isLast等于true时会话结束。
StringBuilder sb = new StringBuilder();
public void onResult(RecognizerResult results, boolean isLast) {
// Log.d(TAG, "result:" + results.getResultString ());
VoiceInfo info = new Gson().fromJson(results.getResultString(), VoiceInfo.class);
if(isLast){
String content = info.ws.get(0).cw.get(0).w;
sb.append(content);
Log.d(TAG, "result:" + sb.toString());
}else{
//拼接内容
List<VoiceInfo.WS> ws = info.ws;
for (VoiceInfo.WS w:ws){
String content = w.cw.get(0).w;
sb.append(content);
}
}
}
//会话发生错误回调接口
public void onError(SpeechError error) {
//打印错误码描述
Log.d(TAG, "error:" + error.getPlainDescription(true)); }
//开始录音
public void onBeginOfSpeech() {}
//volume音量值0~30,data音频数据
public void onVolumeChanged(int volume, byte[] data){}
//结束录音
public void onEndOfSpeech() {}
//扩展用接口
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {}
};
科大讯飞-带对话框的语言识别
资源导入
带有对话框的功能实现
[Java] 纯文本查看 复制代码 public void dialogListen(View view){
//1.创建RecognizerDialog对象
RecognizerDialog mDialog = new RecognizerDialog(this, mInitListener);
//2.设置accent、language等参数
mDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); mDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
//若要将UI控件用于语义理解,必须添加以下参数设置,设置之后onResult回调返回将是语义理解
//结果
// mDialog.setParameter("asr_sch", "1");
// mDialog.setParameter("nlp_version", "2.0");
//3.设置回调接口
mDialog.setListener(mRecognizerDialogListener);
//4.显示dialog,接收语音输入
mDialog.show();
}
添加听写监听
[Java] 纯文本查看 复制代码 private InitListener mInitListener = new InitListener() {
@Override
public void onInit(int i) {
}
};
private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
StringBuilder sb = new StringBuilder();
public void onResult(RecognizerResult results, boolean isLast) {
// Log.d(TAG, "result:" + results.getResultString ());
VoiceInfo info = new Gson().fromJson(results.getResultString(), VoiceInfo.class);
if(isLast){
String content = info.ws.get(0).cw.get(0).w;
sb.append(content);
Log.d(TAG, "result:" + sb.toString());
}else{
//拼接内容
List<VoiceInfo.WS> ws = info.ws;
for (VoiceInfo.WS w:ws){
String content = w.cw.get(0).w;
sb.append(content);
}
}
}
@Override
public void onError(SpeechError speechError) {
}
}
zxing二维码扫描
二维码的概念:用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息。 二维码功能:信息获取(名片、地图、WIFI密码、资料) 网站跳转(跳转到微博、手机网站、网站) 广告推送(用户扫码,直接浏览商家推送的视频、音频广告) 手机支付(扫描商品二维码,通过银行或第三方支付提供的手机端通道完成支付) 二维码特点:高密度编码,信息容量大:500多个汉字 容错能力强,具有纠错功能:这使得二维条码因穿孔、污损等引起局部损坏时,照样可以正确得到识读,损毁面积达50%仍可恢复信息 编码范围广:该条码可以把图片、声音、文字、签字、指纹等可以数字化的信息进行编码 扫描二维码功能实现:由于二维码使用算法,进行保密度编码。如果作为一个开发者来说,实现识别二维码功能,相对来说比较困难。因此,google公司,开源了一套识别二维码的项目。Zxing从github中搜索zxing,然后主页中,下载对应的案例。继承到工程中。 添加依赖库:
扫描结果处理:
二维码扫描流程- 初始化相机,设置一些相机参数;
- 绑定SurfaceView,在SurfaceView上显示预览图像;
- 获取相机的一帧图像;
- 对图像进行一定的预处理,只保留亮度信息,成为灰度图像;
- 对灰度图像进行二维码解析,解析成功进入下一步,不成功回到第③步;
- 返回解析结果并退出。
二维码扫描流程图
可以移动的GridView
下载项目并继承到项目中
可拖动的核心类
按下拖动显示对应的专栏的item
移动处理,专栏之间交换位置
停止拖动,松手情况下,显示拖动的item
GridLayout的使用
将GridLayout引入到布局中
[XML] 纯文本查看 复制代码 <!--android:columnCount="4" 列数
android:animateLayoutChanges="true" 开启动画
-->
<GridLayout
android:id="@+id/gridLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="4"
android:animateLayoutChanges="true"></GridLayout>
注意:这里面中有两属性:android:columnCount="4" 列数android:animateLayoutChanges="true" 开启动画
初始化GridLayout,并添加条目
[Java] 纯文本查看 复制代码 //初始化GridLayout对象
gridLayout = (GridLayout) findViewById(R.id.gridLayout);
添加条目
public void addItem(View view){
//添加条目
TextView tv = new TextView(this);
//设置布局参数
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.height = GridLayout.LayoutParams.WRAP_CONTENT;
params.width = getResources().getDisplayMetrics().widthPixels/4 - margin*2;
//设置外边距
params.setMargins(margin,margin,margin,margin);
tv.setLayoutParams(params);
//设置内边距
tv.setPadding(0,margin,0,margin);
tv.setGravity(Gravity.CENTER);
tv.setText(index+"");
//设置背景资源
tv.setBackgroundResource(R.drawable.item_bg);
index++;
gridLayout.addView(tv,0);
//给条目设置长按点击事件
tv.setOnLongClickListener(onLongClickListener);
}
创建每个item的背景颜色默认背景图片item_bg_normal.xml [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp"/>
<stroke android:color="#000" android:width="1dp"/>
</shape>
按下时的背景图片Item_bg_press.xml: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp"/>
<stroke android:color="#f00" android:width="1dp" android:dashGap="2dp" android:dashWidth="5dp"/>
</shape>
注意:属性dashGap:虚线的宽度 属性dashWidth:实现的宽度
创建条目的状态选择器
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/item_bg_normal"/>
<item android:state_enabled="false" android:drawable="@drawable/item_bg_press"/>
</selector>
给item设置背景资源
[Java] 纯文本查看 复制代码 public void addItem(View view){
//添加条目
TextView tv = new TextView(this);
//设置布局参数
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.height = GridLayout.LayoutParams.WRAP_CONTENT;
//动态计算每个item的宽度
params.width = getResources().getDisplayMetrics().widthPixels/4 - margin*2;
//设置外边距
params.setMargins(margin,margin,margin,margin);
tv.setLayoutParams(params);
//设置内边距
tv.setPadding(0,margin,0,margin);
tv.setGravity(Gravity.CENTER);
tv.setText(index+"");
//设置背景资源
tv.setBackgroundResource(R.drawable.item_bg);
index++;
gridLayout.addView(tv,0);
//给条目设置长按点击事件
tv.setOnLongClickListener(onLongClickListener);
}
DragEvent事件
设置GridLayout每个item长按事件,并产生浮动的阴影效果
[Java] 纯文本查看 复制代码 public void addItem(View view){
//添加条目
TextView tv = new TextView(this);
//设置布局参数
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.height = GridLayout.LayoutParams.WRAP_CONTENT;
//动态计算每个item的宽度
params.width = getResources().getDisplayMetrics().widthPixels/4 - margin*2;
//设置外边距
params.setMargins(margin,margin,margin,margin);
tv.setLayoutParams(params);
//设置内边距
tv.setPadding(0,margin,0,margin);
tv.setGravity(Gravity.CENTER);
tv.setText(index+"");
//设置背景资源
tv.setBackgroundResource(R.drawable.item_bg);
index++;
gridLayout.addView(tv,0);
//给条目设置长按点击事件
tv.setOnLongClickListener(onLongClickListener);
}
实现长按监听[Java] 纯文本查看 复制代码 private View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
dragView = v;
//产生浮动的阴影效果
//①传递数据 ② 产生阴影的 ③ 传递数据 ④ 状态
v.startDrag(null,new View.DragShadowBuilder(v),null,0);
return true;//处理长按事件
}
};
给GridLayout设置可拖动的事件
[Java] 纯文本查看 复制代码 //初始化GridLayout对象
gridLayout = (GridLayout) findViewById(R.id.gridLayout);
//设置拖拽的监听
gridLayout.setOnDragListener(onDragListener);
实现GridLayout的拖动监听
封装拖动事件类型
[Java] 纯文本查看 复制代码 static SparseArray<String> dragEventType = new SparseArray<String>();
static{
dragEventType.put(DragEvent.ACTION_DRAG_STARTED, "STARTED");
dragEventType.put(DragEvent.ACTION_DRAG_ENDED, "ENDED");
dragEventType.put(DragEvent.ACTION_DRAG_ENTERED, "ENTERED");
dragEventType.put(DragEvent.ACTION_DRAG_EXITED, "EXITED");
dragEventType.put(DragEvent.ACTION_DRAG_LOCATION, "LOCATION");
dragEventType.put(DragEvent.ACTION_DROP, "DROP");
}
通过静态方法获取当前拖动的事件类型
[Java] 纯文本查看 复制代码 /*
DragEvent.ACTION_DRAG_STARTED 手指按下
DragEvent.ACTION_DRAG_ENTERED 手指按下|从GridLayout外部进入
DragEvent.ACTION_DRAG_LOCATION 在Gridlayout的区间内移动
DragEvent.ACTION_DRAG_EXITED 离开GridLayout的区间
DragEvent.ACTION_DROP 松手
DragEvent.ACTION_DRAG_ENDED 松手
*/
public static String getDragEventAction(DragEvent de){
return dragEventType.get(de.getAction());
}
GridLayout条目拖拽交换
长按记录拖动的条目
监听拖动事件: 按下时: 将拖动的item设置为不可用 初始化每个item的矩形区域 移动时: 判断拖动的item是否在下方item的矩形区域中 如果存在,进行交互,反之不做交互 抬起时: 将拖动的item设置为可用
[Java] 纯文本查看 复制代码 private View.OnDragListener onDragListener = new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
//Log.i(TAG,getDragEventAction(event));
switch (event.getAction()){
case DragEvent.ACTION_DRAG_STARTED://按下
dragView.setEnabled(false);
initRects();
break;
case DragEvent.ACTION_DRAG_LOCATION://移动
//获取要交换条目的下标
int exchangeItemPosition = getExchangeItemPosition(event);
if(exchangeItemPosition > -1 && dragView != gridLayout.getChildAt(exchangeItemPosition)){
//移除
gridLayout.removeView(dragView);
//添加
gridLayout.addView(dragView,exchangeItemPosition);
}
break;
case DragEvent.ACTION_DRAG_ENDED://弹起
dragView.setEnabled(true);
break;
}
return true;//拖拽事件成功的处理
}
};
初始化每个条目的矩形区域
[Java] 纯文本查看 复制代码 //初始化条目的矩形区域
private void initRects() {
rects = new ArrayList<>();
for (int i = 0; i < gridLayout.getChildCount(); i++) {
View view = gridLayout.getChildAt(i);
//创建矩形
Rect rect = new Rect(view.getLeft(),view.getTop(),view.getRight(),view.getBottom());
rects.add(rect);
}
}
获取要交换的条目下标
[Java] 纯文本查看 复制代码 //获取要交换条目的下标
private int getExchangeItemPosition(DragEvent event) {
for (int i = 0; i < rects.size(); i++) {
Rect rect = rects.get(i);
if(rect.contains((int)event.getX(),(int)event.getY())){
return i;
}
}
return -1;
}
自定义DragGridLayout
继承GridLayout,重写构造方法
[Java] 纯文本查看 复制代码 public DragGridLayout(Context context) {
this(context,null);
}
public DragGridLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public DragGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// android:columnCount="4"
// android:animateLayoutChanges="true"
//设置列数
setColumnCount(columnCount);
//开启动画
setLayoutTransition(new LayoutTransition());
}
初始化GridLayout的显示列数和开启动画
[Java] 纯文本查看 复制代码 public DragGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// android:columnCount="4"
// android:animateLayoutChanges="true"
//设置列数
setColumnCount(columnCount);
//开启动画
setLayoutTransition(new LayoutTransition());
}
为外界提供是否可以拖动监听方法
[Java] 纯文本查看 复制代码 public void setHasCanDrag(boolean hasCanDrag) {
this.hasCanDrag = hasCanDrag;
if(hasCanDrag){
setOnDragListener(onDragListener);
}else{
setOnDragListener(null);
}
}
为外界提供设置条目的方法
[Java] 纯文本查看 复制代码 //从外部设置条目的内容
public void setItems(List<String> items) {
this.items = items;
createItems(items);
}
//创建所有的条目
private void createItems(List<String> items) {
//创建条目
for (String item : items) {
addItem(item);
}
}
添加条目 [Java] 纯文本查看 复制代码 public void addItem(String content){
//添加条目
TextView tv = new TextView(getContext());
//设置布局参数
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.height = GridLayout.LayoutParams.WRAP_CONTENT;
params.width = getResources().getDisplayMetrics().widthPixels/4 - margin*2;
//设置外边距
params.setMargins(margin,margin,margin,margin);
tv.setLayoutParams(params);
//设置内边距
tv.setPadding(0,margin,0,margin);
tv.setGravity(Gravity.CENTER);
tv.setText(content);
//设置背景资源
tv.setBackgroundResource(R.drawable.item_bg);
addView(tv,0);
if(hasCanDrag){
//给条目设置长按点击事件
tv.setOnLongClickListener(onLongClickListener);
}else{
//给条目设置长按点击事件
tv.setOnLongClickListener(null);
}
//设置条目的点击事件
tv.setOnClickListener(onClickListener);
}
给GridLayout控件中拖动事件,实现拖动交互功能
[Java] 纯文本查看 复制代码 private View.OnDragListener onDragListener = new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
//Log.i(TAG,getDragEventAction(event));
switch (event.getAction()){
case DragEvent.ACTION_DRAG_STARTED://按下
dragView.setEnabled(false);
initRects();
break;
case DragEvent.ACTION_DRAG_LOCATION://移动
//获取要交换条目的下标
int exchangeItemPosition = getExchangeItemPosition(event);
if(exchangeItemPosition > -1 && dragView != getChildAt(exchangeItemPosition)){
//移除
removeView(dragView);
//添加
addView(dragView,exchangeItemPosition);
}
break;
case DragEvent.ACTION_DRAG_ENDED://弹起
dragView.setEnabled(true);
break;
}
return true;//拖拽事件成功的处理
}
};
为外界提供每个条目的点击事件监听接口
[Java] 纯文本查看 复制代码 //接口
public interface OnDragItemClickListener{
public void onDragItemClick(TextView tv);
}
private OnDragItemClickListener onDragItemClickListener;
public void setOnDragItemClickListener(OnDragItemClickListener onDragItemClickListener) {
this.onDragItemClickListener = onDragItemClickListener;
}
在添加条目时,设置点击事件
[Java] 纯文本查看 复制代码 //设置条目的点击事件
tv.setOnClickListener(onClickListener);
初始化两个自定义GridLayout控件
[Java] 纯文本查看 复制代码 final DragGridLayout dragGridLayout = (DragGridLayout) findViewById(R.id.dragGridLayout);
dragGridLayout.setHasCanDrag(true);
List<String> items = new ArrayList<>();
items.add("北京");
items.add("上海");
items.add("深圳");
items.add("广州");
items.add("武汉");
items.add("济南");
items.add("重庆");
items.add("长沙");
items.add("大连");
items.add("南京");
items.add("石家庄");
dragGridLayout.setItems(items);
final DragGridLayout dragGridLayout2 = (DragGridLayout) findViewById(R.id.dragGridLayout2);
List<String> items2 = new ArrayList<>();
items2.add("日本");
items2.add("东京");
items2.add("韩国");
items2.add("新加坡");
items2.add("纽约");
items2.add("常德");
items2.add("广西");
items2.add("哈尔滨");
items2.add("南昌");
items2.add("无锡");
items2.add("海南");
dragGridLayout2.setItems(items2);
dragGridLayout2.setHasCanDrag(false);
分别点击两个控件中item进行相互交换
[Java] 纯文本查看 复制代码 //设置条目点击监听
dragGridLayout.setOnDragItemClickListener(new DragGridLayout.OnDragItemClickListener() {
@Override
public void onDragItemClick(TextView tv) {
//移除点击的条目,把条目添加到下面的Gridlayout
dragGridLayout.removeView(tv);//移除是需要时间,不能直接添加
dragGridLayout2.addItem(tv.getText().toString());
}
});
dragGridLayout2.setOnDragItemClickListener(new DragGridLayout.OnDragItemClickListener() {
@Override
public void onDragItemClick(TextView tv) {
//移除点击的条目,把条目添加到上面的Gridlayout
dragGridLayout2.removeView(tv);//移除是需要时间,不能直接添加
dragGridLayout.addItem(tv.getText().toString());
}
});
注意:在添加时,调用 dragGridLayout的addItem方法,进行添加处理 dragGridLayout2.removeView(tv);//移除是需要时间,不能直接添加
dragGridLayout.addItem(tv.getText().toString());
|