android 如何拖动控件的实现
今天,简单讲讲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; //控件长按的位置private RelativeLayout 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 如何拖动控件的实现就讲完了。
就这么简单。
更多相关文章
- Android(安卓)2048游戏设计
- Android--布局方式(RelativeLayout)学习
- android xml注意事项
- 【Android】18.1 利用安卓内置的定位服务实现位置跟踪
- Android(安卓)通过selector改变状态
- Android(安卓)自定义View——自定义ProgressBar
- [置顶] 我的Android进阶之旅------>Android中android:visibility
- 转载:android获取当前位置的三种方式
- Android中设置半个屏幕大小且居中的按钮布局 (layout_weight属性