今天,简单讲讲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 如何拖动控件的实现就讲完了。


就这么简单。

更多相关文章

  1. Android(安卓)2048游戏设计
  2. Android--布局方式(RelativeLayout)学习
  3. android xml注意事项
  4. 【Android】18.1 利用安卓内置的定位服务实现位置跟踪
  5. Android(安卓)通过selector改变状态
  6. Android(安卓)自定义View——自定义ProgressBar
  7. [置顶] 我的Android进阶之旅------>Android中android:visibility
  8. 转载:android获取当前位置的三种方式
  9. Android中设置半个屏幕大小且居中的按钮布局 (layout_weight属性

随机推荐

  1. Android事件分发机制详解
  2. 如何在Android(安卓)Studio项目中导入开
  3. android了解篇
  4. Android(安卓)Gradle使用详解(三) 之 And
  5. Google将在Android(安卓)2.2中提供Adobe
  6. 在读《精通Android(安卓)3》
  7. Android多媒体学习一:Android中Image的简
  8. Android入门教程(五)之------第一个Andro
  9. Binder研究之一   制定计划
  10. 系出名门Android(10) - HTTP 通信, XML