RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 910323
Accepted
Pavel Sumarokov
Pavel Sumarokov
Asked:2020-11-23 02:44:55 +0000 UTC2020-11-23 02:44:55 +0000 UTC 2020-11-23 02:44:55 +0000 UTC

拖放视图元素 LinearLayout - 如何更改视图元素的顺序

  • 772

我有一个带有 TextView 元素的 LinearLayout。每个 TextView 元素都分配有一个处理程序

    ... new View.OnTouchListener() {

            int initialX = 0;
            int initialY = 0;
            static final int MAX_CLICK_DURATION = 200;
            long startClickTime;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        initialX = (int) event.getX();
                        initialY = (int) event.getY();
                        startClickTime = Calendar.getInstance().getTimeInMillis();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (clickDuration > MAX_CLICK_DURATION) {
                            int currentX = (int) event.getX();
                            int currentY = (int) event.getY();
                            dcl.setText(String.format(Locale.getDefault(), "(%d,%d)", currentX, currentY));
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (clickDuration < MAX_CLICK_DURATION) v.performClick();
                        break;
                }
                return true;
            }
        });

理想情况下,当我松开手指时,我打算将开始拖放的元素放在它被拉伸到的元素之前,但现在我只显示坐标,检查监听器的工作。

问题是当手指离开原始元素时,包括移动到另一个 TextView 元素,处理程序停止工作(在这个“预调试”示例中,坐标停止更新),这开始滚动包含此 LinearLayout 元素的 ScrollView .

如何使其在离开原始元素时也可以拖动,并且仅当您将手指从 TextView 元素中捏在 ScrollView 的可用空间上时才进行滚动?即使短按,您也需要保存 TextView 的 OnClick,但我或多或少想通了,这行负责:

if (clickDuration < MAX_CLICK_DURATION) v.performClick();

PS。我知道使用 DragListView 更容易做到这一点,但在这种情况下这是不可能的。TextView所在的LinearLayout是继承在层次结构深处的组件的一部分,您不能将LinearLayout更改为ListView,因为 此层次结构的其他组件将崩溃。

android
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Pavel Sumarokov
    2020-11-27T21:21:31Z2020-11-27T21:21:31Z

    我通过以下方式解决了它:

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        scrollView = null;
        ViewParent parent = this;
        while (parent != null && !(parent instanceof ScrollView)) parent = parent.getParent();
        if (parent != null) scrollView = (ScrollView) parent;
    }
    
    private int displayHeight;
    private ScrollView scrollView;
    private boolean scrollDisabled = false;
    
    private void disableScrolling() {
        if (scrollView != null) scrollView.requestDisallowInterceptTouchEvent(true);
        scrollDisabled = true;
    }
    
    private void enableScrolling() {
        if (scrollView != null) scrollView.requestDisallowInterceptTouchEvent(false);
        scrollDisabled = false;
    }
    
    private void scrollDynamically(int posY) {
        if (scrollView == null) return;
        int[] layoutOnScreen = new int[2];
        mLayout.getLocationOnScreen(layoutOnScreen);
        //здесь и в дальнейшем mLayout - LinearLayout, на котором размещены перетаскиваемые элементы
        if (layoutOnScreen[1] < 240 && posY < 300) scrollView.smoothScrollBy(0, posY < 200 ? -20 : -10);
        if (posY > displayHeight - 150) scrollView.smoothScrollBy(0, posY > displayHeight - 50 ? 20 : 10);
    }
    
    
    private void init() {
        //здесь определяется высота дисплея
        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        if (windowManager == null) return;
        Display display = windowManager.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        displayHeight = size.y;
        mLayout.setPadding(2, 4, 2, 20);
    }
    
    private final OnTouchListener DRAG_AND_DROP = new OnTouchListener() {
    
        long startClickTime;
        TextView target = null;
        TextView source = null;
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    source = (TextView) v;
                    startClickTime = Calendar.getInstance().getTimeInMillis();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (clickDuration > MAX_CLICK_DURATION) {
                        if (!scrollDisabled) disableScrolling();
                        target = null;
                        for (int i = mLayout.getChildCount(); i >= 0; --i) {
                            View anyChild = mLayout.getChildAt(i);
                            if (anyChild instanceof TextView) {
                                TextView child = (TextView) anyChild;
                                Rect bounds = new Rect();
                                child.getHitRect(bounds);
                                if (bounds.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) target = child;
                                else if (child != source) child.setTextColor(0xFFFFFFFF);
                            }
                        }
                        if (target == null) {
                            source.setTextColor(0xFF660000);
                            source.setPaintFlags(source.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
                        } else {
                            source.setPaintFlags(source.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
                            if (target != source) {
                                target.setTextColor(0xFF77FF00);
                                source.setTextColor(0xFFFF7700);
                            }
                            else source.setTextColor(0xFF77FFFF);
                        }
                        scrollDynamically((int) event.getRawY());
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (clickDuration < MAX_CLICK_DURATION) v.performClick();
                    else {
                        if (target == null) /*действия при удалении*/;
                        else {
                            target.setTextColor(0xFFFFFFFF);
                            if (target == source) /*действия при вставке*/;
                            else /*действия при перемещении*/;
                        }
                        source.setPaintFlags(source.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
                        source.setTextColor(0xFFFFFFFF);
                    }
                    enableScrolling();
                    break;
            }
            return true;
        }
    };
    

    因此,拖放提供了三个功能:删除元素、移动元素(如果目标不在屏幕上,则可以在拖动时滚动)和插入新元素。这保留了元素的 onClick 和 ScrollView 的滚动。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5