I have been trying to make a gridview with drag and drop functionality along with one cell of different size. I have already made the the grid drag and drop and its working fine. you can check the code from here
but I want it to be like this and purely dynamic as I will be draging and dropping the other which will be replaced and resized automatically
2 Answers
Answers 1
Your question refers to GridView
but the code you supplied doesn't mention GridView
but uses GridLayout
instead, so I am assuming that GridLayout
is the right layout.
I have put together a demo using a mocked-up layout with one 2x2 tile. I have modified the code that you have supplied to accommodate the 2x2 tile. Other than the code that I added to implement the 2x2 tile, the only other change to MainAcitivity was to the calculateNextIndex
method that uses a different way of calculating the index at an (x, y) position. Layouts and the LongPressListener class were also mocked up since they were not supplied.
Here is a video of the demo:
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; @Override 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 = new GridLayout.LayoutParams(); lp.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, 2); lp.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 2); DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); float dpiToPx = displayMetrics.density; 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()); if (i == 0) { // Setup 2x2 tile for demo purposes. lp.width = (int) (127 * 2 * dpiToPx); lp.height = (int) (102 * 2 * dpiToPx); int margin = (int) (2 * dpiToPx); lp.setMargins(margin, margin, margin, margin); itemView.setLayoutParams(lp); } mGrid.addView(itemView); } } class DragListener implements View.OnDragListener { @Override public boolean onDrag(View v, DragEvent event) { final View view = (View) event.getLocalState(); switch (event.getAction()) { case DragEvent.ACTION_DRAG_LOCATION: if (view == v) return true; // get the new list index final int index = calculateNextIndex(event.getX(), event.getY()); 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(); } // remove the view from the old position mGrid.removeView(view); //add new view mGrid.addView(view, index); break; case DragEvent.ACTION_DROP: view.setVisibility(View.VISIBLE); 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; } }
activity_main.xml
<ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="wrap_content" android:fillViewport="true" android:fitsSystemWindows="true"> <GridLayout android:id="@+id/grid" android:layout_width="match_parent" android:layout_height="match_parent" android:columnCount="3" android:orientation="horizontal" android:rowCount="5" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </ScrollView>
item.xml
<TextView android:id="@+id/text" android:layout_width="125dp" android:layout_height="100dp" android:background="@android:color/darker_gray" android:gravity="center" android:layout_margin="2dp" android:textColor="@android:color/black" android:textSize="36sp" tools:text="88"> </TextView>
LongPressListener.java - original listener was not supplied, so the following was substituted for the demo.
public class LongPressListener implements View.OnLongClickListener { public boolean onLongClick(View view) { ClipData data = ClipData.newPlainText("", ""); View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder( view); view.startDrag(data, shadowBuilder, view, 0); view.setVisibility(View.INVISIBLE); return true; } }
If you work with the demo a little, you will see that it is possible to move tiles such that a 1x1 tile gap is opened up. This may be OK, but the code may need to be reworked a little if not.
0 comments:
Post a Comment