2017-10-15 4 views
7

다른 크기의 셀 하나와 함께 끌어서 놓기 기능으로 gridview를 만들려고했습니다. 나는 그리드 드래그 앤 드랍과 그 잘 작동했다. 당신은 herecolspan 및 rowSpan이있는 GridView

my code output

의 코드를 확인하실 수 있습니다하지만 난 들고 뛰기 교체 될 다른 떨어지는 것 같이이처럼 순수하게 동적 싶은 desired output

+0

엇갈림 눈금 레이아웃을 살펴보십시오. 또한 리사이클 러 뷰를 사용할 수있는 경우 [this] (https://stackoverflow.com/questions/29457712/how-to-set-different-columns-for-rows-in-android-gridview)와 같은 것이 도움이 될 수 있습니다. –

+0

내 코드에는 UI 만 있으면 드래그 앤 드롭 기능이 있습니다. https://github.com/felipecsl/AsymmetricGridView와 같은 많은 옵션이 있습니다. – Furqan

+0

지식 게시와 관련하여 질문에 답변을 올리려는 경우. – AsifAli72090

답변

5

셀의 크기 조정을 수용 할 수있는 새로운 코드로 업데이트되었습니다. 귀하의 질문은 GridView을 의미하지만 제공된 코드는 GridView을 언급하지 않고 GridLayout을 대신 사용하므로 GridLayout이 올바른 레이아웃이라고 가정합니다.

하나의 2x2 타일로 조롱 된 레이아웃을 사용하여 데모를 작성했습니다. 2x2 타일을 수용하기 위해 제공 한 코드를 수정했습니다. 2x2 타일을 구현하기 위해 추가 한 코드 외에도 MainAcitivity에 대한 유일한 변경 사항은 다른 방법으로 (x, y) 위치에서 인덱스를 계산하는 calculateNextIndex 메서드에 대한 것입니다. 레이아웃과 LongPressListener 클래스도 제공되지 않았기 때문에 조롱을당했습니다. 여기

데모의 비디오입니다 :

enter image description here

MainActivity.java

public class MainActivity extends AppCompatActivity { 

    private static final int ITEMS = 10; 
    private GridLayout mGrid; 
    private ScrollView mScrollView; 
    private ValueAnimator mAnimator; 
    private Boolean isScroll = false; 
    private GridLayout.Spec m1xSpec = GridLayout.spec(GridLayout.UNDEFINED, 1); 
    private GridLayout.Spec m2xSpec = GridLayout.spec(GridLayout.UNDEFINED, 2); 
    private int mBaseWidth; 
    private int mBaseHeight; 
    private int mBaseMargin; 

    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mScrollView = (ScrollView) findViewById(R.id.scrollView); 
     mScrollView.setSmoothScrollingEnabled(true); 

     mGrid = (GridLayout) findViewById(R.id.grid); 

     mGrid.setOnDragListener(new DragListener()); 

     final LayoutInflater inflater = LayoutInflater.from(this); 

     GridLayout.LayoutParams lp; 

     DisplayMetrics displayMetrics = new DisplayMetrics(); 
     getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); 
     float dpiToPx = displayMetrics.density; 
     View view = inflater.inflate(R.layout.item, mGrid, false); 
     lp = (GridLayout.LayoutParams) view.getLayoutParams(); 
     mBaseWidth = lp.width; 
     mBaseHeight = lp.height; 
     mBaseMargin = lp.rightMargin; 

     for (int i = 0; i < ITEMS; i++) { 
      final View itemView = inflater.inflate(R.layout.item, mGrid, false); 
      final TextView text = (TextView) itemView.findViewById(R.id.text); 
      text.setText(String.valueOf(i + 1)); 
      itemView.setOnLongClickListener(new LongPressListener()); 
      lp = (i == 0) ? make2x2LayoutParams(itemView) : make1x1LayoutParams(itemView); 
      mGrid.addView(itemView, lp); 
     } 
    } 

    private GridLayout.LayoutParams make2x2LayoutParams(View view) { 
     GridLayout.LayoutParams lp = (GridLayout.LayoutParams) view.getLayoutParams(); 

     lp.width = mBaseWidth * 2 + 2 * mBaseMargin; 
     lp.height = mBaseHeight * 2 + 2 * mBaseMargin; 
     lp.rowSpec = m2xSpec; 
     lp.columnSpec = m2xSpec; 
     lp.setMargins(mBaseMargin, mBaseMargin, mBaseMargin, mBaseMargin); 
     return lp; 
    } 

    private GridLayout.LayoutParams make1x1LayoutParams(View view) { 
     GridLayout.LayoutParams lp = (GridLayout.LayoutParams) view.getLayoutParams(); 

     lp.width = mBaseWidth; 
     lp.height = mBaseHeight; 
     lp.setMargins(mBaseMargin, mBaseMargin, mBaseMargin, mBaseMargin); 
     lp.rowSpec = m1xSpec; 
     lp.columnSpec = m1xSpec; 
     return lp; 
    } 

    private int mDraggedIndex; 

    class DragListener implements View.OnDragListener { 
     @Override 
     public boolean onDrag(View v, DragEvent event) { 
      final View view = (View) event.getLocalState(); 
      int index = calculateNextIndex(event.getX(), event.getY()); 
      View child; 

      switch (event.getAction()) { 
       case DragEvent.ACTION_DRAG_STARTED: 
        mDraggedIndex = index; 
        break; 

       case DragEvent.ACTION_DRAG_LOCATION: 
        if (view == v) return true; 
        // get the new list index 


        final Rect rect = new Rect(); 
        mScrollView.getHitRect(rect); 
        final int scrollY = mScrollView.getScrollY(); 

        if (event.getY() - scrollY > mScrollView.getBottom() - 250) { 
         startScrolling(scrollY, mGrid.getHeight()); 
        } else if (event.getY() - scrollY < mScrollView.getTop() + 250) { 
         startScrolling(scrollY, 0); 
        } else { 
         stopScrolling(); 
        } 

        child = mGrid.getChildAt(0); 
        if (index == 0) { 
         child.setLayoutParams(make1x1LayoutParams(child)); 
         view.setLayoutParams(make2x2LayoutParams(view)); 
        } else if (mDraggedIndex == 0) { 
         view.setLayoutParams(make1x1LayoutParams(view)); 
         child.setLayoutParams(make2x2LayoutParams(child)); 
        } else { 
         child.setLayoutParams(make2x2LayoutParams(child)); 
         view.setLayoutParams(make1x1LayoutParams(view)); 
        } 
        mGrid.removeView(view); 
        mGrid.addView(view, index); 
        break; 
       case DragEvent.ACTION_DROP: 
        for (int i = 0; i < mGrid.getChildCount(); i++) { 
         child = mGrid.getChildAt(i); 
         child.setLayoutParams(make1x1LayoutParams(child)); 
        } 
        mGrid.removeView(view); 
        if (index == 0) { 
         view.setLayoutParams(make2x2LayoutParams(view)); 
        } 
        mGrid.addView(view, index); 
        view.setVisibility(View.VISIBLE); 
        mGrid.getChildAt(0).setLayoutParams(make2x2LayoutParams(mGrid.getChildAt(0))); 
        break; 
       case DragEvent.ACTION_DRAG_ENDED: 
        if (!event.getResult()) { 
         view.setVisibility(View.VISIBLE); 
        } 
        break; 
      } 
      return true; 
     } 
    } 

    private void startScrolling(int from, int to) { 
     if (from != to && mAnimator == null) { 
      isScroll = true; 
      mAnimator = new ValueAnimator(); 
      mAnimator.setInterpolator(new OvershootInterpolator()); 
      mAnimator.setDuration(Math.abs(to - from)); 
      mAnimator.setIntValues(from, to); 
      mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
       @Override 
       public void onAnimationUpdate(ValueAnimator valueAnimator) { 
        mScrollView.smoothScrollTo(0, (int) valueAnimator.getAnimatedValue()); 
       } 
      }); 
      mAnimator.addListener(new AnimatorListenerAdapter() { 
       @Override 
       public void onAnimationEnd(Animator animation) { 
        isScroll = false; 
        mAnimator = null; 
       } 
      }); 
      mAnimator.start(); 
     } 
    } 

    private void stopScrolling() { 
     if (mAnimator != null) { 
      mAnimator.cancel(); 
     } 
    } 

    private int calculateNextIndexOld(float x, float y) { 
     // calculate which column to move to 
     final float cellWidth = mGrid.getWidth()/mGrid.getColumnCount(); 
     final int column = (int) (x/cellWidth); 

     final float cellHeight = mGrid.getHeight()/mGrid.getRowCount(); 
     final int row = (int) Math.floor(y/cellHeight); 

     int index = row * mGrid.getColumnCount() + column; 
     if (index >= mGrid.getChildCount()) { 
      index = mGrid.getChildCount() - 1; 
     } 
     Log.d("MainActivity", "<<<<index=" + index); 
     return index; 
    } 

    private int calculateNextIndex(float x, float y) { 
     // calculate which column to move to 
     int index; 

     for (index = 0; index < mGrid.getChildCount(); index++) { 
      View child = mGrid.getChildAt(index); 
      Rect rect = new Rect(); 
      child.getHitRect(rect); 
      if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) { 
       break; 
      } 
     } 
     if (index >= mGrid.getChildCount()) { 
      // Move into empty cell? Calculate based upon uniform cell sizes. 
      index = calculateNextIndexOld(x, y); 
     } 
     if (index >= mGrid.getChildCount()) { 
      // Can't determine where to put it? Add it to the end. 
      index = mGrid.getChildCount() - 1; 
     } 
     return index; 
    } 
} 

당신이 데모와 함께 조금 작업하는 경우, 당신은 그것이 가능하다는 것을 볼 수 있습니다 1x1 타일 간격이 열리도록 타일을 이동시킵니다. 이 작업은 정상적으로 수행 될 수 있지만 그렇지 않은 경우 코드를 약간 수정해야 할 수 있습니다.

+0

프로그램에서 유일한 문제는 1 크기를 3 행으로 드래그하지 않는 것입니다. – Furqan

+0

@Furqan GridLayout은 3 열 × 5 행입니다. 3 행으로 드래그 할 때 기대하는 크기 조정에 대해서는 명확하지 않습니다. 더 설명해 주시겠습니까? – Cheticamp

+0

숫자 1을 임의의 위치로 드래그하면 숫자 1은 보통 크기로, 다른 숫자는 숫자가 더 큰 숫자로 바뀝니다. 즉, 위치 0에있는 숫자의 크기는 동일하게 유지되지만 다른 숫자는 0에 배치 될 때 크기를 조정할 수 있습니다. – Furqan