今天,简单讲讲android如何拖动控件。
之前,需要做一个功能,实现控件按照手势进行拖动,拖动到移动位置时可以进行一些操作。当时不知道怎么做,于是在网上查找了资料,终于是解决了这个问题。这里记录一下。
一.使用view.layout(left, top, right, bottom)实现拖动。
1.按下图搞懂几个坐标
视图宽度 view.getWidth();
视图高度 view.getHeight()
橘色线:view.getLeft()
蓝色线:view.getRight()
红色线:view.getTop()
粉色线:view.getBottom()
上下左右的偏移都是相对于(0.0)来说的
2. MotionEvent类中 getRowX()和 getX()
1、event.getRowX():触摸点相对于屏幕原点的x坐标
2、event.getX(): 触摸点相对于其所在组件原点的x坐标
下面是具体的代码
package com.xugongming38.dragview; import android.content.Context; import
android.content.SharedPreferences; import
android.support.v7.app.AppCompatActivity; import android.os.Bundle; import
android.view.MotionEvent; import android.view.View; import
android.widget.ImageView; public class MainActivity extends AppCompatActivity
implements View.OnTouchListener{ private ImageView iv_dv_view; private int sx;
private int sy; private SharedPreferences sp; @Override protected void
onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if (getSupportActionBar() != null){
getSupportActionBar().hide(); } sp = this.getSharedPreferences("config",
Context.MODE_PRIVATE); iv_dv_view = (ImageView)
this.findViewById(R.id.iv_dv_view); sp = this.getSharedPreferences("config",
Context.MODE_PRIVATE); iv_dv_view.setOnTouchListener(this); } @Override
protected void onResume() { super.onResume(); } @Override public boolean
onTouch(View v, MotionEvent event) { switch (v.getId()) { // 如果手指放在imageView上拖动
case R.id.iv_dv_view: // event.getRawX(); //获取手指第一次接触屏幕在x方向的坐标 switch
(event.getAction()) { case MotionEvent.ACTION_DOWN:// 获取手指第一次接触屏幕 sx = (int)
event.getRawX(); sy = (int) event.getRawY();
iv_dv_view.setImageResource(R.drawable.t); break; case
MotionEvent.ACTION_MOVE:// 手指在屏幕上移动对应的事件 int x = (int) event.getRawX(); int y =
(int) event.getRawY(); // 获取手指移动的距离 int dx = x - sx; int dy = y - sy; //
得到imageView最开始的各顶点的坐标 int l = iv_dv_view.getLeft(); int r =
iv_dv_view.getRight(); int t = iv_dv_view.getTop(); int b =
iv_dv_view.getBottom(); // 更改imageView在窗体的位置 iv_dv_view.layout(l + dx, t + dy,
r + dx, b + dy); // 获取移动后的位置 sx = (int) event.getRawX(); sy = (int)
event.getRawY(); break; case MotionEvent.ACTION_UP:// 手指离开屏幕对应事件 //
记录最后图片在窗体的位置 int lasty = iv_dv_view.getTop(); int lastx = iv_dv_view.getLeft();
iv_dv_view.setImageResource(R.drawable.next); SharedPreferences.Editor editor =
sp.edit(); editor.putInt("lasty", lasty); editor.putInt("lastx", lastx);
editor.commit(); break; } break; } return true;// 不会中断触摸事件的返回 } }
简单讲讲,这个很简单,就是设置控件的setOnTouchListener,记录在控件按下的位置,然后计算滑动的距离,最后使用iv_dv_view.layout(l
+ dx, t + dy, r + dx, b +
dy);改imageView在窗体的位置。不过我在项目内这样使用时,却发现自己定义的控件滑动的时候不停的闪烁,所以这个代码可能只使用于简单的控件,对于复杂的控件可能不行。
二.使用LayoutParams实现控件的拖动。
1.定义变量
private boolean isLongPress = false; private int startX, startY; //控件长按的位置
privateRelativeLayout curPressView; private LinearLayout.LayoutParams params;
//控件的LayoutParams,便于抬起时恢复控件位置private LinearLayout.LayoutParams m_LinearParams;
//控件移动时设置位置LayoutParamsprivate LinearLayout mLlDeleteCamera; private ImageView
mImgDeleteCamera; private int[] location = new int[2]; private int deleteHeight
=0; private boolean isTouchDelete = false;
2.记录长按时的位置
@Override public void onLongPress(MotionEvent event) { super.onLongPress(event)
; isLongPress = true; startX = (int) event.getRawX(); startY = (int)
event.getRawY(); if (m_LinearParams == null) { m_LinearParams = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT, 1); } curPressView = (RelativeLayout)
monitorView.findView(MonitorView.MONITOR_RL_ID, channelCurSelected); params = (
LinearLayout.LayoutParams) curPressView.getLayoutParams(); if
(checkCurrentItemStatusByCloseSingVideo(channelCurSelected)) { mLlDeleteCamera
.setVisibility(View.VISIBLE); if (!fullScreen) { monitorContent
.getLocationOnScreen(location); deleteHeight = location[1] - PublicFunction.
dip2px(MyApplication.app, 50f); } else { deleteHeight = 0; } } //
Log.e("test_LongPres", "onLongPress " + monitorContent.getHeight() + " " +
location[1] + " " + deleteHeight); }
滑动控件,这个在public boolean onTouch(View v, MotionEvent event)函数里
if (isLongPress) { if (curPressView == null) { isLongPress = true; return
gestureDetector.onTouchEvent(event); } switch (event.getAction()) { case
MotionEvent.ACTION_MOVE:// 手指在屏幕上移动对应的事件 int dx = (int) event.getRawX() - startX
; int dy = (int) event.getRawY() - startY; m_LinearParams.leftMargin = params.
leftMargin+ dx; m_LinearParams.rightMargin = params.rightMargin - dx;
m_LinearParams.topMargin = params.topMargin + dy; m_LinearParams.bottomMargin =
params.bottomMargin - dy; curPressView.setLayoutParams(m_LinearParams);
curPressView.getLocationOnScreen(location); if
(checkCurrentItemStatusByCloseSingVideo(channelCurSelected)) { if (location[1] <
deleteHeight) { if (isTouchDelete == false) { mLlDeleteCamera
.setBackgroundColor(Color.RED); mImgDeleteCamera.setImageResource(R.drawable.
delete_camera_2); isTouchDelete = true; } } else { if (isTouchDelete) {
mLlDeleteCamera.setBackgroundResource(R.color.colorPrimaryNormal);
mImgDeleteCamera.setImageResource(R.drawable.delete_camera_1); isTouchDelete =
false; } } // Log.e("test_LongPres", "ACTION_MOVE: " +
m_LinearParams.leftMargin + " " + m_LinearParams.topMargin + " " +
m_LinearParams.rightMargin + " " + m_LinearParams.bottomMargin// + location[0]
+ " " + location[1]); } break; case MotionEvent.ACTION_UP:// 手指离开屏幕对应事件
curPressView.setLayoutParams(params); isLongPress = false; curPressView = null;
params= null; mLlDeleteCamera.setVisibility(View.GONE); mLlDeleteCamera
.setBackgroundResource(R.color.colorPrimaryNormal); mImgDeleteCamera
.setImageResource(R.drawable.delete_camera_1); // Log.e("test_LongPres",
"ACTION_UP " + isTouchDelete); isTouchDelete = false; break; default: break; }
return true;
简单讲讲,因为我的需求是长按控件,才可以拖动控件,所以首先获取长按时点击的位置,还有控件的LinearLayout.LayoutParams,然后计算滑动的距离,设置LinearLayout.LayoutParams的Margin,这样控件基本就可以拖动。这里使用curPressView.getLocationOnScreen(location);是为了获取控件的坐标,当控件移动到某个位置时,进行一些逻辑操作。
这个是我自己在代码里实现了功能,控件拖动是正常的,而且没有闪烁的现象。大家有兴趣的可以自己查找资料实现一下功能。
android 如何拖动控件的实现就讲完了。
就这么简单。
热门工具 换一换