View拖拽 自定义绑定view拖拽的工具类
由于工作需求,需要用到这种处理方法所以我就写了这个
废话不多说先看效果图

接下来就看代码吧 DragDropManager
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 拖拽工具类
*/
public class DragDropManager implements View.OnTouchListener { /**
* View 集合
*/
private List<View> viewList; private static Activity mActivity;
private static DragDropManager mManager; private Map<View, ViewInfo> mViewMap; /**
* 窗口管理器,用于显示条目的快照
*/
private WindowManager mWindowManager; /**
* 窗口管理的布局参数
*/
private WindowManager.LayoutParams mWindowLayoutParams; /**
* 悬浮的imageView
*/
private ImageView mDragPhotoView;
private Bitmap mDragPhotoBitmap;
private float moveX;
private float moveY; private IDragDropListener listener; public DragDropManager() {
viewList = new ArrayList<>();
mViewMap = new HashMap<>();
} public static DragDropManager getInstance(Activity activity) {
mActivity = activity;
if (mManager == null) {
mManager = new DragDropManager();
}
return mManager;
} /**
* 绑定view
*/
public void bindView(View... views) {
viewList.clear();
for (View view : views) {
view.setOnTouchListener(this);
if(view instanceof TextView){
view.setOnClickListener(null);
}else if(view instanceof ViewGroup){
view.setOnClickListener(null);
}
viewList.add(view);
}
} /**
* 添加view
*
* @param views
*/
public void addView(View... views) {
for (View view : views) {
view.setOnTouchListener(this);
viewList.add(view);
}
} /**
* 设置监听事件
* @param listener
*/
public void setListener(IDragDropListener listener){
this.listener = listener;
} @Override
public boolean onTouch(View view, MotionEvent event) { int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.i("tag", "生成图像");
//首先初始化每个控件的坐标信息
initViewLayout();
//判断出点击的是哪个控件 并悬浮出哪个控件
createDragPhotoView(view);
moveX = event.getX();
moveY = event.getY();
//回调监听
if(listener != null){
listener.startDragDrop(view.getId());
}
break;
case MotionEvent.ACTION_MOVE:
mWindowLayoutParams.x = (int) (mViewMap.get(view).x + (event.getX() - moveX));
mWindowLayoutParams.y = (int) (mViewMap.get(view).y + (event.getY() - moveY));
mWindowManager.updateViewLayout(mDragPhotoView, mWindowLayoutParams);
Log.i("tag", "移动图像 x:"+(view.getX() + (event.getX() - moveX))+" y:" + (view.getY() + (event.getY() - moveY)));
break;
case MotionEvent.ACTION_UP:
Log.i("tag", "去掉图像"); //
if(listener != null) {
for (View tempView : viewList) {
if (tempView.getId() != view.getId()) {
ViewInfo viewInfo = mViewMap.get(tempView);
if (event.getRawX() > viewInfo.x && event.getRawY() > viewInfo.y
&& event.getRawX() < (viewInfo.x + viewInfo.width) && event.getRawY() < (viewInfo.y + viewInfo.height)) {
listener.endDragDrop(view.getId(),tempView.getId());
break;
}
}
}
} // 移除快照
if (mDragPhotoView != null) {
mWindowManager.removeView(mDragPhotoView);
mDragPhotoView.setImageDrawable(null);
mDragPhotoBitmap.recycle();
mDragPhotoBitmap = null;
mDragPhotoView = null;
}
break;
}
return false;
} /**
* 初始化每个控件的坐标信息
*/
private void initViewLayout() {
mViewMap.clear();
int[] location = new int[2];
for (View view : viewList) {
view.getLocationInWindow(location);
ViewInfo viewInfo = new ViewInfo(view, location[0], location[1], view.getMeasuredHeight(), view.getMeasuredWidth());
mViewMap.put(view, viewInfo);
}
} /**
* 创建拖拽快照
*/
private void createDragPhotoView(View view) {
// 进行绘图缓存
view.setDrawingCacheEnabled(true);
// 提取缓存中的图片
mDragPhotoBitmap = Bitmap.createBitmap(view.getDrawingCache());
// 获取当前窗口管理器
mWindowManager = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
// 创建布局参数
mWindowLayoutParams = new WindowManager.LayoutParams();
mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowLayoutParams.gravity = Gravity.TOP | Gravity.START;
mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; // 期望的图片为半透明效果,但设置其他值并没有看到不一样的效果
// 下面这些参数能够帮助准确定位到选中项点击位置
mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowLayoutParams.windowAnimations = 0; // 无动画
mWindowLayoutParams.alpha = 0.6f; // 微透明 mWindowLayoutParams.x = (int) mViewMap.get(view).x;
mWindowLayoutParams.y = (int) mViewMap.get(view).y;
mDragPhotoView = new ImageView(mActivity);
mDragPhotoView.setImageBitmap(mDragPhotoBitmap);
mWindowManager.addView(mDragPhotoView, mWindowLayoutParams);
} /**
* 监听接口
*/
public interface IDragDropListener{ /**
* 开始拖动
* @param startViewId 返回当前view的ID
*/
void startDragDrop(int startViewId); /**
* 结束拖动
* @param startViewId 返回当前view的ID
* @param endViewId 返回覆盖在某个view的ID
*/
void endDragDrop(int startViewId,int endViewId);
} /**
* 记录当前view的坐标和宽高信息
*/
class ViewInfo { private View view;
private float x;
private float y;
private float height;
private float width; public ViewInfo(View view, float x, float y, float height, float width) {
this.view = view;
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
}
}
使用方法
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast; public class MainActivity extends AppCompatActivity { private DragDropManager dragDropManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.tvTitle);
TextView tegg = findViewById(R.id.tvTitlegg);
Button btnTuo = findViewById(R.id.btnTuo);
dragDropManager = DragDropManager.getInstance(this);
dragDropManager.bindView(textView,btnTuo,tegg);
dragDropManager.setListener(new DragDropManager.IDragDropListener() {
@Override
public void startDragDrop(int startViewId) {
Toast.makeText(MainActivity.this,"开始悬浮",0).show();
} @Override
public void endDragDrop(int startViewId, int endViewId) {
Toast.makeText(MainActivity.this,"开始悬浮 sID:" + startViewId + "//endID : " + endViewId,0).show();
}
}); textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"text dianji",0).show();
}
});
btnTuo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"btnTuo dianji",0).show();
}
});
}
}
代码demo
demo下载
参考博客:https://blog.csdn.net/a10615/article/details/51366459
View拖拽 自定义绑定view拖拽的工具类的更多相关文章
- 自定义响应结构 Json格式转换 工具类
import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterx ...
- 让一个view 或者控件不支持拖拽
让一个view 或者控件不支持拖拽: dragView.userInteractionEnabled = NO;
- 使用knockout-sortable实现对自定义菜单的拖拽排序
在开始之前,照例,我们先看效果和功能实现. 关于自定义菜单的实现,这里就不多说了,需要了解的请访问:http://www.cnblogs.com/codelove/p/4838766.html 这里需 ...
- 自定义 Collection View 布局
自定义 Collection View 布局 answer-huang 29 Mar 2014 分享文章 UICollectionView 在 iOS6 中第一次被引入,也是 UIKit 视图类中的一 ...
- iOS系列译文:自定义Collection View布局
原文出处: Ole Begemann 译文出处: 黄爱武(@answer-huang).欢迎加入技术翻译小组. UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一 ...
- 自定义Collection View布局
转自answer-huang的博客 原文出自:Custom Collection View Layouts UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一颗 ...
- [asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文
我们在asp.net 开发中已经封装了最强大的HttpContext,我们可以在HttpContext中可以获取到几乎任何想获取的东西,也可以在HttpContext写入需要返回客户端的信息.但是这些 ...
- ios --xib自定义,解决在导航栏不透明的情况下,自定义xib view高度被压缩64的问题
在使用xib自定义view的时候,个人习惯性的直接使用xib中的约束,所以自然而然的要打开Autolayout.以前在使用的时候没有发现什么问题,最近项目中使用的时候突然发现在导航栏透明的情况下,出现 ...
- Android XML中引用自定义内部类view的四个why
今天碰到了在XML中应用以内部类形式定义的自定义view,结果遇到了一些坑.虽然通过看了一些前辈写的文章解决了这个问题,但是我看到的几篇都没有完整说清楚why,于是决定做这个总结. 使用自定义内部类v ...
随机推荐
- PhantomJS 基础及示例
腾讯云技术社区-掘金主页持续为大家呈现云计算技术文章,欢迎大家关注! 作者:link 概述 PhantomJS is a headless WebKit scriptable with a JavaS ...
- Microsoft office(1)分页符和分节符
Microsoft office下的页面布局中的分页符和分节符的区别: 分页符:标记一页的终止并开始下一页的点 分节符:插入分节符并在下一页开始新节 一般情况下,分节符在分页符外围,分节符一般是各种格 ...
- Linux下使用GDB进行调试
Linux下使用GDB进行调试的常用命令记于此. $ sudo su # g++ -g test.cpp -o test -pthread # gdb test <------- ...
- scrapy-splash抓取动态数据例子十一
一.介绍 本例子用scrapy-splash抓取活动树网站给定关键字抓取活动信息. 给定关键字:数字:融合:电视 抓取信息内如下: 1.资讯标题 2.资讯链接 3.资讯时间 4.资讯来源 二.网站信息 ...
- Android Handler,Loop,HandlerThread消息处理
博客标题也不知道写什么好,仅仅是近期有时候发现Handler,Loop,HandlerThread非常easy混淆,所以做了简单的笔记处理: 第一种 : 大概的意思给出说明图: watermark/2 ...
- Java笔记3:Eclipse添加jar包
本文以jedis包为例,演示Eclipse如何添加和使用jar包. 1 建立一个名为ImportJarDemo的JavaProject.在该工程下建立一个libs的文件夹. 2 将下载的jedis ...
- javascript http库axios
还是那个开源项目中的代码看到的: 直接看axios官方的介绍吧,里面的用法介绍很全: https://github.com/mzabriskie/axios Installing Using npm: ...
- 两列布局(浮动、定位、flex)和三列布局(圣杯、双飞翼、flex)
demo 各种布局演示 https://jsfiddle.net/mayufo/qp890peq/1/ 两栏布局 浮动 <div class="box1"> <d ...
- mysql 5.6 修改root原始密码不为空方法
mysql 5.6安装好之后,是默认root用户的密码为空的,此时为了安全性需要修改密码不为空,修改方法为: cmd或者mysql 5.6 command line client登陆之后,输入一下命令 ...
- android 类似微信的摇一摇实现
一.在 AndroidManifest.xml 中添加操作权限 <uses-permission android:name="android.permission.VIBRATE&qu ...