2017-10-15 33 views
7

Próbowałem zrobić gridview z funkcją przeciągania i upuszczania wraz z jedną komórką o różnej wielkości. Już sprawiłem, że kratka przeciągnęła się i opadła, a działa dobrze. można sprawdzić kod z hereGridView z colspan i rowSpan

my code output

ale chcę być taki jak ten i czysto dynamiczne jak będę przeciągnięcie i upuszczenie drugi, który zostanie zastąpiony i przeskalowane automatycznie desired output

+0

Przejrzeć rozłożoną strukturę siatki. Również jeśli możesz skorzystać z widoku recyklera, może ci pomóc coś w stylu [to] (https://stackoverflow.com/questions/29457712/how-to-set-different-columns-for-rows-in-android-gridview). –

+0

mój kod ma funkcję przeciągnij i upuść, jeśli jest to tylko interfejs użytkownika, mam wiele opcji, takich jak https://github.com/felipecsl/AsymmetricGridView – Furqan

+0

Jeśli promujesz post wiedzy, a także odpowiedź na pytanie. – AsifAli72090

Odpowiedz

5

Zaktualizowany nowym kodem, który umożliwia zmianę rozmiaru komórek. Twoje pytanie dotyczy GridView, ale podany przez Ciebie kod nie wspomina o GridView, ale zamiast tego używa GridLayout, więc zakładam, że GridLayout to właściwy układ.

Połączyłem demo z wykorzystaniem makiety z jedną płytką 2x2. Zmodyfikowałem kod, który podałeś, aby pomieścić kafelek 2x2. Poza kodem, który dodałem do implementacji płytki 2x2, jedyną inną zmianą w MainAcitivity była metoda calculateNextIndex, która wykorzystuje inny sposób obliczania indeksu w pozycji (x, y). Layouty i klasa LongPressListener również zostały wyśmiewane, ponieważ nie zostały dostarczone.

Oto film demo:

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; 
    } 
} 

Jeśli pracujesz z demo trochę, widać, że jest to możliwe aby przesunąć płytki w taki sposób, że zostanie otwarta szczelina kafelkowa 1x1. Może to być w porządku, ale kod może wymagać niewielkiej przeróbki, jeśli nie.

+0

Jedyny problem z twoim programem to 1 nie zmienia rozmiaru, przeciągnij go do trzeciego wiersza. – Furqan

+0

@Furqan GridLayout ma 3 kolumny po 5 rzędów. Nie mam jasności co do zmiany rozmiaru, której oczekujesz po przeciągnięciu do trzeciego wiersza. Czy możesz wyjaśnić dalej? – Cheticamp

+0

Mam na myśli, że po przeciągnięciu numeru 1 do dowolnej pozycji, numer 1 powinien zmienić rozmiar na normalny, a drugi numer zastąpić pozycję numeru, zmienić rozmiar na większy. W skrócie wielkość numeru w pozycji 0 pozostaje taka sama, ale inne liczby mogą dostosować rozmiar, gdy zostaną umieszczone na 0. – Furqan