Android 偶遇Drag and Drop
作者萌动小彩笔
2017.04.20 09:51字数 826阅读 3评论 0喜欢 0
最近在项目的迭代过程中偶遇有关Drag And Drop的知识点,于是便对此知识点进行了一些简单的探究,在此记录下使用心得。
效果图
GIF.gif
需求介绍
将题干中所提供的图片拖拽到答题框内进行排序,题干区域内的图片不能进行相互切换,答题框内的图片可进行相互替换,将答题框内的图片拖拽到题干中进行图片的删除。
根据官方文档所提供的思路
当用户做出某种您识别为开始拖拽数据的手势时,拖放操作开始。
作为响应,您的应用会告知系统正在开始拖拽。 系统回调应用,以获取正在拖拽的数据的表示。
用户手指在当前布局上移动此表示(“拖拽阴影”)的过程中,系统将拖拽事件发送到与布局中的
View对象相关联的拖拽事件侦听器对象和拖拽事件回调方法。 用户释放拖拽阴影后,系统立即结束拖拽操作。
在开始拖拽时,将您想要移动的数据和描述此数据的元数据均包含在系统调用中。
在拖拽期间,系统会将拖拽事件发送到布局中每个视图的拖拽事件侦听器或回调方法。
这些侦听器或回调方法可使用元数据来确定其在数据被放下时是否想要接受这些数据。
如果用户将数据放到某个视图对象上,并且该视图对象的侦听器或回调方法之前已告知系统它想要接受放下的数据,则系统会将该数据发送到拖拽事件中的侦听器或回调方法。
实现方法
从实现View.OnDragListener的类创建拖拽事件侦听器对象(“listeners”)。 使用视图对象的setOnDragListener()方法为视图设置拖拽事件侦听器对象。 每个视图对象还有一个onDragEvent()回调方法。
DragEvent 操作类型.png
拖拽阴影
在拖放操作期间,系统会显示用户拖拽的图像。 对于数据移动,此图像表示正在拖拽的数据。对于其他操作,此图像表示拖拽操作的某个方面。此图像被称为拖拽阴影。您使用为View.DragShadowBuilder对象声明的方法创建拖拽阴影,然后在使用startDrag()开始拖拽时将其传递给系统。 作为系统对startDrag()的响应的一部分,系统会调用您在View.DragShadowBuilder中定义的回调方法以获取拖拽阴影。
代码展示
activity_main.xml布局
标题 title.xml布局
题目内容 content.xml布局
MainAcitivity
public
class MainActivity extends AppCompatActivity { private RecyclerView
recyclerView;//在网络上随便找了几张图片的地址 private String[] images =
{"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492574781205&di=2a8fb3d3916f88a21ec33d08e5795e61&imgtype=0&src=http%3A%2F%2Ffile.cbda.cn%2Fuploadfile%2F2015%2F0330%2F20150330041852447.jpg","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492574781204&di=1259124b260d828df88602e849d27bed&imgtype=0&src=http%3A%2F%2Fpic24.nipic.com%2F20121023%2F5692504_105430688142_2.jpg","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492574781204&di=c0bbe94467bfb35fd30d76c0e9638a4d&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fw%253D580%2Fsign%3Deb4ecc6249fbfbeddc59367748f1f78e%2F36cd4b2309f7905229c31a630ef3d7ca7acbd57c.jpg","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492574781204&di=7c1c2ae590318f9d1b1473b54ef97f12&imgtype=0&src=http%3A%2F%2Fpic2.ooopic.com%2F11%2F44%2F22%2F15b1OOOPIC2a.jpg","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492574781203&di=7466a35b511204029646e534a88e5297&imgtype=0&src=http%3A%2F%2Fimg01.taopic.com%2F141127%2F240494-14112FQ23021.jpg","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1492574781202&di=a24bb915d997bae104a7b98a1311682a&imgtype=0&src=http%3A%2F%2Feasyread.ph.126.net%2FJUvXxLCFCK7w8tDEvOaEYg%3D%3D%2F8796093022405405071.jpg"};
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); recyclerView =
((RecyclerView) findViewById(R.id.recyclerView)); List questions =
new ArrayList<>(); List answers = new
ArrayList<>();//为题干和答案添加内容for(inti =0; i <6; i++) {
questions.add(images[i]); answers.add(""); }
//创建布局管理器 GridLayoutManager manager = new
GridLayoutManager(this,3);
recyclerView.setLayoutManager(manager); final RecyclerViewAdapter
adapter = new RecyclerViewAdapter(this,questions,answers);
recyclerView.setAdapter(adapter);//默认情况下,每个项目占1。你可以改变它通过提供一个定制的GridLayoutManager。通过setSpanSizeLookup
SpanSizeLookup实例(SpanSizeLookup)。 manager.setSpanSizeLookup(new
GridLayoutManager.SpanSizeLookup() { @Override
publicintgetSpanSize(intposition) {//通过判断布局类型来指定它们的跨度intviewType =
adapter.getItemViewType(position);returnviewType ==
RecyclerViewAdapter.QUESTION_CONTENT || viewType ==
RecyclerViewAdapter.ANSWER_CONTENT?1:3; } }); }}
RecyclerViewAdapter
/**
* Created by xiaolong on 2017/4/18.
*/publicclassRecyclerViewAdapterextendsRecyclerView.Adapter{//问题的标题publicstaticfinalintQUESTION_HEADER
=1;//答案标题提示publicstaticfinalintANSWER_HEADER
=2;//题干内容publicstaticfinalintQUESTION_CONTENT
=3;//答案内容publicstaticfinalintANSWER_CONTENT
=4;//标题数量publicstaticfinalintHEADER_COUNT =2;//上下文privateContext
context;//题干和答案数据资源privateList
questions,answers;//布局加载器privateLayoutInflater
inflater;publicRecyclerViewAdapter(Context context, List questions, List
answers){this.context = context;this.questions = questions;this.answers
= answers; inflater = LayoutInflater.from(context);
}@OverridepublicintgetItemViewType(intposition){if(position ==0)
{returnQUESTION_HEADER; }elseif(position == questions.size()
+1){returnANSWER_HEADER; }elseif(position >0&&
position < questions.size() +1){returnQUESTION_CONTENT;
}else{returnANSWER_CONTENT; }
}@OverridepublicRecyclerView.ViewHolderonCreateViewHolder(ViewGroup
parent,intviewType){ View view;switch(viewType)
{caseQUESTION_HEADER:caseANSWER_HEADER: view =
inflater.inflate(R.layout.title,parent,false);returnnewTitleViewHolder(view);caseQUESTION_CONTENT:caseANSWER_CONTENT:
view =
inflater.inflate(R.layout.answer,parent,false);returnnewThumViewHolder(view);
}returnnull;
}@OverridepublicvoidonBindViewHolder(finalRecyclerView.ViewHolder
holder,finalintposition){if(holderinstanceofTitleViewHolder){
TitleViewHolder titleViewHolder = (TitleViewHolder)
holder;switch(getItemViewType(position)) {caseQUESTION_HEADER:
titleViewHolder.title.setText("1.根据观察结果,按顺序排列6张图片变化");//标题一break;caseANSWER_HEADER:
titleViewHolder.title.setText("请按照顺序拖拽到下面相应的框内");//标题二break;
} }elseif(holderinstanceofThumViewHolder){finalThumViewHolder
thumViewHolder = (ThumViewHolder)
holder;switch(getItemViewType(position)) {caseQUESTION_CONTENT:
//加载题干中图片
Glide.with(context).load(questions.get(position -
1)).into(thumViewHolder.answerImage);break;caseANSWER_CONTENT:
//显示答题排序序号
thumViewHolder.orderId.setText(position - questions.size() -
HEADER_COUNT +"");//加载答案中图片Glide.with(context).load(answers.get(position
- questions.size() -
HEADER_COUNT)).into(thumViewHolder.answerImage);break; }
thumViewHolder.answerImage.setOnTouchListener(newView.OnTouchListener()
{@OverridepublicbooleanonTouch(View view, MotionEvent
motionEvent){//在移动状态下触发if(MotionEventCompat.getActionMasked(motionEvent)
== MotionEvent.ACTION_MOVE) { ClipData data =
ClipData.newPlainText("value",position
+"");//此方法在API级别24弃用。为新平台使用startDragAndDrop()版本。thumViewHolder.answerImage.startDrag(data,newView.DragShadowBuilder(view),null,0);
}returnfalse; } });
thumViewHolder.answerImage.setOnClickListener(newView.OnClickListener()
{@OverridepublicvoidonClick(View
view){//获取下标Toast.makeText(context,position+"",Toast.LENGTH_SHORT).show();
} });
thumViewHolder.answerImage.setOnDragListener(newView.OnDragListener()
{@OverridepublicbooleanonDrag(View view, DragEvent
dragEvent){switch(dragEvent.getAction())
{caseDragEvent.ACTION_DRAG_STARTED:returntrue;caseDragEvent.ACTION_DRAG_ENTERED:returntrue;caseDragEvent.ACTION_DRAG_LOCATION:returntrue;caseDragEvent.ACTION_DRAG_EXITED:returntrue;caseDragEvent.ACTION_DROP:
//得到拖动图片的下标 String
dragVal =
dragEvent.getClipData().getItemAt(0).getText().toString();intindex =
Integer.parseInt(dragVal);//进行添加和替换操作replace(index,thumViewHolder.getAdapterPosition());returntrue;caseDragEvent.ACTION_DRAG_ENDED:returntrue;
}returnfalse; } });
} }/** * 进行图片替换操作 *@paramindex *@paramadapterPosition
*/privatevoidreplace(intindex,intadapterPosition){if(index
>0&& index < questions.size() +1&& adapterPosition
< questions.size() +1) {//下标如果在题干中,不做处理return; }elseif(index
>0&& index < questions.size() +1&& adapterPosition
> questions.size() +1) {//从题干中拖拽到答题界面answers.set(adapterPosition -
questions.size() -2,questions.get(index -1)); }elseif(index >
questions.size() +1&& adapterPosition > questions.size()
+1){//答题界面中进行交换String url = answers.get(index - questions.size() -
HEADER_COUNT); answers.set(index - questions.size() -
HEADER_COUNT,answers.get(adapterPosition - questions.size() -
HEADER_COUNT)); answers.set(adapterPosition -
questions.size() - HEADER_COUNT,url); }else{
answers.set(index - questions.size() - HEADER_COUNT,""); }
notifyDataSetChanged();
}@OverridepublicintgetItemCount(){returnquestions.size() +
answers.size() +
HEADER_COUNT;//总数量}//标题ViewHolderclassTitleViewHolderextendsRecyclerView.ViewHolder{privateTextView
title;publicTitleViewHolder(View itemView){super(itemView);
title = (TextView) itemView; }
}//题干和答题ViewHolderclassThumViewHolderextendsRecyclerView.ViewHolder{privateImageView
answerImage;privateTextView orderId;publicThumViewHolder(View
itemView){super(itemView); answerImage = (ImageView)
itemView.findViewById(R.id.image); orderId = (TextView)
itemView.findViewById(R.id.num); } }}
结束语
到了这里此项目需求已经实现了,其实很简单,一看就会明白其中的原理。这是自己的第二篇文章,希望自己的文章质量会有所提高,在此提示:多读书,多看报,少吃零食,多睡觉。
网友评论