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;   //控件移动时设置位置LayoutParams
private 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 如何拖动控件的实现就讲完了。


就这么简单。



猜你喜欢

转载自blog.csdn.net/bzlj2912009596/article/details/80059105