2011-09-11 18 views
5

इस सवाल को समझने के लिए first read how this method works.सहायता

मैं एक खींचें लागू करता है और ड्रॉप ListView कोशिश कर रहा हूँ, यह ठीक हो रहा है, लेकिन एक सड़क ब्लॉक में चलाने की है। तो मुझे सबकुछ संभालना नहीं है, मैं हस्तक्षेप कर रहा हूं (लेकिन झूठी वापसी) MotionEvents सूची दृश्य में भेजा गया है, इसे स्क्रॉलिंग और सामान को संभालने की अनुमति देता है। जब मैं किसी आइटम को खींचना शुरू करना चाहता हूं, तो मैं सत्य वापस लौटाता हूं और सभी खींचने वाली सामग्री को संभाला करता हूं। एक चीज को छोड़कर सब कुछ ठीक काम कर रहा है। ड्रैग (ड्रैग और ड्रॉप) तब शुरू होता है जब यह निर्धारित किया जाता है कि एक घटना के रूप में एक लंबी प्रेस (InterceptTouchEvent में)। मुझे उस छवि के लिए मिलता है जिसे मैं इस तरह खींचता हूं। आइटमपोशन उस आइटम का सूचकांक है जिसे चुना गया था।

(छोड़ते हुए अप्रासंगिक भागों)

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

समस्या है, mDragImage इस तरह एक ठोस काला है। A solid back bitmap

लेकिन, यदि मैं ListView को कुछ भी संभाल नहीं देता हूं। जैसा कि, मैं ACTION_DOWN पर ड्रैग शुरू करता हूं और ACTION_UP पर रोकता हूं, mDragImage दिखने की उम्मीद है (लेकिन मैं स्पष्ट रूप से स्क्रॉलिंग क्षमताओं को खो देता हूं)।

A good bitmap

के बाद से खींचें एक लंबे प्रेस के साथ शुरू होता है, ListView से पहले देर तक दबाए रखने होता है काम करने के लिए अवसर दिया जाता है। यह मेरा अनुमान है कि यह क्यों हो रहा है। जब कोई आइटम दबाया जाता है, तो इसे ListView द्वारा हाइलाइट किया जाता है। ऐसा करने में कहीं, यह बिटमैप के साथ गड़बड़ कर रहा है। तो जब मैं इसे पाने के लिए जाता हूं, यह एक अजीब स्थिति (सभी काला) में है।

मुझे इसे ठीक करने के लिए दो विकल्प दिखाई देते हैं, जिनमें से कोई भी मुझे नहीं पता कि कैसे करना है।

  1. स्क्रैच से एक छवि बनाएं।

  2. खुद को हाइलाइट करना (अगर यह समस्या है) को संभालें।

विकल्प दो मेरे लिए एक बेहतर प्रतीत होता है, सिवाय इसके कि मैंने प्रलेखन और स्रोत कोड को देखा और यह पता नहीं लगा कि ऐसा कैसे किया जाए। यहां कुछ चीजें हैं जिन्हें मैंने किया/कोशिश की है।

  • मैं एक खाली विधि (प्रकाश डाला अभी भी होता है) के साथ setOnItemClickListener(...) और setOnItemSelectedListener (...) की स्थापना की। (इससे पहले कि किसी को भी यह पता चलता है, बुला setOnClickListener परिणाम एक रनटाइम त्रुटि में।)

  • मैं भी एक नया आइटम (विकल्प 2 के लिए) बनाने के लिए ListView प्राप्त करने की कोशिश में देखा है, लेकिन एक तरह से नहीं मिल सका।

  • स्रोत कोड और दस्तावेज को देखकर 45ish मिनट बिताएं जहां यह हाइलाइटिंग हो रहा था (मुझे यह कभी नहीं मिला)।

इसकी सहायता करने में कोई भी सहायता की सराहना की जाएगी।

(EDIT1 स्टार्ट)

इसलिए मैं वास्तव में अगर onLongClickListener काम कर रहा है पता नहीं है, मैं सोच रहा था इससे पहले कि कोई त्रुटि की। मैं अभी इसे स्थापित करने की कोशिश कर रहा हूं, जब यह पता चलता है कि यह करता है तो अपडेट होगा।

(EDIT1 अंत) के बाद से पहले

अंतिम मिनट संपादित करें। मैंने अभी onLongClickListener का उपयोग करने का प्रयास किया है, और छवि अच्छी है। मैं अभी भी जानना चाहूंगा कि कोई और तरीका है या नहीं। काम करने के लिए मुझे लोंगक्लिक लिस्टनर पर कैसे उपयोग करना है बदसूरत है, लेकिन यह काम करता है। मैंने इसे समझने की कोशिश करने में इतना समय बिताया, जवाब का पता लगाना अच्छा लगेगा। मैं अभी भी हाइलाइट रंग को बदलने/संभालने में सक्षम होना चाहता हूं, डिफ़ॉल्ट नारंगी रंग सुंदर नहीं है। ओह और पोस्ट की लंबाई के बारे में खेद है। मैं इसे कम करने के तरीके के बारे में नहीं सोच सका, जबकि मुझे लगता था कि सारी जानकारी की आपूर्ति की जरूरत थी।

उत्तर

0

उपयोग इस कोड, यह आपरेशन दवा और ड्रॉप की अनुमति देता है 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; 
     } 

    } 
} 
संबंधित मुद्दे