2014-10-19 77 views
2

嗨,我有ListView其中每個項目有不同的layout.and我想執行拖放這個listview.i搜索了很多例子和嘗試,但所有作品的字符串列表視圖或嘗試類似的東西,沒有任何工作listview的views.finally我決定去 DevBytes:ListView單元格拖動和重新排列此one.i實現dynaliclistview,但它崩潰,因爲這也使用字符串在listview.Following是我的列表視圖適配器拖放視圖列表視圖

public class ListViewPagerAdapter extends BaseAdapter { 

ViewPagerAdapter mViewPagerAdapter; 
private Context context; 
private int selectedIndex; 
    FragmentManager mFragmentManager; 
    static ViewPager vp; 
    LayoutInflater inflater; 
    private ArrayList<Integer> mContent; 
public ListViewPagerAdapter(Context context,FragmentManager fg) 
{ 
    super(); 
    this.context = context; 
    mFragmentManager = fg; 
} 

@Override 
public int getCount() { 

    return 4; 
} 

public void setSelectedIndex(int position) { 
    selectedIndex = position; 
    notifyDataSetChanged(); 
} 



@Override 
public long getItemId(int position) { 

    return position; 
} 



@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    // TODO Auto-generated method stub 
    if (convertView == null) { 

     inflater = (LayoutInflater) context 
       .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
     if(position==0) 
     { 
      convertView = inflater.inflate(R.layout.titlebar, null); 
     } 

    } 
    if(position==0) 
    { 
     convertView = inflater.inflate(R.layout.titlebar, null); 
    } 
    if(position==1) 
    {LayoutInflater inflater1 = (LayoutInflater) context 
    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
     convertView = inflater1.inflate(R.layout.calendarwidget_layout, null); 

    } 
    if(position==2) 
    { 
     LayoutInflater inflater2 = (LayoutInflater) context 
        .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
    convertView = inflater2.inflate(R.layout.view_pager_list_view, null); 
    vp = (ViewPager) convertView.findViewById(R.id.list_pager); 


    mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager); 
    vp.setAdapter(mViewPagerAdapter); 

    } 
    if(position==3) 
    { 
     LayoutInflater inflater2 = (LayoutInflater) context 
        .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
    convertView = inflater2.inflate(R.layout.view_pager_list_view, null); 
    vp = (ViewPager) convertView.findViewById(R.id.list_pager); 


    mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager); 
    vp.setAdapter(mViewPagerAdapter); 
    mViewPagerAdapter.notifyDataSetChanged(); 


    } 


    return convertView; 
} 

@Override 
public Object getItem(int position) { 
    // TODO Auto-generated method stub 
    return null; 
} 
} 

和下面是dynamiclisview代碼(與從提到的例子)

public class DynamicListView extends ListView { 

private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15; 
private final int MOVE_DURATION = 150; 
private final int LINE_THICKNESS = 15; 

public ArrayList<String> mCheeseList; 

private int mLastEventY = -1; 

private int mDownY = -1; 
private int mDownX = -1; 

private int mTotalOffset = 0; 

private boolean mCellIsMobile = false; 
private boolean mIsMobileScrolling = false; 
private int mSmoothScrollAmountAtEdge = 0; 

private final int INVALID_ID = -1; 
private long mAboveItemId = INVALID_ID; 
private long mMobileItemId = INVALID_ID; 
private long mBelowItemId = INVALID_ID; 

private BitmapDrawable mHoverCell; 
private Rect mHoverCellCurrentBounds; 
private Rect mHoverCellOriginalBounds; 

private final int INVALID_POINTER_ID = -1; 
private int mActivePointerId = INVALID_POINTER_ID; 

private boolean mIsWaitingForScrollFinish = false; 
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; 

public DynamicListView(Context context) { 
    super(context); 
    init(context); 
} 

public DynamicListView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    init(context); 
} 

public DynamicListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(context); 
} 

public void init(Context context) { 
    setOnItemLongClickListener(mOnItemLongClickListener); 
    setOnScrollListener(mScrollListener); 
    DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 
    mSmoothScrollAmountAtEdge = (int)(SMOOTH_SCROLL_AMOUNT_AT_EDGE/metrics.density); 
} 

/** 
* Listens for long clicks on any items in the listview. When a cell has 
* been selected, the hover cell is created and set up. 
*/ 
private AdapterView.OnItemLongClickListener mOnItemLongClickListener = 
     new AdapterView.OnItemLongClickListener() { 
      public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long id) { 
       mTotalOffset = 0; 

       int position = pointToPosition(mDownX, mDownY); 
       int itemNum = position - getFirstVisiblePosition(); 

       View selectedView = getChildAt(itemNum); 
       mMobileItemId = getAdapter().getItemId(position); 
       mHoverCell = getAndAddHoverView(selectedView); 
       selectedView.setVisibility(INVISIBLE); 

       mCellIsMobile = true; 

       updateNeighborViewsForID(mMobileItemId); 

       return true; 
      } 
     }; 

/** 
* Creates the hover cell with the appropriate bitmap and of appropriate 
* size. The hover cell's BitmapDrawable is drawn on top of the bitmap every 
* single time an invalidate call is made. 
*/ 
private BitmapDrawable getAndAddHoverView(View v) { 

    int w = v.getWidth(); 
    int h = v.getHeight(); 
    int top = v.getTop(); 
    int left = v.getLeft(); 

    Bitmap b = getBitmapWithBorder(v); 

    BitmapDrawable drawable = new BitmapDrawable(getResources(), b); 

    mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h); 
    mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds); 

    drawable.setBounds(mHoverCellCurrentBounds); 

    return drawable; 
} 

/** Draws a black border over the screenshot of the view passed in. */ 
private Bitmap getBitmapWithBorder(View v) { 
    Bitmap bitmap = getBitmapFromView(v); 
    Canvas can = new Canvas(bitmap); 

    Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 

    Paint paint = new Paint(); 
    paint.setStyle(Paint.Style.STROKE); 
    paint.setStrokeWidth(LINE_THICKNESS); 
    paint.setColor(Color.BLACK); 

    can.drawBitmap(bitmap, 0, 0, null); 
    can.drawRect(rect, paint); 

    return bitmap; 
} 

/** Returns a bitmap showing a screenshot of the view passed in. */ 
private Bitmap getBitmapFromView(View v) { 
    Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas (bitmap); 
    v.draw(canvas); 
    return bitmap; 
} 

/** 
* Stores a reference to the views above and below the item currently 
* corresponding to the hover cell. It is important to note that if this 
* item is either at the top or bottom of the list, mAboveItemId or mBelowItemId 
* may be invalid. 
*/ 
private void updateNeighborViewsForID(long itemID) { 
    int position = getPositionForID(itemID); 
    ListViewPagerAdapter adapter = ((ListViewPagerAdapter)getAdapter()); 
    mAboveItemId = adapter.getItemId(position - 1); 
    mBelowItemId = adapter.getItemId(position + 1); 
} 

/** Retrieves the view in the list corresponding to itemID */ 
public View getViewForID (long itemID) { 
    int firstVisiblePosition = getFirstVisiblePosition(); 
    ListViewPagerAdapter adapter = ((ListViewPagerAdapter)getAdapter()); 
    for(int i = 0; i < getChildCount(); i++) { 
     View v = getChildAt(i); 
     int position = firstVisiblePosition + i; 
     long id = adapter.getItemId(position); 
     if (id == itemID) { 
      return v; 
     } 
    } 
    return null; 
} 

/** Retrieves the position in the list corresponding to itemID */ 
public int getPositionForID (long itemID) { 
    View v = getViewForID(itemID); 
    if (v == null) { 
     return -1; 
    } else { 
     return getPositionForView(v); 
    } 
} 

/** 
* dispatchDraw gets invoked when all the child views are about to be drawn. 
* By overriding this method, the hover cell (BitmapDrawable) can be drawn 
* over the listview's items whenever the listview is redrawn. 
*/ 
@Override 
protected void dispatchDraw(Canvas canvas) { 
    super.dispatchDraw(canvas); 
    if (mHoverCell != null) { 
     mHoverCell.draw(canvas); 
    } 
} 

@Override 
public boolean onTouchEvent (MotionEvent event) { 

    switch (event.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: 
      mDownX = (int)event.getX(); 
      mDownY = (int)event.getY(); 
      mActivePointerId = event.getPointerId(0); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      if (mActivePointerId == INVALID_POINTER_ID) { 
       break; 
      } 

      int pointerIndex = event.findPointerIndex(mActivePointerId); 

      mLastEventY = (int) event.getY(pointerIndex); 
      int deltaY = mLastEventY - mDownY; 

      if (mCellIsMobile) { 
       mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, 
         mHoverCellOriginalBounds.top + deltaY + mTotalOffset); 
       mHoverCell.setBounds(mHoverCellCurrentBounds); 
       invalidate(); 

       handleCellSwitch(); 

       mIsMobileScrolling = false; 
       handleMobileCellScroll(); 

       return false; 
      } 
      break; 
     case MotionEvent.ACTION_UP: 
      touchEventsEnded(); 
      break; 
     case MotionEvent.ACTION_CANCEL: 
      touchEventsCancelled(); 
      break; 
     case MotionEvent.ACTION_POINTER_UP: 
      /* If a multitouch event took place and the original touch dictating 
      * the movement of the hover cell has ended, then the dragging event 
      * ends and the hover cell is animated to its corresponding position 
      * in the listview. */ 
      pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> 
        MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
      final int pointerId = event.getPointerId(pointerIndex); 
      if (pointerId == mActivePointerId) { 
       touchEventsEnded(); 
      } 
      break; 
     default: 
      break; 
    } 

    return super.onTouchEvent(event); 
} 

/** 
* This method determines whether the hover cell has been shifted far enough 
* to invoke a cell swap. If so, then the respective cell swap candidate is 
* determined and the data set is changed. Upon posting a notification of the 
* data set change, a layout is invoked to place the cells in the right place. 
* Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can 
* offset the cell being swapped to where it previously was and then animate it to 
* its new position. 
*/ 
private void handleCellSwitch() { 
    final int deltaY = mLastEventY - mDownY; 
    int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY; 

    View belowView = getViewForID(mBelowItemId); 
    View mobileView = getViewForID(mMobileItemId); 
    View aboveView = getViewForID(mAboveItemId); 

    boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop()); 
    boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop()); 

    if (isBelow || isAbove) { 

     final long switchItemID = isBelow ? mBelowItemId : mAboveItemId; 
     View switchView = isBelow ? belowView : aboveView; 
     final int originalItem = getPositionForView(mobileView); 

     if (switchView == null) { 
      updateNeighborViewsForID(mMobileItemId); 
      return; 
     } 

     swapElements(mCheeseList, originalItem, getPositionForView(switchView)); 

     ((BaseAdapter) getAdapter()).notifyDataSetChanged(); 

     mDownY = mLastEventY; 

     final int switchViewStartTop = switchView.getTop(); 

     mobileView.setVisibility(View.VISIBLE); 
     switchView.setVisibility(View.INVISIBLE); 

     updateNeighborViewsForID(mMobileItemId); 

     final ViewTreeObserver observer = getViewTreeObserver(); 
     observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 
      @SuppressLint("NewApi") 
      public boolean onPreDraw() { 
       observer.removeOnPreDrawListener(this); 

       View switchView = getViewForID(switchItemID); 

       mTotalOffset += deltaY; 

       int switchViewNewTop = switchView.getTop(); 
       int delta = switchViewStartTop - switchViewNewTop; 

       switchView.setTranslationY(delta); 

       ObjectAnimator animator = ObjectAnimator.ofFloat(switchView, 
         View.TRANSLATION_Y, 0); 
       animator.setDuration(MOVE_DURATION); 
       animator.start(); 

       return true; 
      } 
     }); 
    } 
} 

private void swapElements(ArrayList arrayList, int indexOne, int indexTwo) { 
    Object temp = arrayList.get(indexOne); 
    arrayList.set(indexOne, arrayList.get(indexTwo)); 
    arrayList.set(indexTwo, temp); 
} 


/** 
* Resets all the appropriate fields to a default state while also animating 
* the hover cell back to its correct location. 
*/ 
private void touchEventsEnded() { 
    final View mobileView = getViewForID(mMobileItemId); 
    if (mCellIsMobile|| mIsWaitingForScrollFinish) { 
     mCellIsMobile = false; 
     mIsWaitingForScrollFinish = false; 
     mIsMobileScrolling = false; 
     mActivePointerId = INVALID_POINTER_ID; 

     // If the autoscroller has not completed scrolling, we need to wait for it to 
     // finish in order to determine the final location of where the hover cell 
     // should be animated to. 
     if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) { 
      mIsWaitingForScrollFinish = true; 
      return; 
     } 

     mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop()); 

     ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds", 
       sBoundEvaluator, mHoverCellCurrentBounds); 
     hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
      @Override 
      public void onAnimationUpdate(ValueAnimator valueAnimator) { 
       invalidate(); 
      } 
     }); 
     hoverViewAnimator.addListener(new AnimatorListenerAdapter() { 
      @Override 
      public void onAnimationStart(Animator animation) { 
       setEnabled(false); 
      } 

      @Override 
      public void onAnimationEnd(Animator animation) { 
       mAboveItemId = INVALID_ID; 
       mMobileItemId = INVALID_ID; 
       mBelowItemId = INVALID_ID; 
       mobileView.setVisibility(VISIBLE); 
       mHoverCell = null; 
       setEnabled(true); 
       invalidate(); 
      } 
     }); 
     hoverViewAnimator.start(); 
    } else { 
     touchEventsCancelled(); 
    } 
} 

/** 
* Resets all the appropriate fields to a default state. 
*/ 
private void touchEventsCancelled() { 
    View mobileView = getViewForID(mMobileItemId); 
    if (mCellIsMobile) { 
     mAboveItemId = INVALID_ID; 
     mMobileItemId = INVALID_ID; 
     mBelowItemId = INVALID_ID; 
     mobileView.setVisibility(VISIBLE); 
     mHoverCell = null; 
     invalidate(); 
    } 
    mCellIsMobile = false; 
    mIsMobileScrolling = false; 
    mActivePointerId = INVALID_POINTER_ID; 
} 

/** 
* This TypeEvaluator is used to animate the BitmapDrawable back to its 
* final location when the user lifts his finger by modifying the 
* BitmapDrawable's bounds. 
*/ 
private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() { 
    public Rect evaluate(float fraction, Rect startValue, Rect endValue) { 
     return new Rect(interpolate(startValue.left, endValue.left, fraction), 
       interpolate(startValue.top, endValue.top, fraction), 
       interpolate(startValue.right, endValue.right, fraction), 
       interpolate(startValue.bottom, endValue.bottom, fraction)); 
    } 

    public int interpolate(int start, int end, float fraction) { 
     return (int)(start + fraction * (end - start)); 
    } 
}; 

/** 
* Determines whether this listview is in a scrolling state invoked 
* by the fact that the hover cell is out of the bounds of the listview; 
*/ 
private void handleMobileCellScroll() { 
    mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds); 
} 

/** 
* This method is in charge of determining if the hover cell is above 
* or below the bounds of the listview. If so, the listview does an appropriate 
* upward or downward smooth scroll so as to reveal new items. 
*/ 
public boolean handleMobileCellScroll(Rect r) { 
    int offset = computeVerticalScrollOffset(); 
    int height = getHeight(); 
    int extent = computeVerticalScrollExtent(); 
    int range = computeVerticalScrollRange(); 
    int hoverViewTop = r.top; 
    int hoverHeight = r.height(); 

    if (hoverViewTop <= 0 && offset > 0) { 
     smoothScrollBy(-mSmoothScrollAmountAtEdge, 0); 
     return true; 
    } 

    if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) { 
     smoothScrollBy(mSmoothScrollAmountAtEdge, 0); 
     return true; 
    } 

    return false; 
} 

public void setCheeseList(ArrayList<String> cheeseList) { 
    mCheeseList = cheeseList; 
} 

/** 
* This scroll listener is added to the listview in order to handle cell swapping 
* when the cell is either at the top or bottom edge of the listview. If the hover 
* cell is at either edge of the listview, the listview will begin scrolling. As 
* scrolling takes place, the listview continuously checks if new cells became visible 
* and determines whether they are potential candidates for a cell swap. 
*/ 
private AbsListView.OnScrollListener mScrollListener = new AbsListView.OnScrollListener() { 

    private int mPreviousFirstVisibleItem = -1; 
    private int mPreviousVisibleItemCount = -1; 
    private int mCurrentFirstVisibleItem; 
    private int mCurrentVisibleItemCount; 
    private int mCurrentScrollState; 

    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 
         int totalItemCount) { 
     mCurrentFirstVisibleItem = firstVisibleItem; 
     mCurrentVisibleItemCount = visibleItemCount; 

     mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem 
       : mPreviousFirstVisibleItem; 
     mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount 
       : mPreviousVisibleItemCount; 

     checkAndHandleFirstVisibleCellChange(); 
     checkAndHandleLastVisibleCellChange(); 

     mPreviousFirstVisibleItem = mCurrentFirstVisibleItem; 
     mPreviousVisibleItemCount = mCurrentVisibleItemCount; 
    } 

    @Override 
    public void onScrollStateChanged(AbsListView view, int scrollState) { 
     mCurrentScrollState = scrollState; 
     mScrollState = scrollState; 
     isScrollCompleted(); 
    } 

    /** 
    * This method is in charge of invoking 1 of 2 actions. Firstly, if the listview 
    * is in a state of scrolling invoked by the hover cell being outside the bounds 
    * of the listview, then this scrolling event is continued. Secondly, if the hover 
    * cell has already been released, this invokes the animation for the hover cell 
    * to return to its correct position after the listview has entered an idle scroll 
    * state. 
    */ 
    private void isScrollCompleted() { 
     if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) { 
      if (mCellIsMobile && mIsMobileScrolling) { 
       handleMobileCellScroll(); 
      } else if (mIsWaitingForScrollFinish) { 
       touchEventsEnded(); 
      } 
     } 
    } 

    /** 
    * Determines if the listview scrolled up enough to reveal a new cell at the 
    * top of the list. If so, then the appropriate parameters are updated. 
    */ 
    public void checkAndHandleFirstVisibleCellChange() { 
     if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) { 
      if (mCellIsMobile && mMobileItemId != INVALID_ID) { 
       updateNeighborViewsForID(mMobileItemId); 
       handleCellSwitch(); 
      } 
     } 
    } 

    /** 
    * Determines if the listview scrolled down enough to reveal a new cell at the 
    * bottom of the list. If so, then the appropriate parameters are updated. 
    */ 
    public void checkAndHandleLastVisibleCellChange() { 
     int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount; 
     int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount; 
     if (currentLastVisibleItem != previousLastVisibleItem) { 
      if (mCellIsMobile && mMobileItemId != INVALID_ID) { 
       updateNeighborViewsForID(mMobileItemId); 
       handleCellSwitch(); 
      } 
     } 
    } 
}; 

}

而且下面是list.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:paddingBottom="@dimen/activity_vertical_margin" 
android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
tools:context=".MainActivity" > 

<com.bin.widget.DynamicListView 
    android:id="@+id/campaignListView" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
       android:background="#0000" 
    > 
</com.bin.widget.DynamicListView> 

</RelativeLayout> 

請幫我...在此先感謝

回答

1

HI我終於解決了這個問題我自己,上面的代碼工作通過使在適配器類的listview中很少改變。在適配器的public long getItemId(int position)中進行必要的更改,以便它會給你傳遞職位id的id。不過只是返回position。另外,在listView的getView()方法中,在交換位置刷新listview之後的dynamicListview類中,我們需要做相應的更改。 就是這樣,那麼它就像魅力一樣。希望這可以幫助其他人。

+0

嗨,你可以請把你的答案在這裏或編輯你的問題與糾正的代碼?我需要它,因爲我一直在尋找相當長的時間,並沒有找到任何工作的例子。謝謝 – 2016-08-31 10:26:55