这个可拖动的图标写的比较简单,当时产品给的需求是放一个小icon,当做广告,在4个主页面都可以显示拖动
所以自定义的时候就直接继承了ImageView,下面直接上代码吧,要注意的是,获取屏幕高度的时候要减去状态栏的高度
package com.example.myapplication;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.ImageView;
import java.lang.reflect.Field;
/**
* author: whp
* date: 2018/5/15
*
* @author 99057
*/
@SuppressLint("AppCompatCustomView")
public class CustomDragView extends ImageView {
private int width;
private int height;
private int screenWidth;
private int screenHeight;
private float downX;
private float downY;
private Context mContext;
/**
* 是否拖动
*/
private boolean isDrag = false;
public CustomDragView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
screenWidth = getScreenWidth(mContext);
screenHeight = getScreenHeight(mContext) - getStatusBarHeight(mContext);
}
public boolean isDrag() {
return isDrag;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (this.isEnabled()) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrag = false;
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
final float xDistance = event.getX() - downX;
final float yDistance = event.getY() - downY;
int l, r, t, b;
//当水平或者垂直滑动距离大于10,才算拖动事件
if (Math.abs(xDistance) > 10 || Math.abs(yDistance) > 10) {
isDrag = true;
l = (int) (getLeft() + xDistance);
r = l + width;
t = (int) (getTop() + yDistance);
b = t + height;
if (l < 0) {
l = 0;
r = l + width;
} else if (r > screenWidth) {
r = screenWidth;
l = r - width;
}
if (t < 0) {
t = 0;
b = t + height;
} else if (b > screenHeight) {
b = screenHeight;
t = b - height;
}
this.layout(l, t, r, b);
}
break;
case MotionEvent.ACTION_UP:
setPressed(false);
break;
case MotionEvent.ACTION_CANCEL:
setPressed(false);
break;
default:
break;
}
return true;
}
return false;
}
/**
* 获取屏幕的宽
*
* @param context
* @return
*/
public static int getScreenWidth(Context context) {
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
/**
* 获取屏幕的高
*
* @param context
* @return
*/
public static int getScreenHeight(Context context) {
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
/**
* 获取状态栏高度
*
* @param context
* @return
*/
private int getStatusBarHeight(Context context) {
Class<?> c;
Object obj;
Field field;
int x, statusBarHeight = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return statusBarHeight;
}
}
package com.example.myapplication;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.lang.reflect.Field;
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
private CustomDragView mCustomDragView;
private RelativeLayout mRootLayout;
private int xDelta;
private int yDelta;
private float mDownX;
private float mDownY;
private int mScreenWidth;
private int mScreenHeight;
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCustomDragView = findViewById(R.id.CustomDragView);
mRootLayout = findViewById(R.id.rootLayout);
mScreenWidth = CustomDragView.getScreenWidth(this);
mScreenHeight = CustomDragView.getScreenHeight(this);
mCustomDragView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "点击事件", Toast.LENGTH_LONG).show();
}
});
mCustomDragView.setOnTouchListener(this);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
final int x = (int) event.getRawX();
final int y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mDownX = event.getRawX();
mDownY = event.getRawY();
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view
.getLayoutParams();
xDelta = x - params.leftMargin;
yDelta = y - params.topMargin;
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
int xDistance = x - xDelta;
int yDistance = y - yDelta;
int imgWidth = mCustomDragView.getWidth();
int imgHeight = mCustomDragView.getHeight();
if (xDistance < 0) {
xDistance = 0;
}
if (yDistance < 0) {
yDistance = 0;
}
if ((xDistance + imgWidth) > mScreenWidth) {
xDistance = mScreenWidth - imgWidth;
}
if ((yDistance + imgHeight) > mScreenHeight) {
yDistance = mScreenHeight - imgHeight;
}
layoutParams.leftMargin = xDistance;
layoutParams.topMargin = yDistance;
view.setLayoutParams(layoutParams);
break;
case MotionEvent.ACTION_UP:
//检测移动的距离,如果很小认为是点击事件
if (Math.abs(event.getRawX() - mDownX) < 10 && Math.abs(event.getRawY() - mDownY) < 10) {
try {
//响应点击事件,通过反射获取mListenerInfo实例
Field field = View.class.getDeclaredField("mListenerInfo");
field.setAccessible(true);
//获取mListenerInfo里面的mOnClickListener
Object object = field.get(view);
field = object.getClass().getDeclaredField("mOnClickListener");
field.setAccessible(true);
object = field.get(object);
//点击事件
if (object != null && object instanceof View.OnClickListener) {
((View.OnClickListener) object).onClick(view);
}
} catch (Exception e) {
Log.d("onTouch==>", e.getMessage());
}
}
break;
default:
break;
}
mRootLayout.invalidate();
return true;
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootLayout"
tools:context="com.example.myapplication.MainActivity">
<com.example.myapplication.CustomDragView
android:id="@+id/CustomDragView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
</RelativeLayout>