【问题标题】:Help with Android UI ListView problems帮助解决 Android UI ListView 问题
【发布时间】:2011-11-14 14:16:32
【问题描述】:

要理解这个问题,first read how this method works.

我正在尝试实现拖放ListView,一切正常,但遇到了 一个路障。所以我不必处理所有事情,我正在拦截(但返回 false)MotionEvents 发送到 ListView,让它处理滚动和东西。当我想开始拖动一个项目时,我返回 true 并处理所有拖动的东西。除了一件事,一切都很好。当确定发生长按时(在 onInterceptTouchEvent 中)开始拖动(拖放)。我得到了Bitmap 的图像,我像这样拖动。 itemPositition 是被选中项目的索引。

(省略不相关的部分)

...
View dragItem = mListView.getChildAt(itemPosition);
dragItem.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(dragItem.getDrawingCache());
mDragImage = new ImageView(mContext);
mDragImage.setImageBitmap(bitmap);
...

问题是,mDragImage 是这样的纯黑色。

但是,如果我不让 ListView 处理任何事情。如,我在ACTION_DOWN 上开始拖动并在ACTION_UP 上停止,mDragImage 看起来符合预期(但我显然失去了滚动能力)。

由于拖动是通过长按开始的,因此 ListView 有机会在长按发生之前做一些事情。这是我对为什么会发生这种情况的猜测。当一个项目被按下时,它被 ListView 突出显示。在这样做的某个地方,它弄乱了位图。所以当我去拿它时,它处于一种奇怪的状态(全黑)。

我看到了两种解决此问题的方法,但我都不知道该怎么做。

  1. 从头开始创建图像。

  2. 自己处理突出显示(如果这是问题所在)。

选项 2 对我来说似乎更好,但我查看了文档和源代码却不知道该怎么做。以下是我做过/尝试过的一些事情。

  • 我设置了setOnItemClickListener(...)setOnItemSelectedListener(...) 使用空方法(突出显示 仍然发生)。 (在有人建议之前,打电话给 setOnClickListener 导致运行时错误。)

  • 我还研究过尝试让 ListView 创建一个新项目 (对于选项 2),但找不到方法。

  • 花了 45 分钟浏览源代码和 试图确定突出显示位置的文档 发生了(我从来没有找到过)。

任何解决此问题的帮助将不胜感激。

(EDIT1 开始)

所以我实际上不知道 onLongClickListener 是否工作,我在认为它之前犯了一个错误。我正在尝试设置它,当我发现它时会更新。

(编辑1结束)

发帖前的最后一分钟编辑。我刚才尝试使用onLongClickListener,图像很好。我仍然想知道是否有其他方法。我必须如何使用 onLongClickListener 才能让事情正常工作是丑陋的,但它确实有效。我也花了很多时间试图弄清楚这一点,很高兴找到答案。我仍然希望能够更改/处理突出显示的颜色,默认的橙色并不漂亮。哦,对帖子的长度感到抱歉。在提供我认为需要的所有信息的同时,我想不出办法让它更短。

【问题讨论】:

    标签: android drag-and-drop android-listview highlighting


    【解决方案1】:

    使用此代码,它允许操作药物并放入ListView:

    public class DraggableListView extends ListView {
    
        private static final String LOG_TAG = "tasks365";
    
        private static final int END_OF_LIST_POSITION = -2;
    
        private DropListener mDropListener;
        private int draggingItemHoverPosition;
        private int dragStartPosition; // where was the dragged item originally
        private int mUpperBound; // scroll the view when dragging point is moving out of this bound
        private int mLowerBound; // scroll the view when dragging point is moving out of this bound
        private int touchSlop;
        private Dragging dragging;
        private GestureDetector longPressDetector;
    
        public DraggableListView(Context context, AttributeSet attrs) {
            this(context, attrs, android.R.attr.listViewStyle);
        }
    
        public DraggableListView(final Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    
            longPressDetector = new GestureDetector(getContext(), new SimpleOnGestureListener() {
                @Override
                public void onLongPress(final MotionEvent e) {
                    int x = (int) e.getX();
                    final int y = (int) e.getY();
    
                    int itemnum = pointToPosition(x, y);
                    if (itemnum == AdapterView.INVALID_POSITION) {
                        return;
                    }
    
                    if (dragging != null) {
                        dragging.stop();
                        dragging = null;
                    }
    
                    final View item = getChildAt(itemnum - getFirstVisiblePosition());
                    item.setPressed(false);
                    dragging = new Dragging(getContext());
                    dragging.start(y, ((int) e.getRawY()) - y, item);
                    draggingItemHoverPosition = itemnum;
                    dragStartPosition = draggingItemHoverPosition;
    
                    int height = getHeight();
                    mUpperBound = Math.min(y - touchSlop, height / 3);
                    mLowerBound = Math.max(y + touchSlop, height * 2 / 3);
                }
            });
    
            setOnItemLongClickListener(new OnItemLongClickListener() {
                @SuppressWarnings("unused")
    
                public boolean onItemLongClick(AdapterView<?> paramAdapterView, View paramView, int paramInt, long paramLong) {
                    // Return true to let AbsListView reset touch mode
                    // Without this handler, the pressed item will keep highlight.
                    return true;
                }
            });
        }
    
        /* pointToPosition() doesn't consider invisible views, but we need to, so implement a slightly different version. */
        private int myPointToPosition(int x, int y) {
            if (y < 0) {
                return getFirstVisiblePosition();
            }
            Rect frame = new Rect();
            final int count = getChildCount();
            for (int i = 0; i < count; i++) {
                final View child = getChildAt(i);
                child.getHitRect(frame);
                if (frame.contains(x, y)) {
                    return getFirstVisiblePosition() + i;
                }
            }
            if ((x >= frame.left) && (x < frame.right) && (y >= frame.bottom)) {
                return END_OF_LIST_POSITION;
            }
            return INVALID_POSITION;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if (longPressDetector.onTouchEvent(ev)) {
                return true;
            }
    
            if ((dragging == null) || (mDropListener == null)) {
                // it is not dragging, or there is no drop listener
                return super.onTouchEvent(ev);
            }
    
            int action = ev.getAction();
            switch (ev.getAction()) {
    
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                dragging.stop();
                dragging = null;
    
                if (mDropListener != null) {
                    if (draggingItemHoverPosition == END_OF_LIST_POSITION) {
                        mDropListener.drop(dragStartPosition, getCount() - 1);
                    } else if (draggingItemHoverPosition != INVALID_POSITION) {
                        mDropListener.drop(dragStartPosition, draggingItemHoverPosition);
                    }
                }
                resetViews();
                break;
    
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                int x = (int) ev.getX();
                int y = (int) ev.getY();
                dragging.drag(x, y);
                int position = dragging.calculateHoverPosition();
                if (position != INVALID_POSITION) {
                    if ((action == MotionEvent.ACTION_DOWN) || (position != draggingItemHoverPosition)) {
                        draggingItemHoverPosition = position;
                        doExpansion();
                    }
                    scrollList(y);
                }
                break;
            }
            return true;
        }
    
        private void doExpansion() {
            int expanItemViewIndex = draggingItemHoverPosition - getFirstVisiblePosition();
            if (draggingItemHoverPosition >= dragStartPosition) {
                expanItemViewIndex++;
            }
    
           // Log.v(LOG_TAG, "Dragging item hovers over position " + draggingItemHoverPosition + ", expand item at index "
             //       + expanItemViewIndex);
    
            View draggingItemOriginalView = getChildAt(dragStartPosition - getFirstVisiblePosition());
            for (int i = 0;; i++) {
                View itemView = getChildAt(i);
                if (itemView == null) {
                    break;
                }
                ViewGroup.LayoutParams params = itemView.getLayoutParams();
                int height = LayoutParams.WRAP_CONTENT;
                if (itemView.equals(draggingItemOriginalView)) {
                    height = 1;
                } else if (i == expanItemViewIndex) {
                    height = itemView.getHeight() + dragging.getDraggingItemHeight();
                }
                params.height = height;
                itemView.setLayoutParams(params);
            }
        }
    
        /**
         * Reset view to original height.
         */
        private void resetViews() {
            for (int i = 0;; i++) {
                View v = getChildAt(i);
                if (v == null) {
                    layoutChildren(); // force children to be recreated where needed
                    v = getChildAt(i);
                    if (v == null) {
                        break;
                    }
                }
                ViewGroup.LayoutParams params = v.getLayoutParams();
                params.height = LayoutParams.WRAP_CONTENT;
                v.setLayoutParams(params);
            }
        }
    
        private void resetScrollBounds(int y) {
            int height = getHeight();
            if (y >= height / 3) {
                mUpperBound = height / 3;
            }
            if (y <= height * 2 / 3) {
                mLowerBound = height * 2 / 3;
            }
        }
    
        private void scrollList(int y) {
            resetScrollBounds(y);
    
            int height = getHeight();
            int speed = 0;
            if (y > mLowerBound) {
                // scroll the list up a bit
                speed = y > (height + mLowerBound) / 2 ? 16 : 4;
            } else if (y < mUpperBound) {
                // scroll the list down a bit
                speed = y < mUpperBound / 2 ? -16 : -4;
            }
            if (speed != 0) {
                int ref = pointToPosition(0, height / 2);
                if (ref == AdapterView.INVALID_POSITION) {
                    //we hit a divider or an invisible view, check somewhere else
                    ref = pointToPosition(0, height / 2 + getDividerHeight() + 64);
                }
                View v = getChildAt(ref - getFirstVisiblePosition());
                if (v != null) {
                    int pos = v.getTop();
                    setSelectionFromTop(ref, pos - speed);
                }
            }
        }
    
        public void setDropListener(DropListener l) {
            mDropListener = l;
        }
    
        public interface DropListener {
            void drop(int from, int to);
        }
    
        class Dragging {
    
            private Context context;
            private WindowManager windowManager;
            private WindowManager.LayoutParams mWindowParams;
            private ImageView mDragView;
            private Bitmap mDragBitmap;
            private int coordOffset;
            private int mDragPoint; // at what offset inside the item did the user grab it
            private int draggingItemHeight;
            private int x;
            private int y;
            private int lastY;
    
            public Dragging(Context context) {
                this.context = context;
                windowManager = (WindowManager) context.getSystemService("window");
            }
    
            /**
             * @param y
             * @param offset - the difference in y axis between screen coordinates and coordinates in this view
             * @param view - which view is dragged
             */
            public void start(int y, int offset, View view) {
                this.y = y;
                lastY = y;
                this.coordOffset = offset;
                mDragPoint = y - view.getTop();
    
                draggingItemHeight = view.getHeight();
    
                mDragView = new ImageView(context);
                mDragView.setBackgroundResource(android.R.drawable.alert_light_frame);
    
                // Create a copy of the drawing cache so that it does not get recycled
                // by the framework when the list tries to clean up memory
                view.setDrawingCacheEnabled(true);
                mDragBitmap = Bitmap.createBitmap(view.getDrawingCache());
                mDragView.setImageBitmap(mDragBitmap);
    
                mWindowParams = new WindowManager.LayoutParams();
                mWindowParams.gravity = Gravity.TOP;
                mWindowParams.x = 0;
                mWindowParams.y = y - mDragPoint + coordOffset;
                mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
                mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
                mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
                mWindowParams.format = PixelFormat.TRANSLUCENT;
                mWindowParams.windowAnimations = 0;
    
                windowManager.addView(mDragView, mWindowParams);
            }
    
            public void drag(int x, int y) {
                lastY = this.y;
                this.x = x;
                this.y = y;
                mWindowParams.y = y - mDragPoint + coordOffset;
                windowManager.updateViewLayout(mDragView, mWindowParams);
            }
    
            public void stop() {
                if (mDragView != null) {
                    windowManager.removeView(mDragView);
                    mDragView.setImageDrawable(null);
                    mDragView = null;
                }
                if (mDragBitmap != null) {
                    mDragBitmap.recycle();
                    mDragBitmap = null;
                }
            }
    
            public int getDraggingItemHeight() {
                return draggingItemHeight;
            }
    
            public int calculateHoverPosition() {
                int adjustedY = (int) (y - mDragPoint + (Math.signum(y - lastY) + 2) * draggingItemHeight / 2);
                // Log.v(LOG_TAG, "calculateHoverPosition(): lastY=" + lastY + ", y=" + y + ", adjustedY=" + adjustedY);
                int pos = myPointToPosition(0, adjustedY);
                if (pos >= 0) {
                    if (pos >= dragStartPosition) {
                        pos -= 1;
                    }
                }
                return pos;
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多